Add more dioxus components

This commit is contained in:
photino 2024-01-01 19:08:36 +08:00
parent b970f94bfc
commit 4fc633a0ff
52 changed files with 321 additions and 107 deletions

View File

@ -52,12 +52,12 @@ For Chinese rustaceans, you can also follow our WeChat official account to canta
![zino-web](https://user-images.githubusercontent.com/3446306/265183253-90b4f8bb-33d2-4e14-b6e3-78da313e2e68.png)
[`zino-core`]: https://github.com/photino/zino/tree/main/zino-core
[`zino-derive`]: https://github.com/photino/zino/tree/main/zino-derive
[`zino-model`]: https://github.com/photino/zino/tree/main/zino-model
[`zino-extra`]: https://github.com/photino/zino/tree/main/zino-extra
[`zino-dioxus`]: https://github.com/photino/zino/tree/main/zino-dioxus
[`zino-cli`]: https://github.com/photino/zino/tree/main/zino-cli
[`zino-core`]: https://github.com/zino-rs/zino/tree/main/zino-core
[`zino-derive`]: https://github.com/zino-rs/zino/tree/main/zino-derive
[`zino-model`]: https://github.com/zino-rs/zino/tree/main/zino-model
[`zino-extra`]: https://github.com/zino-rs/zino/tree/main/zino-extra
[`zino-dioxus`]: https://github.com/zino-rs/zino/tree/main/zino-dioxus
[`zino-cli`]: https://github.com/zino-rs/zino/tree/main/zino-cli
[zino]: https://crates.io/crates/zino
[zino-docs]: https://docs.rs/zino
[zino-core]: https://crates.io/crates/zino-core
@ -78,8 +78,8 @@ For Chinese rustaceans, you can also follow our WeChat official account to canta
[`actix-web`]: https://crates.io/crates/actix-web
[`axum`]: https://crates.io/crates/axum
[`dioxus`]: https://crates.io/crates/dioxus
[`actix-app`]: https://github.com/photino/zino/tree/main/examples/actix-app
[`axum-app`]: https://github.com/photino/zino/tree/main/examples/axum-app
[`dioxus-desktop`]: https://github.com/photino/zino/tree/main/examples/dioxus-desktop
[license]: https://github.com/photino/zino/blob/main/LICENSE
[zino-issue]: https://github.com/photino/zino/issues/new
[`actix-app`]: https://github.com/zino-rs/zino/tree/main/examples/actix-app
[`axum-app`]: https://github.com/zino-rs/zino/tree/main/examples/axum-app
[`dioxus-desktop`]: https://github.com/zino-rs/zino/tree/main/examples/dioxus-desktop
[license]: https://github.com/zino-rs/zino/blob/main/LICENSE
[zino-issue]: https://github.com/zino-rs/zino/issues/new

View File

@ -5,7 +5,7 @@ An example for [actix-web] integration.
[actix-web]: https://crates.io/crates/actix-web
"""
contact = { url = "https://github.com/photino/zino" }
contact = { url = "https://github.com/zino-rs/zino" }
license = "MIT"
[security_schemes.jwt_auth]

View File

@ -5,7 +5,7 @@ An example for [axum] integration.
[axum]: https://crates.io/crates/axum
"""
contact = { url = "https://github.com/photino/zino" }
contact = { url = "https://github.com/zino-rs/zino" }
license = "MIT"
[security_schemes.jwt_auth]

View File

@ -41,7 +41,7 @@ pub fn Wrapper(cx: Scope) -> Element {
}
NavbarEnd {
NavbarLink {
to: "https://github.com/photino/zino",
to: "https://github.com/zino-rs/zino",
IconText {
Icon {
SvgIcon { icon: BsGithub }

View File

@ -53,7 +53,7 @@ pub fn Overview(cx: Scope) -> Element {
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/tags",
href: "https://github.com/zino-rs/zino/tags",
img {
src: "https://img.shields.io/github/v/tag/photino/zino",
}
@ -68,56 +68,56 @@ pub fn Overview(cx: Scope) -> Element {
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/stargazers",
href: "https://github.com/zino-rs/zino/stargazers",
img {
src: "https://img.shields.io/github/stars/photino/zino",
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/watchers",
href: "https://github.com/zino-rs/zino/watchers",
img {
src: "https://img.shields.io/github/watchers/photino/zino",
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/forks",
href: "https://github.com/zino-rs/zino/forks",
img {
src: "https://img.shields.io/github/forks/photino/zino",
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/graphs/contributors",
href: "https://github.com/zino-rs/zino/graphs/contributors",
img {
src: "https://img.shields.io/github/contributors/photino/zino",
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/commits/main",
href: "https://github.com/zino-rs/zino/commits/main",
img {
src: "https://img.shields.io/github/last-commit/photino/zino/main",
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/pulls",
href: "https://github.com/zino-rs/zino/pulls",
img {
src: "https://img.shields.io/github/issues-pr/photino/zino"
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/actions/workflows/rust.yml",
href: "https://github.com/zino-rs/zino/actions/workflows/rust.yml",
img {
src: "https://img.shields.io/github/actions/workflow/status/photino/zino/rust.yml",
}
}
a {
class: "mr-2",
href: "https://github.com/photino/zino/blob/main/LICENSE",
href: "https://github.com/zino-rs/zino/blob/main/LICENSE",
img {
src: "https://img.shields.io/github/license/photino/zino",
}
@ -151,7 +151,7 @@ pub fn Overview(cx: Scope) -> Element {
class: "card-content",
a {
class: "mr-2",
href: "https://github.com/photino/zino/issues",
href: "https://github.com/zino-rs/zino/issues",
img {
src: "https://img.shields.io/github/issues/photino/zino",
}
@ -159,7 +159,7 @@ pub fn Overview(cx: Scope) -> Element {
for label in ["bug", "enhancement", "dependencies"] {
a {
class: "mr-2",
href: "https://github.com/photino/zino/labels/{label}",
href: "https://github.com/zino-rs/zino/labels/{label}",
img {
src: "https://img.shields.io/github/issues/photino/zino/{label}",
}

View File

@ -309,7 +309,7 @@ fn StargazerListing<'a>(cx: Scope<'a>, index: usize, stargazer: &'a Map) -> Elem
img { src: avatar_url },
}
}
th {
td {
a {
href: "https://github.com/{name}?tab=followers",
img {

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["command-line-utilities", "network-programming", "web-programming"]
keywords = ["cli", "gui", "zino", "dioxus"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-cli"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-cli)
[![docs-rs]](https://docs.rs/zino-cli)
@ -8,4 +8,4 @@
CLI tools for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming::http-server"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-core"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-core)
[![docs-rs]](https://docs.rs/zino-core)
@ -28,7 +28,7 @@ The following optional features are available:
| `validator` | Enables the common validation rules. | No |
| `view` | Enables the HTML template rendering. | No |
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino
[`opendal`]: https://crates.io/crates/opendal
[`metrics`]: https://crates.io/crates/metrics
[`async-std`]: https://crates.io/crates/async-std

View File

@ -229,6 +229,9 @@ pub trait JsonObjectExt {
/// Creates a new instance with the `entries`.
fn data_entries(values: Vec<Map>) -> Self;
/// Creates a new instance with a single key `item`.
fn data_item(value: impl Into<JsonValue>) -> Self;
/// Creates a new instance with the `items`.
fn data_items<T: Into<JsonValue>>(values: Vec<T>) -> Self;
}
@ -685,6 +688,13 @@ impl JsonObjectExt for Map {
map
}
#[inline]
fn data_item(value: impl Into<JsonValue>) -> Self {
let mut map = Map::with_capacity(1);
map.insert("item".to_owned(), value.into());
map
}
#[inline]
fn data_items<T: Into<JsonValue>>(values: Vec<T>) -> Self {
let mut map = Map::with_capacity(2);

View File

@ -1,4 +1,4 @@
use crate::{datetime, extension::TomlValueExt, Map};
use crate::{datetime, extension::TomlValueExt, Map, Uuid};
use std::time::Duration;
use toml::value::{Array, Table};
@ -75,6 +75,10 @@ pub trait TomlTableExt {
/// and parses it as `Duration`.
fn get_duration(&self, key: &str) -> Option<Duration>;
/// Extracts the string corresponding to the key and parses it as `Uuid`.
/// If the `Uuid` is `nil`, it also returns `None`.
fn parse_uuid(&self, key: &str) -> Option<Result<Uuid, uuid::Error>>;
/// Converts `self` to a JSON object.
fn to_map(&self) -> Map;
}
@ -199,6 +203,13 @@ impl TomlTableExt for Table {
.and_then(|s| datetime::parse_duration(s).ok())
}
fn parse_uuid(&self, key: &str) -> Option<Result<Uuid, uuid::Error>> {
self.get_str(key)
.map(|s| s.trim_start_matches("urn:uuid:"))
.filter(|s| !s.chars().all(|c| c == '0' || c == '-'))
.map(|s| s.parse())
}
fn to_map(&self) -> Map {
let mut map = Map::with_capacity(self.len());
for (key, value) in self.iter() {

View File

@ -62,6 +62,9 @@ pub type TomlValue = toml::Value;
/// A Universally Unique Identifier (UUID).
pub type Uuid = uuid::Uuid;
/// A 128 bit representation of a fixed-precision decimal number.
pub type Decimal = rust_decimal::Decimal;
/// A value which is initialized on the first access.
pub type LazyLock<T> = once_cell::sync::Lazy<T>;

View File

@ -1,5 +1,5 @@
use super::{DatabaseDriver, DatabaseRow};
use crate::{error::Error, BoxError};
use crate::{error::Error, BoxError, Decimal, Uuid};
use chrono::{DateTime, Local, NaiveDate, NaiveTime};
use sqlx::{database::HasValueRef, Database, Decode, Row, Type};
@ -78,12 +78,54 @@ where
row.try_get_unchecked(field).map_err(Error::from)
}
/// Decodes a single value as `Decimal` for the field in a row.
#[cfg(any(
feature = "orm-mariadb",
feature = "orm-mysql",
feature = "orm-postgres",
feature = "orm-tidb"
))]
#[inline]
pub fn decode_decimal(row: &DatabaseRow, field: &str) -> Result<Decimal, Error> {
row.try_get_unchecked(field).map_err(Error::from)
}
/// Decodes a single value as `Decimal` for the field in a row.
#[cfg(not(any(
feature = "orm-mariadb",
feature = "orm-mysql",
feature = "orm-postgres",
feature = "orm-tidb"
)))]
#[inline]
pub fn decode_decimal(row: &DatabaseRow, field: &str) -> Result<Decimal, Error> {
decode::<String>(row, field)
.and_then(|value| value.parse().map_err(Error::from))
.map_err(Error::from)
}
/// Decodes a single value as `Uuid` for the field in a row.
#[cfg(feature = "orm-postgres")]
#[inline]
pub fn decode_uuid(row: &DatabaseRow, field: &str) -> Result<Uuid, Error> {
row.try_get_unchecked(field).map_err(Error::from)
}
/// Decodes a single value as `Uuid` for the field in a row.
#[cfg(not(feature = "orm-postgres"))]
#[inline]
pub fn decode_uuid(row: &DatabaseRow, field: &str) -> Result<Uuid, Error> {
decode::<String>(row, field)
.and_then(|value| value.parse().map_err(Error::from))
.map_err(Error::from)
}
/// Decodes a single value as `Vec<T>` for the field in a row.
#[cfg(feature = "orm-postgres")]
#[inline]
pub fn decode_array<'r, T>(row: &'r sqlx::postgres::PgRow, field: &str) -> Result<Vec<T>, Error>
pub fn decode_array<'r, T>(row: &'r DatabaseRow, field: &str) -> Result<Vec<T>, Error>
where
T: for<'a> Decode<'a, sqlx::Postgres> + sqlx::Type<sqlx::Postgres>,
T: for<'a> Decode<'a, DatabaseDriver> + sqlx::Type<DatabaseDriver>,
{
row.try_get_unchecked(field).map_err(Error::from)
}

View File

@ -87,19 +87,19 @@ macro_rules! impl_sqlx_executor {
let mut stream = sqlx::query(sql).fetch(self);
let mut max_rows = super::MAX_ROWS.load(Relaxed);
let mut rows = Vec::with_capacity(stream.size_hint().0.min(max_rows));
while max_rows > 0 {
match stream.next().await {
Some(Ok(row)) => {
while let Some(result) = stream.next().await {
match result {
Ok(row) if max_rows > 0 => {
rows.push(row);
max_rows -= 1;
}
Some(Err(err)) => {
Err(err) => {
if matches!(err, sqlx::error::Error::PoolTimedOut) {
super::GlobalPool::connect_all().await;
}
return Err(err.into());
}
None => break,
_ => break,
}
}
Ok(rows)
@ -121,19 +121,19 @@ macro_rules! impl_sqlx_executor {
let mut stream = query.fetch(self);
let mut max_rows = super::MAX_ROWS.load(Relaxed);
let mut rows = Vec::with_capacity(stream.size_hint().0.min(max_rows));
while max_rows > 0 {
match stream.next().await {
Some(Ok(row)) => {
while let Some(result) = stream.next().await {
match result {
Ok(row) if max_rows > 0 => {
rows.push(row);
max_rows -= 1;
}
Some(Err(err)) => {
Err(err) => {
if matches!(err, sqlx::error::Error::PoolTimedOut) {
super::GlobalPool::connect_all().await;
}
return Err(err.into());
}
None => break,
_ => break,
}
}
Ok(rows)

View File

@ -137,7 +137,7 @@ mod decode;
mod scalar;
#[cfg(feature = "orm-sqlx")]
pub use decode::{decode, decode_array};
pub use decode::{decode, decode_array, decode_decimal, decode_uuid};
#[cfg(feature = "orm-sqlx")]
pub use scalar::ScalarQuery;

View File

@ -53,8 +53,8 @@ where
let mut rows = sqlx::query(&sql).fetch(pool);
let mut data = Vec::new();
let mut max_rows = super::MAX_ROWS.load(Relaxed);
while max_rows > 0 {
if let Some(row) = rows.try_next().await? {
while let Some(row) = rows.try_next().await? {
if max_rows > 0 {
data.push(row.try_get_unchecked(0)?);
max_rows -= 1;
} else {
@ -109,8 +109,8 @@ where
let mut rows = query.fetch(pool);
let mut data = Vec::new();
let mut max_rows = super::MAX_ROWS.load(Relaxed);
while max_rows > 0 {
if let Some(row) = rows.try_next().await? {
while let Some(row) = rows.try_next().await? {
if max_rows > 0 {
data.push(row.try_get_unchecked(0)?);
max_rows -= 1;
} else {

View File

@ -512,7 +512,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
Self::before_mutation(query, mutation).await?;
let primary_key_name = Self::PRIMARY_KEY_NAME;
let table_name = query.format_table_name::<Self>();
let table_name = Self::table_name();
let filters = query.format_filters::<Self>();
let updates = mutation.format_updates::<Self>();
let sql = if cfg!(any(
@ -557,7 +557,7 @@ pub trait Schema: 'static + Send + Sync + ModelHooks {
let pool = Self::acquire_writer().await?.pool();
Self::before_mutation(query, mutation).await?;
let table_name = query.format_table_name::<Self>();
let table_name = Self::table_name();
let filters = query.format_filters::<Self>();
let updates = mutation.format_updates::<Self>();
let sql = format!("UPDATE {table_name} SET {updates} {filters};");

View File

@ -21,6 +21,9 @@ impl<'c> EncodeColumn<DatabaseDriver> for Column<'c> {
"u64" | "i64" | "usize" | "isize" | "Option<u64>" | "Option<i64>" | "u32" | "i32"
| "u16" | "i16" | "u8" | "i8" | "Option<u32>" | "Option<i32>" => "INTEGER",
"f64" | "f32" => "REAL",
"Date" => "DATE",
"Time" => "TIME",
"DateTime" => "DATETIME",
"Vec<u8>" => "BLOB",
_ => "TEXT",
}

View File

@ -172,7 +172,7 @@ where
let mutation = mutations.0;
Self::before_mutation(query, mutation).await?;
let table_name = query.format_table_name::<Self>();
let table_name = Self::table_name();
let filters = query.format_filters::<Self>();
let updates = mutation.format_updates::<Self>();
let sql = format!("UPDATE {table_name} SET {updates} {filters};");
@ -190,7 +190,7 @@ where
let mutation = mutations.1;
S::before_mutation(query, mutation).await?;
let table_name = query.format_table_name::<S>();
let table_name = S::table_name();
let filters = query.format_filters::<S>();
let updates = mutation.format_updates::<S>();
let sql = format!("UPDATE {table_name} SET {updates} {filters};");

View File

@ -5,8 +5,8 @@ version = "0.15.0"
rust-version = "1.75"
edition = "2021"
license = "MIT"
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-derive"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-derive)
[![docs-rs]](https://docs.rs/zino-derive)
@ -8,4 +8,4 @@
Derived traits for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -28,7 +28,15 @@ pub(super) fn parse_token_stream(input: DeriveInput) -> TokenStream {
if ignore {
continue;
}
if type_name == "Map" {
if type_name == "Uuid" {
decode_model_fields.push(quote! {
model.#ident = orm::decode_uuid(row, #name)?;
});
} else if type_name == "Decimal" {
decode_model_fields.push(quote! {
model.#ident = orm::decode_decimal(row, #name)?;
});
} else if type_name == "Map" {
decode_model_fields.push(quote! {
if let JsonValue::Object(map) = orm::decode(row, #name)? {
model.#ident = map;

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["gui", "network-programming", "web-programming"]
keywords = ["zino", "dioxus", "components"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-dioxus"
readme = "README.md"
@ -19,6 +19,15 @@ dioxus-router = "0.4.3"
dioxus-free-icons = "0.7.0"
smallvec = "1.11.1"
[dependencies.uuid]
version = "1.6.1"
features = [
"fast-rng",
"serde",
"v4",
"v7",
]
[dependencies.zino-core]
path = "../zino-core"
version = "0.18.0"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-dioxus)
[![docs-rs]](https://docs.rs/zino-dioxus)
@ -12,7 +12,7 @@ Dioxus components for [`zino`].
The design of our components is most inspired by [`Bulma`] and [`daisyUI`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino
[`Bulma`]: https://bulma.io/
[`daisyUI`]: https://daisyui.com/

View File

@ -149,4 +149,11 @@ macro_rules! format_class {
.map(Class::format)
.unwrap_or_else(|| $default_class.into())
};
($cx:ident, $class_prop:ident, $default_class:expr) => {
$cx.props
.$class_prop
.as_ref()
.map(Class::format)
.unwrap_or_else(|| $default_class.into())
};
}

View File

@ -0,0 +1,42 @@
use dioxus::events::FormData;
use zino_core::{extension::JsonObjectExt, Map, Uuid};
/// Extension trait for [`FormData`].
pub trait FormDataExt {
/// Extracts the string value.
fn get_str(&self) -> Option<&str>;
/// Extracts the string value and parses it as `Uuid`.
/// If the `Uuid` is `nil`, it also returns `None`.
fn parse_uuid(&self) -> Option<Result<Uuid, uuid::Error>>;
/// Converts `self` to a JSON object.
fn to_map(&self) -> Map;
}
impl<'a> FormDataExt for FormData {
fn get_str(&self) -> Option<&str> {
let value = self.value.as_str();
(!value.is_empty()).then_some(value)
}
fn parse_uuid(&self) -> Option<Result<Uuid, uuid::Error>> {
self.get_str()
.map(|s| s.trim_start_matches("urn:uuid:"))
.filter(|s| !s.chars().all(|c| c == '0' || c == '-'))
.map(|s| s.parse())
}
fn to_map(&self) -> Map {
let values = &self.values;
let mut map = Map::with_capacity(values.len());
for (key, value) in values.iter() {
if let Some([value]) = values.get(key).map(|v| v.as_slice()) {
map.upsert(key, value.clone());
} else {
map.upsert(key, value.clone());
}
}
map
}
}

View File

@ -1,5 +1,7 @@
//! Extension traits and helper utilities.
mod form_data;
mod vnode;
pub use form_data::FormDataExt;
pub use vnode::VNodeExt;

View File

@ -1,6 +1,6 @@
use dioxus_core::{DynamicNode::Component, VNode};
/// Extension trait for [`VNode`](dioxus_core::VNode).
/// Extension trait for [`VNode`].
pub trait VNodeExt {
/// Returns `true` if `self` has a given component node as its child.
fn has_component(&self, name: &str) -> bool;

View File

@ -9,5 +9,6 @@ pub mod extension;
pub mod icon;
pub mod layout;
pub mod menu;
pub mod message;
pub mod prelude;
pub mod theme;

View File

@ -7,7 +7,7 @@ mod sidebar;
pub use dropdown::{Dropdown, DropdownProps};
pub use navbar::{
Navbar, NavbarBrand, NavbarBrandProps, NavbarCenter, NavbarCenterProps, NavbarEnd,
NavbarEndProps, NavbarLink, NavbarLinkProps, NavbarMenu, NavbarMenuProps, NavbarProps,
NavbarStart, NavbarStartProps,
NavbarEndProps, NavbarItem, NavbarItemProps, NavbarLink, NavbarLinkProps, NavbarMenu,
NavbarMenuProps, NavbarProps, NavbarStart, NavbarStartProps,
};
pub use sidebar::{Sidebar, SidebarProps};

View File

@ -169,3 +169,24 @@ pub struct NavbarLinkProps<'a> {
/// The children to render within the component.
children: Element<'a>,
}
/// A container for each single item of the navbar.
pub fn NavbarItem<'a>(cx: Scope<'a, NavbarItemProps<'a>>) -> Element {
let class = format_class!(cx, "navbar-item");
render! {
div {
class: "{class}",
&cx.props.children
}
}
}
/// The [`NavbarItem`] properties struct for the configuration of the component.
#[derive(Props)]
pub struct NavbarItemProps<'a> {
/// The class attribute for the component.
#[props(into)]
pub class: Option<Class<'a>>,
/// The children to render within the component.
children: Element<'a>,
}

View File

@ -1,16 +1,23 @@
use crate::theme::Theme;
use crate::{class::Class, format_class};
use dioxus::prelude::*;
/// A vertical menu used in the navigation aside.
pub fn Sidebar<'a>(cx: Scope<'a, SidebarProps<'a>>) -> Element {
let class = format_class!(cx, "sidebar");
render! {
div {}
div {
class: "{class}",
&cx.props.children
}
}
}
/// The [`Sidebar`] properties struct for the configuration of the component.
#[derive(Debug, PartialEq, Props)]
#[derive(Props)]
pub struct SidebarProps<'a> {
/// Theme.
theme: &'a Theme,
/// The class attribute for the component.
#[props(into)]
pub class: Option<Class<'a>>,
/// The children to render within the component.
children: Element<'a>,
}

View File

@ -0,0 +1,5 @@
//! Contextual feedback messages.
mod notification;
pub use notification::{Notification, NotificationProps};

View File

@ -0,0 +1,38 @@
use crate::{class::Class, format_class};
use dioxus::prelude::*;
/// A simple colored block meant to draw the attention to the user about something.
pub fn Notification<'a>(cx: Scope<'a, NotificationProps<'a>>) -> Element {
let close_notification = use_state(cx, || false);
if *close_notification.get() {
None
} else {
let class = format_class!(cx, "notification");
let close_class = format_class!(cx, close_class, "delete");
render! {
div {
class: "{class}",
button {
class: "{close_class}",
onclick: |_event| {
close_notification.set(true);
}
}
&cx.props.children
}
}
}
}
/// The [`Notification`] properties struct for the configuration of the component.
#[derive(Props)]
pub struct NotificationProps<'a> {
/// The class attribute for the component.
#[props(into)]
pub class: Option<Class<'a>>,
/// A class to apply to the `close` button element.
#[props(into)]
pub close_class: Option<Class<'a>>,
/// The children to render within the component.
children: Element<'a>,
}

View File

@ -2,11 +2,13 @@
pub use crate::{
class::Class,
extension::FormDataExt,
icon::{Icon, IconText},
layout::{Container, FluidContainer, MainContainer},
menu::{
Dropdown, Navbar, NavbarBrand, NavbarCenter, NavbarEnd, NavbarLink, NavbarMenu,
Dropdown, Navbar, NavbarBrand, NavbarCenter, NavbarEnd, NavbarItem, NavbarLink, NavbarMenu,
NavbarStart, Sidebar,
},
message::Notification,
theme::Theme,
};

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-extra"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-extra)
[![docs-rs]](https://docs.rs/zino-extra)
@ -17,4 +17,4 @@ The following optional features are available:
| `cache` | Enables the cache services. | No |
| `format` | Enables the support for common file formats. | No |
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-middleware"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-middleware)
[![docs-rs]](https://docs.rs/zino-middleware)
@ -8,4 +8,4 @@
Middlewares for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["web-programming", "database"]
keywords = ["web", "model", "orm", "schema"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-model"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-model)
[![docs-rs]](https://docs.rs/zino-model)
@ -8,5 +8,5 @@
Domain models for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-router"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-router)
[![docs-rs]](https://docs.rs/zino-router)
@ -8,4 +8,4 @@
A flexible router for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-rpc"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-rpc)
[![docs-rs]](https://docs.rs/zino-rpc)
@ -8,4 +8,4 @@
RPC support for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino-server"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino-server)
[![docs-rs]](https://docs.rs/zino-server)
@ -8,4 +8,4 @@
A HTTP server for [`zino`].
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino

View File

@ -7,8 +7,8 @@ edition = "2021"
license = "MIT"
categories = ["asynchronous", "network-programming", "web-programming::http-server"]
keywords = ["http", "web", "framework"]
homepage = "https://github.com/photino/zino"
repository = "https://github.com/photino/zino"
homepage = "https://github.com/zino-rs/zino"
repository = "https://github.com/zino-rs/zino"
documentation = "https://docs.rs/zino"
readme = "README.md"

View File

@ -1,4 +1,4 @@
[![github]](https://github.com/photino/zino)
[![github]](https://github.com/zino-rs/zino)
[![crates-io]](https://crates.io/crates/zino)
[![docs-rs]](https://docs.rs/zino)
@ -38,13 +38,13 @@ The following optional features are available:
| `orm` | Enables the ORM for MySQL, PostgreSQL or **SQLite**. | Yes |
| `view` | Enables the HTML template rendering. | Yes |
[`zino`]: https://github.com/photino/zino
[`zino`]: https://github.com/zino-rs/zino
[`sqlx`]: https://crates.io/crates/sqlx
[`tracing`]: https://crates.io/crates/tracing
[`metrics`]: https://crates.io/crates/metrics
[`actix-web`]: https://crates.io/crates/actix-web
[`axum`]: https://crates.io/crates/axum
[`dioxus`]: https://crates.io/crates/dioxus
[`actix-app`]: https://github.com/photino/zino/tree/main/examples/actix-app
[`axum-app`]: https://github.com/photino/zino/tree/main/examples/axum-app
[`dioxus-desktop`]: https://github.com/photino/zino/tree/main/examples/dioxus-desktop
[`actix-app`]: https://github.com/zino-rs/zino/tree/main/examples/actix-app
[`axum-app`]: https://github.com/zino-rs/zino/tree/main/examples/axum-app
[`dioxus-desktop`]: https://github.com/zino-rs/zino/tree/main/examples/dioxus-desktop

View File

@ -56,6 +56,9 @@ where
}
});
}
runtime.block_on(async {
Self::load().await;
});
let app_env = Self::env();
let app_name = Self::name();

View File

@ -21,7 +21,7 @@ pub use zino_core::{
schedule::{AsyncCronJob, AsyncJob, AsyncJobScheduler, CronJob, Job, JobScheduler},
state::State,
validation::Validation,
warn, BoxFuture, LazyLock, Map, Record, Uuid,
warn, BoxFuture, Decimal, LazyLock, Map, Record, Uuid,
};
#[cfg(feature = "orm")]