🔥 Remove external packages for unity

This commit is contained in:
Manuel Cillero 2024-04-12 21:41:53 +02:00
parent 4ea28030c7
commit 4b1e34487d
59 changed files with 3 additions and 1905 deletions

View file

@ -18,12 +18,12 @@ keywords = [
"pagetop", "web", "framework", "frontend", "ssr"
]
exclude = [
"drust/", "examples/", "helpers/", "packages/", "tests/"
"examples/", "helpers/", "tests/"
]
rust-version = "1.70.0"
[workspace]
members = ["drust", "helpers/*", "packages/*"]
members = ["helpers/*"]
[lib]
name = "pagetop"
@ -72,9 +72,6 @@ serde = { version = "1.0", features = ["derive"] }
version = "0.3.30"
optional = true
[dependencies.heck]
version = "0.4.1"
[dependencies.sea-orm]
version = "0.12.15"
features = ["debug-print", "macros", "runtime-async-std-native-tls"]

View file

@ -57,19 +57,7 @@ This program features a `HelloWorld` package, providing a service that serves a
accessible via `http://localhost:8088` under default settings.
# 📂 Repository Structure
This repository is organized into a workspace that includes several subprojects, each serving a
distinct role within the PageTop ecosystem:
## Application
* [drust](https://github.com/manuelcillero/pagetop/tree/latest/drust):
A simple Content Management System (CMS) built on PageTop, which enables the creation, editing,
and maintenance of dynamic, fast, and modular websites. It uses the following essential packages
to provide standard CMS functionalities.
## Helpers
# 📂 Helpers
* [pagetop-macros](https://github.com/manuelcillero/pagetop/tree/latest/helpers/pagetop-macros):
A collection of procedural macros that enhance the development experience within PageTop.
@ -77,27 +65,6 @@ distinct role within the PageTop ecosystem:
* [pagetop-build](https://github.com/manuelcillero/pagetop/tree/latest/helpers/pagetop-build):
Simplifies the process of embedding resources directly into binary files for PageTop applications.
## Packages
* [pagetop-user](https://github.com/manuelcillero/pagetop/tree/latest/packages/pagetop-user):
Facilitates user management, including roles, permissions, and session handling, for applications
built on PageTop.
* [pagetop-admin](https://github.com/manuelcillero/pagetop/tree/latest/packages/pagetop-admin):
Provides a unified interface for administrators to configure and manage package settings.
* [pagetop-node](https://github.com/manuelcillero/pagetop/tree/latest/packages/pagetop-node):
Enables the creation and customization of content types, enhancing website content management.
## Themes
* [pagetop-bootsier](https://github.com/manuelcillero/pagetop/tree/latest/packages/pagetop-bootsier):
Utilizes the *[Bootstrap](https://getbootstrap.com/)* framework to offer versatile page layouts
and component stylings.
* [pagetop-bulmix](https://github.com/manuelcillero/pagetop/tree/latest/packages/pagetop-bulmix):
Utilizes the *[Bulma](https://bulma.io/)* framework for sleek, responsive design elements.
# 🚧 Warning

View file

@ -1,23 +0,0 @@
[package]
name = "drust"
version = "0.0.3"
edition = "2021"
description = "A modern web Content Management System to share your world."
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "MIT OR Apache-2.0"
authors = [
"Manuel Cillero <manuel@cillero.es>"
]
[dependencies]
pagetop = { version = "0.0", path = "../", features = ["mysql"], default-features = false }
# Packages.
pagetop-admin = { version = "0.0", path = "../packages/pagetop-admin" }
pagetop-user = { version = "0.0", path = "../packages/pagetop-user" }
pagetop-node = { version = "0.0", path = "../packages/pagetop-node" }
# Themes.
pagetop-bootsier = { version = "0.0", path = "../packages/pagetop-bootsier" }
pagetop-bulmix = { version = "0.0", path = "../packages/pagetop-bulmix" }

View file

@ -1,37 +0,0 @@
<div align="center">
<h1>Drust</h1>
<p>A Content Management System built on PageTop.</p>
</div>
## Overview
Modestly inspired by [Drupal](https://www.drupal.org), **Drust** utilizes **PageTop** to develop a
CMS (*Content Management System*). It enables the creation of dynamic, manageable, and customizable
websites, allowing users to effortlessly create, manage, and organize a wide variety of content on a
website.
# 📦 About PageTop
[PageTop](https://docs.rs/pagetop) is an opinionated web framework to build modular *Server-Side
Rendering* web solutions.
# 🚧 Warning
**PageTop** framework is currently in active development. The API is unstable and subject to
frequent changes. Production use is not recommended until version **0.1.0**.
# 📜 License
All code in this project is dual-licensed under either:
* MIT License
([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
* Apache License, Version 2.0,
([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is
the de-facto standard in the Rust ecosystem.

View file

@ -1,8 +0,0 @@
[app]
name = "Drust"
description = """\
A modern web Content Management System to share your world.\
"""
[database]
db_type = "mysql"

View file

@ -1,10 +0,0 @@
[app]
#theme = "Basic"
#theme = "Chassis"
theme = "Inception"
#theme = "Bootsier"
#theme = "Bulmix"
language = "es-ES"
[log]
tracing = "Info,pagetop=Debug,sqlx::query=Warn"

View file

@ -1,28 +0,0 @@
use pagetop::prelude::*;
struct Drust;
impl PackageTrait for Drust {
fn dependencies(&self) -> Vec<PackageRef> {
vec![
// Packages.
&pagetop_admin::Admin,
&pagetop_user::User,
&pagetop_node::Node,
// Themes.
&pagetop_bootsier::Bootsier,
&pagetop_bulmix::Bulmix,
]
}
fn drop_packages(&self) -> Vec<PackageRef> {
vec![
// &pagetop_node::Node
]
}
}
#[pagetop::main]
async fn main() -> std::io::Result<()> {
Application::prepare(&Drust).run()?.await
}

View file

@ -1,22 +0,0 @@
[package]
name = "pagetop-admin"
version = "0.0.21"
edition = "2021"
description = "PageTop package that provides a unified settings interface to other packages."
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "MIT OR Apache-2.0"
authors = [
"Manuel Cillero <manuel@cillero.es>"
]
categories = [
"web-programming", "gui"
]
keywords = [
"pagetop", "admin", "config", "settings", "packages"
]
[dependencies]
pagetop = { version = "0.0", path = "../../" }

View file

@ -1,37 +0,0 @@
<div align="center">
<h1>PageTop Admin</h1>
<p>PageTop package that provides a unified settings interface to other packages.</p>
[![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](#-license)
[![API Docs](https://img.shields.io/docsrs/pagetop-admin?label=API%20Docs&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-admin)
[![Crates.io](https://img.shields.io/crates/v/pagetop-admin.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-admin)
[![Downloads](https://img.shields.io/crates/d/pagetop-admin.svg?style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-admin)
</div>
# 📦 About PageTop
[PageTop](https://docs.rs/pagetop) is an opinionated web framework to build modular *Server-Side
Rendering* web solutions.
# 🚧 Warning
**PageTop** framework is currently in active development. The API is unstable and subject to
frequent changes. Production use is not recommended until version **0.1.0**.
# 📜 License
All code in this crate is dual-licensed under either:
* MIT License
([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
* Apache License, Version 2.0,
([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is
the de-facto standard in the Rust ecosystem.

View file

@ -1,39 +0,0 @@
use pagetop::prelude::*;
static_locales!(LOCALES_ADMIN);
mod summary;
pub struct Admin;
impl PackageTrait for Admin {
fn name(&self) -> L10n {
L10n::t("package_name", &LOCALES_ADMIN)
}
fn description(&self) -> L10n {
L10n::t("package_description", &LOCALES_ADMIN)
}
fn actions(&self) -> Vec<ActionBox> {
actions![
action::page::BeforePrepareBody::new(before_prepare_body),
action::component::BeforePrepare::<Menu>::new(before_prepare_menu)
.filter_by_referer_id("admin-menu-test"),
]
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
scfg.service(
service::web::scope("/admin").route("", service::web::get().to(summary::summary)),
);
}
}
fn before_prepare_body(page: &mut Page) {
page.alter_body_classes(ClassesOp::Add, "test-admin");
}
fn before_prepare_menu(component: &mut Menu, _cx: &mut Context) {
component.alter_id("admin-menu-test-altered");
}

View file

@ -1,2 +0,0 @@
package_name = Admin module
package_description = Administration module.

View file

@ -1,2 +0,0 @@
package_name = Admin module
package_description = Módulo de administración.

View file

@ -1,163 +0,0 @@
use crate::LOCALES_ADMIN;
use pagetop::prelude::*;
pub async fn summary(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
let top_menu = Menu::new()
.with_id("admin-menu-test")
.add_item(menu::Item::label(L10n::t("package_name", &LOCALES_ADMIN)))
.add_item(menu::Item::label(L10n::n("Ejemplo \"Label\"")))
.add_item(menu::Item::link(L10n::n("Ejemplo \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Ejemplo \"LinkBlank\""),
|_| "https://www.google.es",
))
.add_item(menu::Item::submenu(
L10n::n("Ejemplo Submenú"),
menu::Submenu::new()
.with_title(L10n::n("Título submenú"))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
))
.add_item(menu::Item::submenu(
L10n::n("Otro submenú con un texto muy, pero que muy largo"),
menu::Submenu::new()
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
))
.add_item(menu::Item::label(L10n::n("Opción \"Label\""))),
))
.add_item(menu::Item::label(L10n::n("Opción \"Label\""))),
))
.add_item(menu::Item::megamenu(
L10n::n("Ejemplo Megamenú 1"),
menu::Megamenu::new()
.add_group(
menu::Group::new()
.add_element(menu::Element::submenu(
menu::Submenu::new()
.with_title(L10n::n("Título submenú"))
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
)),
))
.add_element(menu::Element::submenu(
menu::Submenu::new()
.with_title(L10n::n("Título submenú"))
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
)),
)),
)
.add_group(
menu::Group::new().add_element(menu::Element::submenu(
menu::Submenu::new()
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
))
.add_item(menu::Item::label(L10n::n("Opción \"Label\""))),
)),
)
.add_group(
menu::Group::new()
.add_element(menu::Element::submenu(
menu::Submenu::new()
.with_title(L10n::n("Título submenú"))
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
)),
))
.add_element(menu::Element::submenu(
menu::Submenu::new()
.with_title(L10n::n("Título submenú"))
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
)),
)),
)
.add_group(
menu::Group::new().add_element(menu::Element::submenu(
menu::Submenu::new()
.add_item(menu::Item::label(L10n::n("Opción \"Label\"")))
.add_item(menu::Item::link(L10n::n("Opción \"Link\""), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(
L10n::n("Opción \"LinkBlank\""),
|_| "https://www.google.es",
))
.add_item(menu::Item::label(L10n::n("Opción \"Label\""))),
)),
),
));
let side_menu = Menu::new()
.add_item(menu::Item::label(L10n::n("Opción 1")))
.add_item(menu::Item::link(L10n::n("Opción 2"), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::link_blank(L10n::n("Opción 3"), |_| {
"https://www.google.es"
}))
.add_item(menu::Item::submenu(
L10n::n("Submenú 1"),
menu::Submenu::new()
.add_item(menu::Item::label(L10n::n("Opción 1")))
.add_item(menu::Item::label(L10n::n("Opción 2"))),
)) /*
.add_item(menu::Item::separator()) */
.add_item(menu::Item::submenu(
L10n::n("Submenú 2"),
menu::Submenu::new()
.add_item(menu::Item::label(L10n::n("Opción 1")))
.add_item(menu::Item::label(L10n::n("Opción 2"))),
))
.add_item(menu::Item::label(L10n::n("Opción 4")));
Page::new(request)
.with_title(L10n::n("Admin"))
.with_component_in("top-menu", side_menu)
.with_component(
flex::Container::new()
.add_item(flex::Item::with(Html::with(html! { p { "Columna 1"} })))
.add_item(flex::Item::with(top_menu))
.add_item(flex::Item::with(Html::with(html! { p { "Columna 3"} }))),
)
.render()
}

View file

@ -1,26 +0,0 @@
[package]
name = "pagetop-bootsier"
version = "0.0.18"
edition = "2021"
description = "PageTop theme that uses Bootstrap framework for versatile styles and components."
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "MIT OR Apache-2.0"
authors = [
"Manuel Cillero <manuel@cillero.es>"
]
categories = [
"web-programming", "gui"
]
keywords = [
"pagetop", "theme", "bootstrap", "css", "js"
]
[dependencies]
pagetop = { version = "0.0", path = "../../" }
static-files = "0.2.3"
[build-dependencies]
pagetop-build = { version = "0.0", path = "../../helpers/pagetop-build" }

View file

@ -1,37 +0,0 @@
<div align="center">
<h1>PageTop Bootsier</h1>
<p>PageTop theme that uses Bootstrap framework for versatile styles and components.</p>
[![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](#-license)
[![API Docs](https://img.shields.io/docsrs/pagetop-bootsier?label=API%20Docs&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-bootsier)
[![Crates.io](https://img.shields.io/crates/v/pagetop-bootsier.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-bootsier)
[![Downloads](https://img.shields.io/crates/d/pagetop-bootsier.svg?style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-bootsier)
</div>
# 📦 About PageTop
[PageTop](https://docs.rs/pagetop) is an opinionated web framework to build modular *Server-Side
Rendering* web solutions.
# 🚧 Warning
**PageTop** framework is currently in active development. The API is unstable and subject to
frequent changes. Production use is not recommended until version **0.1.0**.
# 📜 License
All code in this crate is dual-licensed under either:
* MIT License
([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
* Apache License, Version 2.0,
([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is
the de-facto standard in the Rust ecosystem.

View file

@ -1,7 +0,0 @@
use pagetop_build::StaticFilesBundle;
fn main() -> std::io::Result<()> {
StaticFilesBundle::from_dir("./static")
.with_name("bootsier")
.build()
}

View file

@ -1,179 +0,0 @@
use pagetop::prelude::*;
static_locales!(LOCALES_BOOTSIER);
static_files!(bootsier);
pub struct Bootsier;
impl PackageTrait for Bootsier {
fn theme(&self) -> Option<ThemeRef> {
Some(&Bootsier)
}
fn actions(&self) -> Vec<ActionBox> {
actions![
action::theme::BeforePrepare::<Icon>::new(&Self, before_prepare_icon),
action::theme::BeforePrepare::<Button>::new(&Self, before_prepare_button),
action::theme::BeforePrepare::<Heading>::new(&Self, before_prepare_heading),
action::theme::BeforePrepare::<Paragraph>::new(&Self, before_prepare_paragraph),
action::theme::RenderComponent::<Error404>::new(&Self, render_error404),
]
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
service_for_static_files!(scfg, bootsier => "/bootsier");
}
}
impl ThemeTrait for Bootsier {
#[rustfmt::skip]
fn regions(&self) -> Vec<(&'static str, L10n)> {
vec![
("header", L10n::t("header", &LOCALES_BOOTSIER)),
("nav_branding", L10n::t("nav_branding", &LOCALES_BOOTSIER)),
("nav_main", L10n::t("nav_main", &LOCALES_BOOTSIER)),
("nav_additional", L10n::t("nav_additional", &LOCALES_BOOTSIER)),
("breadcrumb", L10n::t("breadcrumb", &LOCALES_BOOTSIER)),
("content", L10n::t("breadcrumb", &LOCALES_BOOTSIER)),
("sidebar_first", L10n::t("sidebar_first", &LOCALES_BOOTSIER)),
("sidebar_second", L10n::t("sidebar_second", &LOCALES_BOOTSIER)),
("footer", L10n::t("footer", &LOCALES_BOOTSIER)),
]
}
fn prepare_body(&self, page: &mut Page) -> Markup {
Body::with(match page.context().layout() {
"admin" => flex::Container::new()
.add_item(flex::Item::region().with_id("top-menu"))
.add_item(flex::Item::region().with_id("side-menu"))
.add_item(flex::Item::region().with_id("content")),
_ => flex::Container::new()
.add_item(flex::Item::region().with_id("header"))
.add_item(flex::Item::region().with_id("nav_branding"))
.add_item(flex::Item::region().with_id("nav_main"))
.add_item(flex::Item::region().with_id("nav_additional"))
.add_item(flex::Item::region().with_id("breadcrumb"))
.add_item(flex::Item::region().with_id("content"))
.add_item(flex::Item::region().with_id("sidebar_first"))
.add_item(flex::Item::region().with_id("sidebar_second"))
.add_item(flex::Item::region().with_id("footer")),
})
.render(page.context())
}
fn after_prepare_body(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/base/favicon.ico")))
.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::at("/bootsier/css/bootstrap.min.css")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_assets(AssetsOp::AddJavaScript(
JavaScript::at("/bootsier/js/bootstrap.bundle.min.js")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_assets(AssetsOp::AddBaseAssets)
.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::at("/bootsier/css/styles.css").with_version("0.0.1"),
));
}
}
fn before_prepare_icon(i: &mut Icon, _cx: &mut Context) {
i.alter_classes(
ClassesOp::Replace(i.font_size().to_string()),
with_font(i.font_size()),
);
}
#[rustfmt::skip]
fn before_prepare_button(b: &mut Button, _cx: &mut Context) {
b.alter_classes(ClassesOp::Replace("button__tap".to_owned()), "btn");
b.alter_classes(
ClassesOp::Replace(b.style().to_string()),
match b.style() {
StyleBase::Default => "btn-primary",
StyleBase::Info => "btn-info",
StyleBase::Success => "btn-success",
StyleBase::Warning => "btn-warning",
StyleBase::Danger => "btn-danger",
StyleBase::Light => "btn-light",
StyleBase::Dark => "btn-dark",
StyleBase::Link => "btn-link",
},
);
b.alter_classes(
ClassesOp::Replace(b.font_size().to_string()),
with_font(b.font_size()),
);
}
#[rustfmt::skip]
fn before_prepare_heading(h: &mut Heading, _cx: &mut Context) {
h.alter_classes(
ClassesOp::Replace(h.size().to_string()),
match h.size() {
HeadingSize::ExtraLarge => "display-1",
HeadingSize::XxLarge => "display-2",
HeadingSize::XLarge => "display-3",
HeadingSize::Large => "display-4",
HeadingSize::Medium => "display-5",
_ => "",
},
);
}
fn before_prepare_paragraph(p: &mut Paragraph, _cx: &mut Context) {
p.alter_classes(
ClassesOp::Replace(p.font_size().to_string()),
with_font(p.font_size()),
);
}
fn render_error404(_: &Error404, cx: &mut Context) -> Option<Markup> {
Some(html! {
div class="jumbotron" {
div class="media" {
img
src="/bootsier/images/caution.png"
class="mr-4"
style="width: 20%; max-width: 188px"
alt="Caution!";
div class="media-body" {
h1 class="display-4" { ("RESOURCE NOT FOUND") }
p class="lead" {
(L10n::t("e404-description", &LOCALES_BOOTSIER)
.escaped(cx.langid()))
}
hr class="my-4";
p {
(L10n::t("e404-description", &LOCALES_BOOTSIER)
.escaped(cx.langid()))
}
a
class="btn btn-primary btn-lg"
href="/"
role="button"
{
(L10n::t("back-homepage", &LOCALES_BOOTSIER)
.escaped(cx.langid()))
}
}
}
}
})
}
#[rustfmt::skip]
fn with_font(font_size: &FontSize) -> String {
String::from(match font_size {
FontSize::ExtraLarge => "fs-1",
FontSize::XxLarge => "fs-2",
FontSize::XLarge => "fs-3",
FontSize::Large => "fs-4",
FontSize::Medium => "fs-5",
_ => "",
})
}

View file

@ -1,6 +0,0 @@
e404-description = Oops! Page Not Found
e404-message = The page you are looking for may have been removed, had its name changed, or is temporarily unavailable.
e500-description = Oops! Unexpected Error
e500-message = We're having an issue. Please report this error to an administrator.
back-homepage = Back to homepage

View file

@ -1,9 +0,0 @@
header = Header
nav_branding = Navigation branding region
nav_main = Main navigation region
nav_additional = Additional navigation region (eg search form, social icons, etc)
breadcrumb = Breadcrumb
content = Main content
sidebar_first = Sidebar first
sidebar_second = Sidebar second
footer = Footer

View file

@ -1,5 +0,0 @@
e404-description = ¡Vaya! Página No Encontrada
e404-message = La página que está buscando puede haber sido eliminada, cambiada de nombre o no está disponible temporalmente.
e500-description = ¡Vaya! Error Inesperado
e500-message = Está ocurriendo una incidencia. Por favor, informe de este error a un administrador.
back-homepage = Volver al inicio

View file

@ -1,9 +0,0 @@
header = Cabecera
nav_branding = Navegación y marca
nav_main = Navegación principal
nav_additional = Navegación adicional (p.e. formulario de búsqueda, iconos sociales, etc.)
breadcrumb = Ruta de posicionamiento
content = Contenido principal
sidebar_first = Barra lateral primera
sidebar_second = Barra lateral segunda
footer = Pie

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,13 +0,0 @@
/* OVERRIDE COMPONENT STYLES */
/* Heading component */
.heading__subtitle {
margin-top: calc(-1 * var(--val-gap-0-35));
}
/* Button component */
.btn > span {
margin: 0 var(--val-gap-0-5);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,26 +0,0 @@
[package]
name = "pagetop-bulmix"
version = "0.0.17"
edition = "2021"
description = "PageTop theme that uses the Bulma framework for sleek, responsive design elements."
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "MIT OR Apache-2.0"
authors = [
"Manuel Cillero <manuel@cillero.es>"
]
categories = [
"web-programming", "gui"
]
keywords = [
"pagetop", "theme", "bulma", "css", "js"
]
[dependencies]
pagetop = { version = "0.0", path = "../../" }
static-files = "0.2.3"
[build-dependencies]
pagetop-build = { version = "0.0", path = "../../helpers/pagetop-build" }

View file

@ -1,37 +0,0 @@
<div align="center">
<h1>PageTop Bulmix</h1>
<p>PageTop theme that uses the Bulma framework for sleek, responsive design elements.</p>
[![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](#-license)
[![API Docs](https://img.shields.io/docsrs/pagetop-bulmix?label=API%20Docs&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-bulmix)
[![Crates.io](https://img.shields.io/crates/v/pagetop-bulmix.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-bulmix)
[![Downloads](https://img.shields.io/crates/d/pagetop-bulmix.svg?style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-bulmix)
</div>
# 📦 About PageTop
[PageTop](https://docs.rs/pagetop) is an opinionated web framework to build modular *Server-Side
Rendering* web solutions.
# 🚧 Warning
**PageTop** framework is currently in active development. The API is unstable and subject to
frequent changes. Production use is not recommended until version **0.1.0**.
# 📜 License
All code in this crate is dual-licensed under either:
* MIT License
([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
* Apache License, Version 2.0,
([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is
the de-facto standard in the Rust ecosystem.

View file

@ -1,7 +0,0 @@
use pagetop_build::StaticFilesBundle;
fn main() -> std::io::Result<()> {
StaticFilesBundle::from_dir("./static")
.with_name("bulmix")
.build()
}

View file

@ -1,117 +0,0 @@
use pagetop::prelude::*;
static_files!(bulmix);
pub struct Bulmix;
impl PackageTrait for Bulmix {
fn theme(&self) -> Option<ThemeRef> {
Some(&Bulmix)
}
fn actions(&self) -> Vec<ActionBox> {
actions![
action::theme::BeforePrepare::<Icon>::new(&Self, before_prepare_icon),
action::theme::BeforePrepare::<Button>::new(&Self, before_prepare_button),
action::theme::BeforePrepare::<Heading>::new(&Self, before_prepare_heading),
action::theme::BeforePrepare::<Paragraph>::new(&Self, before_prepare_paragraph),
action::theme::RenderComponent::<Icon>::new(&Self, render_icon),
]
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
service_for_static_files!(scfg, bulmix => "/bulmix");
}
}
impl ThemeTrait for Bulmix {
/*
#[rustfmt::skip]
fn builtin_classes(&self, builtin: ThemeBuiltInClasses) -> Option<String> {
match builtin {
ThemeBuiltInClasses::BodyWrapper => Some(String::from("container")),
ThemeBuiltInClasses::FlexWrapper => Some(String::from("container")),
ThemeBuiltInClasses::RegionContainer => Some(String::from("container")),
_ => Some(builtin.to_string()),
}
}
*/
fn after_prepare_body(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/base/favicon.ico")))
.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::at("/bulmix/css/bulma.min.css")
.with_version("0.9.4")
.with_weight(-99),
))
.alter_assets(AssetsOp::AddBaseAssets)
.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::at("/bulmix/css/styles.css").with_version("0.0.1"),
));
}
}
fn before_prepare_icon(i: &mut Icon, _cx: &mut Context) {
i.alter_classes(
ClassesOp::Replace(i.font_size().to_string()),
with_font(i.font_size()),
);
}
#[rustfmt::skip]
fn before_prepare_button(b: &mut Button, _cx: &mut Context) {
b.alter_classes(ClassesOp::Replace("button__tap".to_owned()), "button");
b.alter_classes(
ClassesOp::Replace(b.style().to_string()),
match b.style() {
StyleBase::Default => "is-primary",
StyleBase::Info => "is-info",
StyleBase::Success => "is-success",
StyleBase::Warning => "is-warning",
StyleBase::Danger => "is-danger",
StyleBase::Light => "is-light",
StyleBase::Dark => "is-dark",
StyleBase::Link => "is-text",
},
);
b.alter_classes(
ClassesOp::Replace(b.font_size().to_string()),
with_font(b.font_size()),
);
}
#[rustfmt::skip]
fn before_prepare_heading(h: &mut Heading, _cx: &mut Context) {
match h.size() {
HeadingSize::Subtitle => {
h.alter_classes(ClassesOp::Replace(h.size().to_string()), "subtitle")
}
_ => h.alter_classes(ClassesOp::Add, "title"),
};
}
fn before_prepare_paragraph(p: &mut Paragraph, _cx: &mut Context) {
p.alter_classes(ClassesOp::Add, "block");
p.alter_classes(
ClassesOp::Replace(p.font_size().to_string()),
with_font(p.font_size()),
);
}
fn render_icon(i: &Icon, _cx: &mut Context) -> Option<Markup> {
return match i.icon_name().get() {
None => None,
_ => Some(html! { span class="icon" { i class=[i.classes().get()] {} } }),
};
}
#[rustfmt::skip]
fn with_font(font_size: &FontSize) -> String {
String::from(match font_size {
FontSize::ExtraLarge => "is-size-1",
FontSize::XxLarge => "is-size-2",
FontSize::XLarge => "is-size-3",
FontSize::Large => "is-size-4",
FontSize::Medium => "is-size-5",
_ => "",
})
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,11 +0,0 @@
html {
scroll-behavior: smooth;
}
/* OVERRIDE COMPONENT STYLES */
/* Button component */
.is-link {
text-decoration: none;
}

View file

@ -1,22 +0,0 @@
[package]
name = "pagetop-node"
version = "0.0.20"
edition = "2021"
description = "PageTop package for easy content type creation and customization."
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "MIT OR Apache-2.0"
authors = [
"Manuel Cillero <manuel@cillero.es>"
]
categories = [
"web-programming", "gui"
]
keywords = [
"pagetop", "node", "cms", "content", "workflow"
]
[dependencies]
pagetop = { version = "0.0", path = "../../", features = ["database"], default-features = false }

View file

@ -1,37 +0,0 @@
<div align="center">
<h1>PageTop Node</h1>
<p>PageTop package for easy content type creation and customization.</p>
[![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](#-license)
[![API Docs](https://img.shields.io/docsrs/pagetop-node?label=API%20Docs&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-node)
[![Crates.io](https://img.shields.io/crates/v/pagetop-node.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-node)
[![Downloads](https://img.shields.io/crates/d/pagetop-node.svg?style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-node)
</div>
# 📦 About PageTop
[PageTop](https://docs.rs/pagetop) is an opinionated web framework to build modular *Server-Side
Rendering* web solutions.
# 🚧 Warning
**PageTop** framework is currently in active development. The API is unstable and subject to
frequent changes. Production use is not recommended until version **0.1.0**.
# 📜 License
All code in this crate is dual-licensed under either:
* MIT License
([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
* Apache License, Version 2.0,
([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is
the de-facto standard in the Rust ecosystem.

View file

@ -1,43 +0,0 @@
use pagetop::prelude::*;
static_locales!(LOCALES_NODE);
//mod entity;
mod migration;
pub struct Node;
impl PackageTrait for Node {
fn name(&self) -> L10n {
L10n::t("package_name", &LOCALES_NODE)
}
fn description(&self) -> L10n {
L10n::t("package_description", &LOCALES_NODE)
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
scfg.route("/node", service::web::get().to(node));
}
fn actions(&self) -> Vec<ActionBox> {
actions![action::page::BeforePrepareBody::new(before_prepare_body).with_weight(-1)]
}
fn migrations(&self) -> Vec<MigrationItem> {
migrations![
m20220316_000001_create_table_node_type,
m20220316_000002_create_table_node,
m20220316_000003_create_table_node_access,
m20220316_000004_create_table_node_revision,
]
}
}
async fn node(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
Page::new(request).with_title(L10n::n("Nodo")).render()
}
fn before_prepare_body(page: &mut Page) {
page.alter_body_classes(ClassesOp::Add, "test-node");
}

View file

@ -1,2 +0,0 @@
package_name = Node
package_description = Allows content to be submitted to the site and displayed on pages.

View file

@ -1,2 +0,0 @@
package_name = Nodo
package_description = Permite enviar contenidos al sitio y mostrarlos en páginas.

View file

@ -1,4 +0,0 @@
pub mod m20220316_000001_create_table_node_type;
pub mod m20220316_000002_create_table_node;
pub mod m20220316_000003_create_table_node_access;
pub mod m20220316_000004_create_table_node_revision;

View file

@ -1,59 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum NodeType {
Table, // node_type: Stores information about all defined Node types.
Type, // The machine-readable name of this type.
Name, // The human-readable name of this type.
Description, // Descripción breve del tipo.
Help, // Help information shown to the user when creating a Node of this type.
HasTitle, // Boolean indicating whether this type uses the Node.Title field.
TitleLabel, // The label displayed for the title field on the edit form.
Custom, // A boolean indicating whether this type is defined by a module (FALSE) or
// by a user via Add content type (TRUE).
Locked, // A boolean indicating whether the administrator can change the machine
// name of this type.
Disabled, // A boolean indicating whether the node type is disabled.
OrigType, // The original machine-readable name of this node type, this may be
// different from the current type name if the locked field is 0.
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(NodeType::Table)
.if_not_exists()
.col(
ColumnDef::new(NodeType::Type)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(NodeType::Name).string().not_null())
.col(ColumnDef::new(NodeType::Description).string().not_null())
.col(ColumnDef::new(NodeType::Help).string().not_null())
.col(ColumnDef::new(NodeType::HasTitle).string().not_null())
.col(ColumnDef::new(NodeType::TitleLabel).string().not_null())
.col(ColumnDef::new(NodeType::Custom).string().not_null())
.col(ColumnDef::new(NodeType::Locked).string().not_null())
.col(ColumnDef::new(NodeType::Disabled).string().not_null())
.col(ColumnDef::new(NodeType::OrigType).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(NodeType::Table).to_owned())
.await
}
}

View file

@ -1,70 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum Node {
Table, // node: The base table for nodes.
Nid, // The primary identifier for a node.
Vid, // The current NodeRevision.vid version identifier.
Type, // The NodeType.type of this node.
Language, // The {languages}.language of this node.
Title, // The title of this node, always treated as non-markup plain text.
Uid, // The User.uid that owns this node; initially, this is the user that
// created it.
Status, // Boolean indicating whether the node is published (visible to
// non-administrators).
Created, // The Unix timestamp when the node was created.
Changed, // The Unix timestamp when the node was most recently saved.
Comment, // Whether comments are allowed on this node: 0 = no, 1 = closed (read
// only), 2 = open (read/write).
Promote, // Boolean indicating whether the node should be displayed on the front
// page.
Sticky, // Boolean indicating whether the node should be displayed at the top of
// lists in which it appears.
Tnid, // The translation set id for this node, which equals the node id of the
// source post in each set.
Translate, // A boolean indicating whether this translation page needs to be updated.
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Node::Table)
.if_not_exists()
.col(
ColumnDef::new(Node::Nid)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Node::Vid).string().not_null())
.col(ColumnDef::new(Node::Type).string().not_null())
.col(ColumnDef::new(Node::Language).string().not_null())
.col(ColumnDef::new(Node::Title).string().not_null())
.col(ColumnDef::new(Node::Uid).string().not_null())
.col(ColumnDef::new(Node::Status).string().not_null())
.col(ColumnDef::new(Node::Created).string().not_null())
.col(ColumnDef::new(Node::Changed).string().not_null())
.col(ColumnDef::new(Node::Comment).string().not_null())
.col(ColumnDef::new(Node::Promote).string().not_null())
.col(ColumnDef::new(Node::Sticky).string().not_null())
.col(ColumnDef::new(Node::Tnid).string().not_null())
.col(ColumnDef::new(Node::Translate).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Node::Table).to_owned())
.await
}
}

View file

@ -1,54 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum NodeAccess {
Table, // node_access: Identifies which realm/grant pairs a user must possess in
// order to view, update, or delete specific nodes.
Nid, // The Node.nid this record affects.
Gid, // The grant ID a user must possess in the specified realm to gain this
// row's privileges on the node.
Realm, // The realm in which the user must possess the grant ID. Each node access
// node can define one or more realms.
GrantView, // Boolean indicating whether a user with the realm/grant pair can view this
// node.
GrantUpdate, // Boolean indicating whether a user with the realm/grant pair can edit this
// node.
GrantDelete, // Boolean indicating whether a user with the realm/grant pair can delete
// this node.
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(NodeAccess::Table)
.if_not_exists()
.col(
ColumnDef::new(NodeAccess::Nid)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(NodeAccess::Gid).string().not_null())
.col(ColumnDef::new(NodeAccess::Realm).string().not_null())
.col(ColumnDef::new(NodeAccess::GrantView).string().not_null())
.col(ColumnDef::new(NodeAccess::GrantUpdate).string().not_null())
.col(ColumnDef::new(NodeAccess::GrantDelete).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(NodeAccess::Table).to_owned())
.await
}
}

View file

@ -1,60 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum NodeRevision {
Table, // node_revision: Stores information about each saved version of a Node.
Nid, // The Node this version belongs to.
Vid, // The primary identifier for this version.
Uid, // The User.uid that created this version.
Title, // The title of this version.
Log, // The log entry explaining the changes in this version.
Timestamp, // A Unix timestamp indicating when this version was created.
Status, // Boolean indicating whether the node (at the time of this revision) is
// published (visible to non-administrators).
Comment, // Whether comments are allowed on this node (at the time of this revision):
// 0 = no, 1 = closed (read only), 2 = open (read/write).
Promote, // Boolean indicating whether the node (at the time of this revision) should
// be displayed on the front page.
Sticky, // Boolean indicating whether the node (at the time of this revision) should
// be displayed at the top of lists in which it appears.
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(NodeRevision::Table)
.if_not_exists()
.col(
ColumnDef::new(NodeRevision::Nid)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(NodeRevision::Vid).string().not_null())
.col(ColumnDef::new(NodeRevision::Uid).string().not_null())
.col(ColumnDef::new(NodeRevision::Title).string().not_null())
.col(ColumnDef::new(NodeRevision::Log).string().not_null())
.col(ColumnDef::new(NodeRevision::Timestamp).string().not_null())
.col(ColumnDef::new(NodeRevision::Status).string().not_null())
.col(ColumnDef::new(NodeRevision::Comment).string().not_null())
.col(ColumnDef::new(NodeRevision::Promote).string().not_null())
.col(ColumnDef::new(NodeRevision::Sticky).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(NodeRevision::Table).to_owned())
.await
}
}

View file

@ -1,23 +0,0 @@
[package]
name = "pagetop-user"
version = "0.0.19"
edition = "2021"
description = "PageTop package for user, roles, permissions, and session management."
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "MIT OR Apache-2.0"
authors = [
"Manuel Cillero <manuel@cillero.es>"
]
categories = [
"web-programming", "gui", "authentication"
]
keywords = [
"pagetop", "user", "login", "grants", "preferences"
]
[dependencies]
pagetop = { version = "0.0", path = "../../", features = ["database"], default-features = false }
serde = { version = "1.0", features = ["derive"] }

View file

@ -1,37 +0,0 @@
<div align="center">
<h1>PageTop User</h1>
<p>PageTop package for user, roles, permissions, and session management.</p>
[![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg?style=for-the-badge)](#-license)
[![API Docs](https://img.shields.io/docsrs/pagetop-user?label=API%20Docs&style=for-the-badge&logo=Docs.rs)](https://docs.rs/pagetop-user)
[![Crates.io](https://img.shields.io/crates/v/pagetop-user.svg?style=for-the-badge&logo=ipfs)](https://crates.io/crates/pagetop-user)
[![Downloads](https://img.shields.io/crates/d/pagetop-user.svg?style=for-the-badge&logo=transmission)](https://crates.io/crates/pagetop-user)
</div>
# 📦 About PageTop
[PageTop](https://docs.rs/pagetop) is an opinionated web framework to build modular *Server-Side
Rendering* web solutions.
# 🚧 Warning
**PageTop** framework is currently in active development. The API is unstable and subject to
frequent changes. Production use is not recommended until version **0.1.0**.
# 📜 License
All code in this crate is dual-licensed under either:
* MIT License
([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
* Apache License, Version 2.0,
([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is
the de-facto standard in the Rust ecosystem.

View file

@ -1,63 +0,0 @@
use pagetop::prelude::*;
static_locales!(LOCALES_USER);
mod migration;
pub struct User;
impl PackageTrait for User {
fn name(&self) -> L10n {
L10n::t("package_name", &LOCALES_USER)
}
fn description(&self) -> L10n {
L10n::t("package_description", &LOCALES_USER)
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
scfg.route("/user/login", service::web::get().to(login));
}
fn migrations(&self) -> Vec<MigrationItem> {
migrations![
m20220312_000001_create_table_role,
m20220312_000002_create_table_role_permission,
m20220312_000003_create_table_user,
m20220312_000004_create_table_user_role,
]
}
}
async fn login(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
Page::new(request)
.with_title(L10n::n("Identificación del usuario"))
.with_component(
flex::Container::new()
.with_id("welcome")
.add_item(flex::Item::with(form_login())),
)
.render()
}
fn form_login() -> Form {
Form::new()
.with_id("user-login")
.add_element(
form::Input::textfield()
.with_name("name")
.with_label(L10n::t("username", &LOCALES_USER))
.with_help_text(
L10n::t("username_help", &LOCALES_USER)
.with_arg("app", config::SETTINGS.app.name.to_owned()),
)
.with_autofocus(true),
)
.add_element(
form::Input::password()
.with_name("pass")
.with_label(L10n::t("password", &LOCALES_USER))
.with_help_text(L10n::t("password_help", &LOCALES_USER)),
)
.add_element(form::ActionButton::submit().with_value(L10n::t("login", &LOCALES_USER)))
}

View file

@ -1,8 +0,0 @@
package_name = User
package_description = Manages the user registration and login system.
username = User name
password = Password
username_help = Enter your { $app } username.
password_help = Enter the password that accompanies your username.
login = Log in

View file

@ -1,8 +0,0 @@
package_name = Usuario
package_description = Gestiona el registro de usuarios y el sistema de accesos.
username = Nombre de usuario
password = Contraseña
username_help = Introduzca su nombre de usuario en { $app }.
password_help = Introduzca la contraseña asociada a su nombre de usuario.
login = Iniciar sesión

View file

@ -1,4 +0,0 @@
pub mod m20220312_000001_create_table_role;
pub mod m20220312_000002_create_table_role_permission;
pub mod m20220312_000003_create_table_user;
pub mod m20220312_000004_create_table_user_role;

View file

@ -1,71 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum Role {
Table, // role: Store user roles.
Rid, // Primary Key: Unique role ID.
Name, // Unique role name.
Weight, // The weight of this role in listings and the user interface.
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Role::Table)
.if_not_exists()
.col(
ColumnDef::new(Role::Rid)
.unsigned()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(Role::Name)
.string_len(64)
.not_null()
.unique_key(),
)
.col(
ColumnDef::new(Role::Weight)
.integer()
.not_null()
.default(10),
)
// INDEXES.
.index(
Index::create()
.name("weight-name")
.col(Role::Weight)
.col(Role::Name),
)
.to_owned(),
)
.await?;
// Built-in roles.
db::exec::<InsertStatement>(
Query::insert()
.into_table(Role::Table)
.columns(vec![Role::Name, Role::Weight])
.values_panic(vec!["anonymous".into(), "1".into()])
.values_panic(vec!["authenticated".into(), "2".into()])
.values_panic(vec!["administrator".into(), "3".into()]),
)
.await
.map(|_| ())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Role::Table).to_owned())
.await
}
}

View file

@ -1,64 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum RolePermission {
Table, // role_permission: Stores the permissions assigned to user roles.
Rid, // Foreign Key: Role::Rid.
Permission, // A single permission granted to the role identified by Rid.
}
#[derive(Iden)]
enum Role {
Table,
Rid,
/* ... */
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(RolePermission::Table)
.if_not_exists()
.col(ColumnDef::new(RolePermission::Rid).unsigned().not_null())
.col(
ColumnDef::new(RolePermission::Permission)
.string_len(128)
.not_null(),
)
// INDEXES.
.primary_key(
Index::create()
.col(RolePermission::Rid)
.col(RolePermission::Permission),
)
.index(
Index::create()
.name("permission")
.col(RolePermission::Permission),
)
.foreign_key(
ForeignKey::create()
.name("fk_role_permission-rid")
.from(RolePermission::Table, RolePermission::Rid)
.to(Role::Table, Role::Rid)
.on_delete(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict),
)
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(RolePermission::Table).to_owned())
.await
}
}

View file

@ -1,60 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum User {
Table, // user: Stores user data.
Uid, // Primary Key: Unique user ID.
Name, // Unique user name.
Pass, // User's password (hashed).
Mail, // User's e-mail address.
Created, // Timestamp for when user was created.
Changed, // Timestamp for when user was changed.
Access, // Timestamp for previous time user accessed the site.
Login, // Timestamp for user's last login.
Status, // Whether the user is active(1) or blocked(0).
Timezone, // User's time zone.
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(User::Table)
.if_not_exists()
.col(
ColumnDef::new(User::Uid)
.unsigned()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(User::Name)
.string_len(60)
.not_null()
.unique_key(),
)
.col(ColumnDef::new(User::Pass).string_len(128).not_null())
.col(ColumnDef::new(User::Mail).string_len(255))
.col(ColumnDef::new(User::Created).timestamp().not_null())
.col(ColumnDef::new(User::Changed).timestamp().not_null())
.col(ColumnDef::new(User::Access).timestamp().not_null())
.col(ColumnDef::new(User::Login).timestamp().not_null())
.col(ColumnDef::new(User::Status).boolean().not_null())
.col(ColumnDef::new(User::Timezone).string_len(32))
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(User::Table).to_owned())
.await
}
}

View file

@ -1,66 +0,0 @@
use pagetop::prelude::*;
#[rustfmt::skip]
#[derive(Iden)]
enum UserRole {
Table, // user_role: Maps users to roles.
Uid, // Foreign Key: User::Uid for user.
Rid, // Foreign Key: Role::Rid for role.
}
#[derive(Iden)]
enum User {
Table,
Uid,
/* ... */
}
#[derive(Iden)]
enum Role {
Table,
Rid,
/* ... */
}
new_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(UserRole::Table)
.if_not_exists()
.col(ColumnDef::new(UserRole::Uid).unsigned().not_null())
.col(ColumnDef::new(UserRole::Rid).unsigned().not_null())
// INDEXES.
.primary_key(Index::create().col(UserRole::Uid).col(UserRole::Rid))
.foreign_key(
ForeignKey::create()
.name("fk_user_role-uid")
.from(UserRole::Table, UserRole::Uid)
.to(User::Table, User::Uid)
.on_delete(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict),
)
.foreign_key(
ForeignKey::create()
.name("fk_user_role-rid")
.from(UserRole::Table, UserRole::Rid)
.to(Role::Table, Role::Rid)
.on_delete(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict),
)
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(UserRole::Table).to_owned())
.await
}
}

View file

@ -1,117 +0,0 @@
#!/bin/bash
# Ask the user which database system to use
read -p "Which database system are you using? (mysql/postgresql/sqlite): " DB_SYSTEM
# Check if selected database system is installed
if [ "$DB_SYSTEM" == "mysql" ]; then
if ! command -v mysql &> /dev/null; then
echo "mysql is not installed or not found in PATH. Please install mysql and try again."
exit 1
fi
elif [ "$DB_SYSTEM" == "postgresql" ]; then
if ! command -v psql &> /dev/null; then
echo "postgresql is not installed or not found in PATH. Please install postgresql and try again."
exit 1
fi
elif [ "$DB_SYSTEM" == "sqlite" ]; then
if ! command -v sqlite3 &> /dev/null; then
echo "sqlite3 is not installed or not found in PATH. Please install sqlite3 and try again."
exit 1
fi
else
echo "Invalid database system selected. Please choose either 'mysql', 'postgresql', or 'sqlite'."
exit 1
fi
EXIT_CODE=0
echo
echo "You will be prompted to provide details for creating the Drust database."
echo "Press ENTER to accept the default values."
echo
if [ "$DB_SYSTEM" == "sqlite" ]; then
DEFAULT_DB_NAME="drust.db"
# Only prompt for database name, as user and password are not used by SQLite
read -p "Enter database name [$DEFAULT_DB_NAME]: " DB_NAME
DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME}
# For SQLite, just check if the database file exists and create it if it doesn't
if [ ! -f "$DB_NAME" ]; then
echo "Creating SQLite database file: $DB_NAME"
sqlite3 "$DB_NAME" ".quit"
EXIT_CODE=$?
else
echo "SQLite database file $DB_NAME already exists."
exit 1
fi
else
DEFAULT_DB_NAME="drust"
DEFAULT_DB_USER="drust"
DEFAULT_DB_PASS="demo"
DEFAULT_DB_HOST="localhost"
# Prompt for database details, allow defaults
read -p "Enter database name [$DEFAULT_DB_NAME]: " DB_NAME
DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME}
read -p "Enter database user [$DEFAULT_DB_USER]: " DB_USER
DB_USER=${DB_USER:-$DEFAULT_DB_USER}
read -p "Enter database password [$DEFAULT_DB_PASS]: " DB_PASS
DB_PASS=${DB_PASS:-$DEFAULT_DB_PASS}
read -p "Enter database host [$DEFAULT_DB_HOST]: " DB_HOST
DB_HOST=${DB_HOST:-$DEFAULT_DB_HOST}
# Prompt for database system root or another privileged user's credentials
echo
read -p "Enter $DB_SYSTEM root or admin user: " DB_ROOT_USER
read -sp "Enter $DB_SYSTEM root or admin password: " DB_ROOT_PASS
echo
# Confirm before proceeding
echo
echo "You are about to create the database \"$DB_NAME\" and assign privileges to user \"$DB_USER\"."
read -p "Are you sure you want to proceed? (y/N): " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
echo "Operation cancelled."
exit 1
fi
# Execute commands for MySQL or PostgreSQL
if [ "$DB_SYSTEM" == "mysql" ]; then
MYSQL_PWD="$DB_ROOT_PASS" mysql -u "$DB_ROOT_USER" -h "$DB_HOST" <<EOF
CREATE DATABASE IF NOT EXISTS $DB_NAME;
CREATE USER IF NOT EXISTS '$DB_USER'@'$DB_HOST' IDENTIFIED BY '$DB_PASS';
GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'$DB_HOST';
FLUSH PRIVILEGES;
EOF
elif [ "$DB_SYSTEM" == "postgresql" ]; then
PGPASSWORD="$DB_ROOT_PASS" psql -U "$DB_ROOT_USER" -h "$DB_HOST" <<EOF
CREATE DATABASE IF NOT EXISTS $DB_NAME;
DO \$\$
BEGIN
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_user
WHERE usename = '$DB_USER') THEN
CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASS';
END IF;
END
\$\$;
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
EOF
fi
EXIT_CODE=$?
fi
if [ $EXIT_CODE -eq 0 ]; then
echo "Operation completed."
else
echo "An error occurred. Exit code: $EXIT_CODE"
fi
# Exit the script with the mysql command's exit code
exit $EXIT_CODE

View file

@ -1,96 +0,0 @@
#!/bin/bash
# Ask the user which database system to use
read -p "Which database system are you using? (mysql/postgresql/sqlite): " DB_SYSTEM
# Check if selected database system is installed
if [ "$DB_SYSTEM" == "mysql" ]; then
if ! command -v mysql &> /dev/null; then
echo "mysql is not installed or not found in PATH. Please install mysql and try again."
exit 1
fi
elif [ "$DB_SYSTEM" == "postgresql" ]; then
if ! command -v psql &> /dev/null; then
echo "postgresql is not installed or not found in PATH. Please install postgresql and try again."
exit 1
fi
elif [ "$DB_SYSTEM" == "sqlite" ]; then
if ! command -v sqlite3 &> /dev/null; then
echo "sqlite3 is not installed or not found in PATH. Please install sqlite3 and try again."
exit 1
fi
else
echo "Invalid database system selected. Please choose either 'mysql', 'postgresql', or 'sqlite'."
exit 1
fi
EXIT_CODE=0
echo
echo "You will be prompted to provide details to delete the Drust database."
echo "Press ENTER to accept the default values."
echo
if [ "$DB_SYSTEM" == "sqlite" ]; then
DEFAULT_DB_NAME="drust.db"
# Only prompt for database name
read -p "Enter database name to delete [$DEFAULT_DB_NAME]: " DB_NAME
DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME}
# For SQLite, check if the database file exists and delete it
if [ -f "$DB_NAME" ]; then
echo "Deleting SQLite database file: $DB_NAME"
rm "$DB_NAME"
EXIT_CODE=$?
else
echo "SQLite database file $DB_NAME does not exist."
exit 1
fi
else
DEFAULT_DB_NAME="drust"
DEFAULT_DB_HOST="localhost"
# Prompt for database details, allow defaults
read -p "Enter database name to delete [$DEFAULT_DB_NAME]: " DB_NAME
DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME}
read -p "Enter database host [$DEFAULT_DB_HOST]: " DB_HOST
DB_HOST=${DB_HOST:-$DEFAULT_DB_HOST}
# Prompt for database system root or another privileged user's credentials
echo
read -p "Enter $DB_SYSTEM root or admin user: " DB_ROOT_USER
read -sp "Enter $DB_SYSTEM root or admin password: " DB_ROOT_PASS
echo
# Confirm before proceeding
echo
echo "You are about to delete the database \"$DB_NAME\"."
read -p "Are you sure you want to proceed? (y/N): " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
echo "Operation cancelled."
exit 1
fi
# Execute commands for MySQL or PostgreSQL
if [ "$DB_SYSTEM" == "mysql" ]; then
MYSQL_PWD="$DB_ROOT_PASS" mysql -u "$DB_ROOT_USER" -h "$DB_HOST" <<EOF
DROP DATABASE $DB_NAME;
EOF
elif [ "$DB_SYSTEM" == "postgresql" ]; then
PGPASSWORD="$DB_ROOT_PASS" psql -U "$DB_ROOT_USER" -h "$DB_HOST" <<EOF
DROP DATABASE $DB_NAME;
EOF
fi
EXIT_CODE=$?
fi
if [ $EXIT_CODE -eq 0 ]; then
echo "Database deletion completed successfully."
else
echo "An error occurred during database deletion. Exit code: $EXIT_CODE"
fi
# Exit the script with the mysql command's exit code
exit $EXIT_CODE

View file

@ -55,13 +55,6 @@ HELPERS=(
pagetop-macros
pagetop-build
)
PACKAGES=(
pagetop-user
pagetop-admin
pagetop-node
pagetop-bootsier
pagetop-bulmix
)
# Publish all helper crates
pushd helpers > /dev/null 2>&1
@ -75,15 +68,6 @@ popd > /dev/null 2>&1
# Publish the root crate
CRATE=pagetop; publish_crate
# Publish all main packages
pushd packages > /dev/null 2>&1
for CRATE in "${PACKAGES[@]}"; do
pushd "$CRATE" > /dev/null 2>&1
publish_crate
popd > /dev/null 2>&1
done
popd > /dev/null 2>&1
# Reset local Git repository to clean licenses after publishing
echo -e "\nCleaning local state"
git reset HEAD --hard