🏷️ PageContext pasa a ser RenderResources

Ahora los componentes no tendrán acceso al contexto de la página
(PageContext) porque podrían usarse en otros tipos de respuesta que no
sean sólo páginas. En su lugar se usará RenderResources que formarán
también parte de la página.
This commit is contained in:
Manuel Cillero 2022-12-18 14:09:53 +01:00
parent a687c646f2
commit b0446c7206
30 changed files with 263 additions and 252 deletions

View file

@ -41,7 +41,7 @@ pub async fn summary() -> ResultPage<Markup, FatalError> {
.with_item(MenuItem::label("Opción 4"));
Page::new()
.with_context(PageOp::SetTheme("Bootsier"))
.with_resource(ResourceOp::SetTheme("Bootsier"))
.with_title("Admin")
.add_to("top-menu", top_menu)
.add_to(

View file

@ -51,12 +51,12 @@ impl ComponentTrait for Anchor {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
#[rustfmt::skip]
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
let target = match &self.target() {
AnchorTarget::Blank => Some("_blank"),
AnchorTarget::Parent => Some("_parent"),
@ -71,9 +71,9 @@ impl ComponentTrait for Anchor {
href=[self.href().get()]
target=[target]
{
(self.left_icon().render(context))
(self.left_icon().render(rsx))
span { (*self.html()) }
(self.right_icon().render(context))
(self.right_icon().render(rsx))
}
}
}

View file

@ -29,23 +29,23 @@ impl ComponentTrait for Block {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
before_render_inline(self, context);
fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, rsx);
}
fn default_render(&self, context: &mut PageContext) -> Markup {
let id = context.required_id::<Block>(self.id());
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
let id = rsx.required_id::<Block>(self.id());
html! {
div id=(id) class=[self.classes().get()] {
@if let Some(title) = self.title().get() {
h2 class="block-title" { (title) }
}
div class="block-body" {
(self.components().render(context))
(self.components().render(rsx))
}
}
}

View file

@ -42,47 +42,47 @@ impl ComponentTrait for Container {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
before_render_inline(self, context);
fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, rsx);
}
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
match self.container_type() {
ContainerType::Header => html! {
header id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(context))
(self.components().render(rsx))
}
}
},
ContainerType::Footer => html! {
footer id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(context))
(self.components().render(rsx))
}
}
},
ContainerType::Main => html! {
main id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(context))
(self.components().render(rsx))
}
}
},
ContainerType::Section => html! {
section id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(context))
(self.components().render(rsx))
}
}
},
_ => html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(context))
(self.components().render(rsx))
}
},
}

View file

@ -39,11 +39,11 @@ impl ComponentTrait for Button {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
let button_type = match self.button_type() {
ButtonType::Button => "button",
ButtonType::Submit => "submit",

View file

@ -36,11 +36,11 @@ impl ComponentTrait for Date {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
let id = self.name().get().map(|name| concat_string!("edit-", name));
html! {
div class=[self.classes().get()] {

View file

@ -40,15 +40,15 @@ impl ComponentTrait for Form {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
before_render_inline(self, context);
fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, rsx);
}
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
let method = match self.method() {
FormMethod::Post => Some("post".to_owned()),
FormMethod::Get => None,
@ -61,7 +61,7 @@ impl ComponentTrait for Form {
method=[method]
accept-charset=[self.charset().get()]
{
div { (self.elements().render(context)) }
div { (self.elements().render(rsx)) }
}
}
}

View file

@ -23,7 +23,7 @@ impl ComponentTrait for Hidden {
self.weight
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
let id = self.name().get().map(|name| concat_string!("value-", name));
html! {
input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()];

View file

@ -53,12 +53,12 @@ impl ComponentTrait for Input {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
#[rustfmt::skip]
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
let type_input = match self.input_type() {
InputType::Textfield => "text",
InputType::Password => "password",

View file

@ -61,18 +61,18 @@ impl ComponentTrait for Column {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
before_render_inline(self, context);
fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, rsx);
}
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(context))
(self.components().render(rsx))
}
}
}

View file

@ -28,18 +28,18 @@ impl ComponentTrait for Row {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
before_render_inline(self, context);
fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, rsx);
}
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.columns().render(context))
(self.columns().render(rsx))
}
}
}

View file

@ -51,11 +51,11 @@ impl ComponentTrait for Heading {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
let id = self.id().get();
let classes = self.classes().get();
html! { @match &self.heading_type() {

View file

@ -24,11 +24,11 @@ impl ComponentTrait for Html {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
html! { (*self.html()) }
}

View file

@ -24,17 +24,17 @@ impl ComponentTrait for Icon {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
context.alter(PageOp::AddStyleSheet(
fn before_render(&mut self, rsx: &mut RenderResources) {
rsx.alter(ResourceOp::AddStyleSheet(
StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"),
));
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
html! { i class=[self.classes().get()] {}; }
}

View file

@ -26,11 +26,11 @@ impl ComponentTrait for Image {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, _: &mut PageContext) -> Markup {
fn default_render(&self, _: &mut RenderResources) -> Markup {
html! {
img
src=[self.source().get()]

View file

@ -37,11 +37,11 @@ impl ComponentTrait for MenuItem {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
match self.item_type() {
MenuItemType::Void => html! {},
@ -63,7 +63,7 @@ impl ComponentTrait for MenuItem {
li class="submenu" {
a href="#" { (label) }
ul {
(menu.items().render(context))
(menu.items().render(rsx))
}
}
},
@ -186,32 +186,31 @@ impl ComponentTrait for Menu {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn before_render(&mut self, context: &mut PageContext) {
before_render_inline(self, context);
fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, rsx);
}
fn default_render(&self, context: &mut PageContext) -> Markup {
context
.alter(PageOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"),
))
.alter(PageOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"),
))
.alter(PageOp::AddJavaScript(
JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"),
))
.alter(PageOp::AddJQuery);
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
rsx.alter(ResourceOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"),
))
.alter(ResourceOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"),
))
.alter(ResourceOp::AddJavaScript(
JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"),
))
.alter(ResourceOp::AddJQuery);
let id = context.required_id::<Menu>(self.id());
let id = rsx.required_id::<Menu>(self.id());
html! {
ul id=(id) class=[self.classes().get()] {
(self.items().render(context))
(self.items().render(rsx))
}
script type="text/javascript" defer {
"jQuery(function(){jQuery('#" (id) "').smartmenus({"

View file

@ -38,17 +38,17 @@ impl ComponentTrait for Paragraph {
self.weight
}
fn is_renderable(&self, context: &PageContext) -> bool {
(self.renderable.check)(context)
fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(rsx)
}
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! {
p
id=[self.id().get()]
class=[self.classes().get()]
{
(self.components().render(context))
(self.components().render(rsx))
}
}
}

View file

@ -27,7 +27,7 @@ impl ModuleTrait for DefaultHomePage {
async fn demo() -> ResultPage<Markup, FatalError> {
Page::new()
.with_title(l("page_title").as_str())
.with_context(PageOp::AddStyleSheet(StyleSheet::located(
.with_resource(ResourceOp::AddStyleSheet(StyleSheet::located(
"/theme/module/homepage/styles.css",
)))
.with_body_classes(ClassesOp::AddFirst, "default-homepage")

View file

@ -16,11 +16,9 @@ impl ThemeTrait for Aliner {
}
fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon(
Favicon::new().with_icon("/theme/favicon.ico"),
))
.alter_context(PageOp::AddStyleSheet(
StyleSheet::located("/aliner/css/styles.css").with_weight(-99),
));
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_resource(ResourceOp::AddStyleSheet(
StyleSheet::located("/aliner/css/styles.css").with_weight(-99),
));
}
}

View file

@ -18,20 +18,18 @@ impl ThemeTrait for Bootsier {
}
fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon(
Favicon::new().with_icon("/theme/favicon.ico"),
))
.alter_context(PageOp::AddStyleSheet(
StyleSheet::located("/bootsier/css/bootstrap.min.css")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_context(PageOp::AddJavaScript(
JavaScript::located("/bootsier/js/bootstrap.bundle.min.js")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_context(PageOp::AddJQuery);
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_resource(ResourceOp::AddStyleSheet(
StyleSheet::located("/bootsier/css/bootstrap.min.css")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_resource(ResourceOp::AddJavaScript(
JavaScript::located("/bootsier/js/bootstrap.bundle.min.js")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_resource(ResourceOp::AddJQuery);
}
fn error_404_not_found(&self) -> Container {

View file

@ -16,22 +16,20 @@ impl ThemeTrait for Bulmix {
}
fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon(
Favicon::new().with_icon("/theme/favicon.ico"),
))
.alter_context(PageOp::AddStyleSheet(
StyleSheet::located("/bulmix/css/bulma.min.css")
.with_version("0.9.4")
.with_weight(-99),
))
.alter_context(PageOp::AddJQuery);
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_resource(ResourceOp::AddStyleSheet(
StyleSheet::located("/bulmix/css/bulma.min.css")
.with_version("0.9.4")
.with_weight(-99),
))
.alter_resource(ResourceOp::AddJQuery);
}
#[rustfmt::skip]
fn before_render_component(
&self,
component: &mut dyn ComponentTrait,
_context: &mut PageContext,
_rsx: &mut RenderResources,
) {
match component.handle() {
COMPONENT_ANCHOR => {
@ -110,7 +108,7 @@ impl ThemeTrait for Bulmix {
fn render_component(
&self,
component: &dyn ComponentTrait,
_context: &mut PageContext,
_rsx: &mut RenderResources,
) -> Option<Markup> {
match component.handle() {
COMPONENT_ICON => {

View file

@ -1,3 +1,6 @@
mod resources;
pub use resources::{RenderResources, ResourceOp};
mod definition;
pub use definition::{component_mut, component_ref, AnyComponent, BaseComponent, ComponentTrait};

View file

@ -1,6 +1,6 @@
use super::ComponentTrait;
use super::{ComponentTrait, RenderResources};
use crate::html::{html, Markup};
use crate::response::page::PageContext;
use std::sync::{Arc, RwLock};
@ -26,12 +26,12 @@ impl ComponentsBundle {
self.0.clear();
}
pub fn render(&self, context: &mut PageContext) -> Markup {
pub fn render(&self, rsx: &mut RenderResources) -> Markup {
let mut components = self.0.clone();
components.sort_by_key(|c| c.read().unwrap().weight());
html! {
@for c in components.iter() {
(" ")(c.write().unwrap().render(context))(" ")
(" ")(c.write().unwrap().render(rsx))(" ")
}
}
}

View file

@ -1,11 +1,12 @@
use super::RenderResources;
use crate::html::{html, Markup};
use crate::response::page::PageContext;
use crate::util::{single_type_name, Handle};
pub use std::any::Any as AnyComponent;
pub trait BaseComponent {
fn render(&mut self, context: &mut PageContext) -> Markup;
fn render(&mut self, rsx: &mut RenderResources) -> Markup;
}
pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
@ -28,15 +29,15 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
}
#[allow(unused_variables)]
fn is_renderable(&self, context: &PageContext) -> bool {
fn is_renderable(&self, rsx: &RenderResources) -> bool {
true
}
#[allow(unused_variables)]
fn before_render(&mut self, context: &mut PageContext) {}
fn before_render(&mut self, rsx: &mut RenderResources) {}
#[allow(unused_variables)]
fn default_render(&self, context: &mut PageContext) -> Markup {
fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! {}
}
@ -46,17 +47,17 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
}
impl<C: ComponentTrait> BaseComponent for C {
fn render(&mut self, context: &mut PageContext) -> Markup {
fn render(&mut self, rsx: &mut RenderResources) -> Markup {
// Acciones del componente antes de renderizar.
self.before_render(context);
self.before_render(rsx);
// Acciones del tema antes de renderizar el componente.
context.theme().before_render_component(self, context);
rsx.theme().before_render_component(self, rsx);
match self.is_renderable(context) {
true => match context.theme().render_component(self, context) {
match self.is_renderable(rsx) {
true => match rsx.theme().render_component(self, rsx) {
Some(html) => html,
None => self.default_render(context),
None => self.default_render(rsx),
},
false => html! {},
}
@ -77,7 +78,7 @@ macro_rules! hook_before_render_component {
paste::paste! {
$crate::pub_handle!($ACTION_HANDLE);
type Action = fn(&$Component, &mut PageContext);
type Action = fn(&$Component, &mut RenderResources);
pub struct [< BeforeRender $Component >] {
action: Option<Action>,
@ -118,18 +119,18 @@ macro_rules! hook_before_render_component {
self
}
pub fn run(&self, component: &mut $Component, context: &mut PageContext) {
pub fn run(&self, component: &mut $Component, rsx: &mut RenderResources) {
if let Some(action) = self.action {
action(component, context)
action(component, rsx)
}
}
}
#[inline(always)]
fn before_render_inline(component: &mut $Component, context: &mut PageContext) {
fn before_render_inline(component: &mut $Component, rsx: &mut RenderResources) {
run_actions($ACTION_HANDLE, |action|
action_ref::<[< BeforeRender $Component >]>(&**action)
.run(component, context)
.run(component, rsx)
);
}
}

View file

@ -1,6 +1,6 @@
use crate::response::page::PageContext;
use crate::core::component::RenderResources;
pub type IsRenderable = fn(&PageContext) -> bool;
pub type IsRenderable = fn(&RenderResources) -> bool;
pub struct Renderable {
pub check: IsRenderable,
@ -14,6 +14,6 @@ impl Default for Renderable {
}
}
fn render_always(_: &PageContext) -> bool {
fn render_always(_: &RenderResources) -> bool {
true
}

View file

@ -1,7 +1,5 @@
use super::PageOp;
use crate::core::theme::{all::theme_by_single_name, ThemeStaticRef};
use crate::html::{html, Assets, Favicon, IdentifierValue, JavaScript, Markup, ModeJS, StyleSheet};
use crate::html::{html, Assets, IdentifierValue, JavaScript, Markup, ModeJS, StyleSheet};
use crate::{base, concat_string, config, util, LazyStatic};
static DEFAULT_THEME: LazyStatic<ThemeStaticRef> =
@ -10,26 +8,29 @@ static DEFAULT_THEME: LazyStatic<ThemeStaticRef> =
None => &base::theme::bootsier::Bootsier,
});
pub enum ResourceOp {
SetTheme(&'static str),
AddStyleSheet(StyleSheet),
RemoveStyleSheet(&'static str),
AddJavaScript(JavaScript),
RemoveJavaScript(&'static str),
AddJQuery,
}
#[rustfmt::skip]
pub struct PageContext {
pub struct RenderResources {
theme : ThemeStaticRef,
favicon : Option<Favicon>,
metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>,
stylesheets: Assets<StyleSheet>,
javascripts: Assets<JavaScript>,
with_jquery: bool,
id_counter : usize,
}
impl Default for PageContext {
impl Default for RenderResources {
#[rustfmt::skip]
fn default() -> Self {
PageContext {
RenderResources {
theme : *DEFAULT_THEME,
favicon : None,
metadata : Vec::new(),
properties : Vec::new(),
stylesheets: Assets::<StyleSheet>::new(),
javascripts: Assets::<JavaScript>::new(),
with_jquery: false,
@ -38,45 +39,29 @@ impl Default for PageContext {
}
}
impl PageContext {
impl RenderResources {
pub fn new() -> Self {
PageContext::default()
RenderResources::default()
}
pub fn alter(&mut self, op: PageOp) -> &mut Self {
pub fn alter(&mut self, op: ResourceOp) -> &mut Self {
match op {
PageOp::SetTheme(theme_name) => {
ResourceOp::SetTheme(theme_name) => {
self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME);
}
PageOp::AddFavicon(favicon) => {
self.favicon = Some(favicon);
}
PageOp::RemoveFavicon => {
self.favicon = None;
}
PageOp::AddMetadata(name, content) => {
self.metadata.push((name, content));
}
PageOp::AddProperty(property, content) => {
self.properties.push((property, content));
}
PageOp::AddStyleSheet(css) => {
ResourceOp::AddStyleSheet(css) => {
self.stylesheets.add(css);
}
PageOp::RemoveStyleSheet(source) => {
ResourceOp::RemoveStyleSheet(source) => {
self.stylesheets.remove(source);
}
PageOp::AddJavaScript(js) => {
ResourceOp::AddJavaScript(js) => {
self.javascripts.add(js);
}
PageOp::RemoveJavaScript(source) => {
ResourceOp::RemoveJavaScript(source) => {
self.javascripts.remove(source);
}
PageOp::AddJQuery => {
ResourceOp::AddJQuery => {
if !self.with_jquery {
self.javascripts.add(
JavaScript::located("/theme/js/jquery.min.js")
@ -91,32 +76,22 @@ impl PageContext {
self
}
/// PageContext GETTERS.
/// Resources GETTERS.
pub(crate) fn theme(&mut self) -> ThemeStaticRef {
self.theme
}
/// PageContext RENDER.
/// Resources RENDER.
pub fn render(&mut self) -> Markup {
html! {
@match &self.favicon {
Some(favicon) => (favicon.render()),
None => "",
}
@for (name, content) in &self.metadata {
meta name=(name) content=(content) {}
}
@for (property, content) in &self.properties {
meta property=(property) content=(content) {}
}
(self.stylesheets.render())
(self.javascripts.render())
}
}
// PageContext EXTRAS.
// Resources EXTRAS.
pub fn required_id<T>(&mut self, id: &IdentifierValue) -> String {
match id.get() {

View file

@ -1,7 +1,7 @@
use crate::base::component::{Container, Html};
use crate::core::component::ComponentTrait;
use crate::core::component::{ComponentTrait, RenderResources};
use crate::html::{html, Favicon, Markup};
use crate::response::page::{Page, PageContext, PageOp};
use crate::response::page::Page;
use crate::util::{single_type_name, Handle};
use crate::{concat_string, config, server};
@ -28,9 +28,9 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
#[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon(
Favicon::new().with_icon("/theme/favicon.ico"),
));
if page.favicon().is_none() {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")));
}
}
fn render_page_head(&self, page: &mut Page) -> Markup {
@ -49,10 +49,22 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
@if let Some(d) = page.description().get() {
meta name="description" content=(d);
}
meta http-equiv="X-UA-Compatible" content="IE=edge";
meta name="viewport" content=(viewport);
(page.context().render())
meta name="viewport" content=(viewport);
@for (name, content) in page.metadata() {
meta name=(name) content=(content) {}
}
meta http-equiv="X-UA-Compatible" content="IE=edge";
@for (property, content) in page.properties() {
meta property=(property) content=(content) {}
}
@if let Some(f) = page.favicon() {
(f.render())
}
(page.resources().render())
}
}
}
@ -84,7 +96,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
fn before_render_component(
&self,
component: &mut dyn ComponentTrait,
context: &mut PageContext,
rsx: &mut RenderResources,
) {
/*
Cómo usarlo:
@ -99,11 +111,12 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
*/
}
#[rustfmt::skip]
#[allow(unused_variables)]
fn render_component(
&self,
component: &dyn ComponentTrait,
context: &mut PageContext,
rsx: &mut RenderResources,
) -> Option<Markup> {
None
/*

View file

@ -25,7 +25,7 @@ impl fmt::Display for FatalError {
// Error 403.
FatalError::AccessDenied => {
let mut error_page = Page::new();
let error_content = error_page.context().theme().error_403_access_denied();
let error_content = error_page.resources().theme().error_403_access_denied();
if let Ok(page) = error_page
.with_title("Error FORBIDDEN")
.using_template("error")
@ -40,7 +40,7 @@ impl fmt::Display for FatalError {
// Error 404.
FatalError::NotFound => {
let mut error_page = Page::new();
let error_content = error_page.context().theme().error_404_not_found();
let error_content = error_page.resources().theme().error_404_not_found();
if let Ok(page) = error_page
.with_title("Error RESOURCE NOT FOUND")
.using_template("error")

View file

@ -1,27 +1,5 @@
use crate::html::{Favicon, JavaScript, StyleSheet};
pub use actix_web::Result as ResultPage;
pub enum PageOp {
SetTheme(&'static str),
AddFavicon(Favicon),
RemoveFavicon,
AddMetadata(&'static str, &'static str),
AddProperty(&'static str, &'static str),
AddStyleSheet(StyleSheet),
RemoveStyleSheet(&'static str),
AddJavaScript(JavaScript),
RemoveJavaScript(&'static str),
AddJQuery,
}
mod context;
pub use context::PageContext;
mod hook;
pub use hook::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE};

View file

@ -1,8 +1,8 @@
use super::{BeforeRenderPageHook, PageContext, PageOp, ResultPage, HOOK_BEFORE_RENDER_PAGE};
use super::{BeforeRenderPageHook, ResultPage, HOOK_BEFORE_RENDER_PAGE};
use crate::core::component::*;
use crate::core::hook::{action_ref, run_actions};
use crate::html::{html, AttributeValue, Classes, ClassesOp, Markup, DOCTYPE};
use crate::html::{html, AttributeValue, Classes, ClassesOp, Favicon, Markup, DOCTYPE};
use crate::response::FatalError;
use crate::{config, trace, LazyStatic};
@ -43,11 +43,14 @@ pub enum TextDirection {
#[rustfmt::skip]
pub struct Page {
context : PageContext,
language : AttributeValue,
direction : AttributeValue,
title : AttributeValue,
description : AttributeValue,
metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>,
favicon : Option<Favicon>,
resources : RenderResources,
body_classes: Classes,
regions : HashMap<&'static str, ComponentsBundle>,
template : String,
@ -57,7 +60,6 @@ impl Default for Page {
#[rustfmt::skip]
fn default() -> Self {
Page {
context : PageContext::new(),
language : match &*DEFAULT_LANGUAGE {
Some(language) => AttributeValue::new().with_value(language),
_ => AttributeValue::new(),
@ -68,6 +70,10 @@ impl Default for Page {
},
title : AttributeValue::new(),
description : AttributeValue::new(),
metadata : Vec::new(),
properties : Vec::new(),
favicon : None,
resources : RenderResources::new(),
body_classes: Classes::new().with_value(ClassesOp::SetDefault, "body"),
regions : common_components(),
template : "default".to_owned(),
@ -82,11 +88,6 @@ impl Page {
// Page BUILDER.
pub fn with_context(mut self, op: PageOp) -> Self {
self.alter_context(op);
self
}
pub fn with_language(mut self, language: &str) -> Self {
self.alter_language(language);
self
@ -107,6 +108,26 @@ impl Page {
self
}
pub fn with_metadata(mut self, name: &'static str, content: &'static str) -> Self {
self.alter_metadata(name, content);
self
}
pub fn with_property(mut self, property: &'static str, content: &'static str) -> Self {
self.alter_property(property, content);
self
}
pub fn with_favicon(mut self, favicon: Option<Favicon>) -> Self {
self.alter_favicon(favicon);
self
}
pub fn with_resource(mut self, op: ResourceOp) -> Self {
self.alter_resource(op);
self
}
pub fn with_body_classes(mut self, op: ClassesOp, classes: &str) -> Self {
self.alter_body_classes(op, classes);
self
@ -129,11 +150,6 @@ impl Page {
// Page ALTER.
pub fn alter_context(&mut self, op: PageOp) -> &mut Self {
self.context.alter(op);
self
}
pub fn alter_language(&mut self, language: &str) -> &mut Self {
self.language.alter_value(language);
self
@ -158,6 +174,26 @@ impl Page {
self
}
pub fn alter_metadata(&mut self, name: &'static str, content: &'static str) -> &mut Self {
self.metadata.push((name, content));
self
}
pub fn alter_property(&mut self, property: &'static str, content: &'static str) -> &mut Self {
self.metadata.push((property, content));
self
}
pub fn alter_favicon(&mut self, favicon: Option<Favicon>) -> &mut Self {
self.favicon = favicon;
self
}
pub fn alter_resource(&mut self, op: ResourceOp) -> &mut Self {
self.resources.alter(op);
self
}
pub fn alter_body_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.body_classes.alter_value(op, classes);
self
@ -170,10 +206,6 @@ impl Page {
// Page GETTERS.
pub fn context(&mut self) -> &mut PageContext {
&mut self.context
}
pub fn language(&self) -> &AttributeValue {
&self.language
}
@ -190,6 +222,22 @@ impl Page {
&self.description
}
pub fn metadata(&self) -> &Vec<(&str, &str)> {
&self.metadata
}
pub fn properties(&self) -> &Vec<(&str, &str)> {
&self.properties
}
pub fn favicon(&self) -> &Option<Favicon> {
&self.favicon
}
pub fn resources(&mut self) -> &mut RenderResources {
&mut self.resources
}
pub fn body_classes(&self) -> &Classes {
&self.body_classes
}
@ -207,13 +255,13 @@ impl Page {
});
// Acciones del tema antes de renderizar la página.
self.context.theme().before_render_page(self);
self.resources.theme().before_render_page(self);
// Primero, renderizar el cuerpo.
let body = self.context.theme().render_page_body(self);
let body = self.resources.theme().render_page_body(self);
// Luego, renderizar la cabecera.
let head = self.context.theme().render_page_head(self);
let head = self.resources.theme().render_page_head(self);
// Finalmente, renderizar la página.
Ok(html! {
@ -227,7 +275,7 @@ impl Page {
pub fn render_region(&mut self, region: &str) -> Option<Markup> {
match self.regions.get_mut(region) {
Some(components) => Some(components.render(&mut self.context)),
Some(components) => Some(components.render(&mut self.resources)),
None => None,
}
}