Initial State
This commit is contained in:
commit
261577bfc7
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/ui/target
|
1565
Cargo.lock
generated
Normal file
1565
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "kttd"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "0.6.18", features = ["tracing", "http2"] }
|
||||
chrono = { version = "0.4.24", features = ["serde"] }
|
||||
ctxerr = "0.2.5"
|
||||
diesel = { version = "2.0.4", features = ["chrono"] }
|
||||
diesel-async = { version = "0.2.2", features = ["postgres", "tokio-postgres", "deadpool"] }
|
||||
serde = { version = "1.0.163", features = ["derive"] }
|
||||
tokio = { version = "1.28.0", features = ["parking_lot", "macros", "rt", "rt-multi-thread"] }
|
8
diesel.toml
Normal file
8
diesel.toml
Normal file
@ -0,0 +1,8 @@
|
||||
# For documentation on how to configure this file,
|
||||
# see https://diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/schema.rs"
|
||||
|
||||
[migrations_directory]
|
||||
dir = "migrations"
|
0
migrations/.keep
Normal file
0
migrations/.keep
Normal file
6
migrations/00000000000000_diesel_initial_setup/down.sql
Normal file
6
migrations/00000000000000_diesel_initial_setup/down.sql
Normal file
@ -0,0 +1,6 @@
|
||||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
||||
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
36
migrations/00000000000000_diesel_initial_setup/up.sql
Normal file
36
migrations/00000000000000_diesel_initial_setup/up.sql
Normal file
@ -0,0 +1,36 @@
|
||||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
|
||||
|
||||
|
||||
-- Sets up a trigger for the given table to automatically set a column called
|
||||
-- `updated_at` whenever the row is modified (unless `updated_at` was included
|
||||
-- in the modified columns)
|
||||
--
|
||||
-- # Example
|
||||
--
|
||||
-- ```sql
|
||||
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
|
||||
--
|
||||
-- SELECT diesel_manage_updated_at('users');
|
||||
-- ```
|
||||
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
||||
BEGIN
|
||||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
||||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
IF (
|
||||
NEW IS DISTINCT FROM OLD AND
|
||||
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
||||
) THEN
|
||||
NEW.updated_at := current_timestamp;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
1
migrations/2023-05-11-145250_create_users/down.sql
Normal file
1
migrations/2023-05-11-145250_create_users/down.sql
Normal file
@ -0,0 +1 @@
|
||||
-- This file should undo anything in `up.sql`
|
10
migrations/2023-05-11-145250_create_users/up.sql
Normal file
10
migrations/2023-05-11-145250_create_users/up.sql
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
image_id INTEGER,
|
||||
first_name VARCHAR NOT NULL,
|
||||
last_name VARCHAR NOT NULL,
|
||||
email VARCHAR NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
)
|
1
migrations/2023-05-11-145320_create_items/down.sql
Normal file
1
migrations/2023-05-11-145320_create_items/down.sql
Normal file
@ -0,0 +1 @@
|
||||
-- This file should undo anything in `up.sql`
|
1
migrations/2023-05-11-145320_create_items/up.sql
Normal file
1
migrations/2023-05-11-145320_create_items/up.sql
Normal file
@ -0,0 +1 @@
|
||||
-- Your SQL goes here
|
1
migrations/2023-05-11-145323_create_locations/down.sql
Normal file
1
migrations/2023-05-11-145323_create_locations/down.sql
Normal file
@ -0,0 +1 @@
|
||||
-- This file should undo anything in `up.sql`
|
1
migrations/2023-05-11-145323_create_locations/up.sql
Normal file
1
migrations/2023-05-11-145323_create_locations/up.sql
Normal file
@ -0,0 +1 @@
|
||||
-- Your SQL goes here
|
1
migrations/2023-05-11-145327_create_tasks/down.sql
Normal file
1
migrations/2023-05-11-145327_create_tasks/down.sql
Normal file
@ -0,0 +1 @@
|
||||
-- This file should undo anything in `up.sql`
|
1
migrations/2023-05-11-145327_create_tasks/up.sql
Normal file
1
migrations/2023-05-11-145327_create_tasks/up.sql
Normal file
@ -0,0 +1 @@
|
||||
-- Your SQL goes here
|
35
src/api/mod.rs
Normal file
35
src/api/mod.rs
Normal file
@ -0,0 +1,35 @@
|
||||
mod user;
|
||||
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
|
||||
use crate::db::DbPool;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ApiState {
|
||||
pub pool: DbPool,
|
||||
}
|
||||
|
||||
pub async fn start_server(state: ApiState) {
|
||||
// initialize tracing
|
||||
// tracing_subscriber::fmt::init();
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
.route("/", get(root))
|
||||
.route("/users", post(user::create_user))
|
||||
.route("/users", get(user::list_user))
|
||||
.with_state(state);
|
||||
|
||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
||||
.serve(app.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// basic handler that responds with a static string
|
||||
async fn root() -> &'static str {
|
||||
"Hello, World!"
|
||||
}
|
47
src/api/user.rs
Normal file
47
src/api/user.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use axum::{extract::State, http::StatusCode, Json};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::db::{
|
||||
models::user::{NewUser, User},
|
||||
repos,
|
||||
};
|
||||
|
||||
use super::ApiState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ApiUser {
|
||||
first_name: String,
|
||||
last_name: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
pub async fn create_user(
|
||||
State(s): State<ApiState>,
|
||||
Json(payload): Json<ApiUser>,
|
||||
) -> Result<Json<User>, (StatusCode, String)> {
|
||||
let user = repos::user::create_user(
|
||||
&s.pool,
|
||||
NewUser {
|
||||
first_name: &payload.first_name,
|
||||
last_name: &payload.last_name,
|
||||
email: &payload.email,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(internal_error)?;
|
||||
|
||||
Ok(Json(user))
|
||||
}
|
||||
|
||||
pub async fn list_user(State(s): State<ApiState>) -> (StatusCode, Json<Vec<User>>) {
|
||||
let user = repos::user::list_users(&s.pool).await.unwrap();
|
||||
|
||||
(StatusCode::CREATED, Json(user))
|
||||
}
|
||||
|
||||
fn internal_error<E>(err: E) -> (StatusCode, String)
|
||||
where
|
||||
E: std::error::Error,
|
||||
{
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
|
||||
}
|
13
src/db/mod.rs
Normal file
13
src/db/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
pub mod models;
|
||||
pub mod repos;
|
||||
pub mod schema;
|
||||
|
||||
use diesel_async::pg::AsyncPgConnection;
|
||||
use diesel_async::pooled_connection::deadpool::Pool;
|
||||
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
|
||||
|
||||
pub type DbPool = Pool<AsyncPgConnection>;
|
||||
|
||||
pub async fn connect<S: Into<String>>(durl: S) -> Result<DbPool, crate::error::Error> {
|
||||
Ok(DbPool::builder(AsyncDieselConnectionManager::new(durl)).build()?)
|
||||
}
|
0
src/db/models/image.rs
Normal file
0
src/db/models/image.rs
Normal file
0
src/db/models/item.rs
Normal file
0
src/db/models/item.rs
Normal file
0
src/db/models/location.rs
Normal file
0
src/db/models/location.rs
Normal file
6
src/db/models/mod.rs
Normal file
6
src/db/models/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
pub mod image;
|
||||
pub mod item;
|
||||
pub mod location;
|
||||
pub mod role;
|
||||
pub mod tag;
|
||||
pub mod user;
|
0
src/db/models/role.rs
Normal file
0
src/db/models/role.rs
Normal file
0
src/db/models/tag.rs
Normal file
0
src/db/models/tag.rs
Normal file
24
src/db/models/user.rs
Normal file
24
src/db/models/user.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::db::schema::users;
|
||||
|
||||
#[derive(Debug, Serialize, Clone, Queryable, Selectable, Identifiable)]
|
||||
#[diesel(table_name = users)]
|
||||
pub struct User {
|
||||
pub id: i32,
|
||||
pub image_id: Option<i32>,
|
||||
pub first_name: String,
|
||||
pub last_name: String,
|
||||
pub email: String,
|
||||
pub created_at: chrono::NaiveDateTime,
|
||||
pub updated_at: chrono::NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Insertable)]
|
||||
#[diesel(table_name = users)]
|
||||
pub struct NewUser<'a> {
|
||||
pub first_name: &'a str,
|
||||
pub last_name: &'a str,
|
||||
pub email: &'a str,
|
||||
}
|
0
src/db/repos/items.rs
Normal file
0
src/db/repos/items.rs
Normal file
0
src/db/repos/location.rs
Normal file
0
src/db/repos/location.rs
Normal file
3
src/db/repos/mod.rs
Normal file
3
src/db/repos/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod items;
|
||||
pub mod location;
|
||||
pub mod user;
|
25
src/db/repos/user.rs
Normal file
25
src/db/repos/user.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use diesel::prelude::*;
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
use crate::db::models::user::NewUser;
|
||||
use crate::db::schema::users;
|
||||
use crate::db::{models::user::User, DbPool};
|
||||
use crate::Error;
|
||||
|
||||
pub async fn create_user<'a>(pool: &DbPool, user: NewUser<'a>) -> Result<User, Error> {
|
||||
let mut conn = pool.get().await?;
|
||||
|
||||
Ok(diesel::insert_into(users::table)
|
||||
.values(&user)
|
||||
.get_result(&mut conn)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn list_users(pool: &DbPool) -> Result<Vec<User>, Error> {
|
||||
let mut conn = pool.get().await?;
|
||||
|
||||
Ok(users::table
|
||||
.select(User::as_select())
|
||||
.load(&mut conn)
|
||||
.await?)
|
||||
}
|
108
src/db/schema.rs
Normal file
108
src/db/schema.rs
Normal file
@ -0,0 +1,108 @@
|
||||
diesel::table! {
|
||||
users {
|
||||
id -> Int4,
|
||||
image_id -> Nullable<Int4>,
|
||||
first_name -> VarChar,
|
||||
last_name -> VarChar,
|
||||
email -> VarChar,
|
||||
created_at -> Timestamp,
|
||||
updated_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
user_schedule {
|
||||
id -> Int4,
|
||||
user_id -> Int4,
|
||||
created_at -> Timestamp,
|
||||
updated_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
items {
|
||||
id -> Int4,
|
||||
title -> VarChar,
|
||||
image_id -> Nullable<Int4>,
|
||||
location_id -> Nullable<Int4>,
|
||||
description -> Text,
|
||||
created_by -> Int4,
|
||||
created_at -> Timestamp,
|
||||
updated_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
images {
|
||||
id -> Int4,
|
||||
title -> VarChar,
|
||||
url -> VarChar,
|
||||
created_at -> Timestamp,
|
||||
updated_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
item_image {
|
||||
id -> Int4,
|
||||
item_id -> Int4,
|
||||
image_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
locations {
|
||||
id -> Int4,
|
||||
parent_id -> Nullable<Int4>,
|
||||
image_id -> Nullable<Int4>,
|
||||
title -> VarChar,
|
||||
description -> Text,
|
||||
created_by -> Int4,
|
||||
created_at -> Timestamp,
|
||||
updated_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
location_image {
|
||||
id -> Int4,
|
||||
location_id -> Int4,
|
||||
image_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
tasks {
|
||||
id -> Int4,
|
||||
active -> Bool,
|
||||
title -> Varchar,
|
||||
description -> Text,
|
||||
assigned_to -> Nullable<Int4>,
|
||||
estimate_time -> Int4,
|
||||
estimate_period -> Int4,
|
||||
estimate_start_date -> Nullable<Timestamp>,
|
||||
estimate_end_date -> Nullable<Timestamp>,
|
||||
created_by -> Int4,
|
||||
created_at -> Timestamp,
|
||||
updated_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
item_task {
|
||||
id -> Int4,
|
||||
location_id -> Int4,
|
||||
image_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(users -> images (image_id));
|
||||
|
||||
diesel::joinable!(item_image -> images (image_id));
|
||||
diesel::joinable!(item_image -> items (item_id));
|
||||
|
||||
diesel::joinable!(location_image -> images (image_id));
|
||||
diesel::joinable!(location_image -> locations (location_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(items, item_image, images,);
|
||||
diesel::allow_tables_to_appear_in_same_query!(items, location_image, locations,);
|
16
src/error.rs
Normal file
16
src/error.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use ctxerr::ctxerr;
|
||||
use diesel::result;
|
||||
use diesel_async::pooled_connection::deadpool::{BuildError, PoolError};
|
||||
// use diesel_async::pooled_connection::PoolError;
|
||||
|
||||
#[ctxerr]
|
||||
pub enum ErrorKind {
|
||||
#[error("PoolError: {0}")]
|
||||
Pool(#[from] PoolError),
|
||||
|
||||
#[error("PoolBuildError: {0}")]
|
||||
PoolBuild(#[from] BuildError),
|
||||
|
||||
#[error("DieselResultError: {0}")]
|
||||
DieselResult(#[from] result::Error),
|
||||
}
|
27
src/main.rs
Normal file
27
src/main.rs
Normal file
@ -0,0 +1,27 @@
|
||||
mod api;
|
||||
mod db;
|
||||
mod error;
|
||||
|
||||
pub use error::{Error, ErrorKind};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Error> {
|
||||
let durl = std::env::var("DATABASE_URL")
|
||||
.unwrap_or_else(|_| "postgres://postgres@127.0.0.1:5432/kttd".to_string());
|
||||
|
||||
let pool = db::connect(durl).await?;
|
||||
|
||||
// repos::user::create_user(
|
||||
// &pool,
|
||||
// db::models::user::NewUser {
|
||||
// first_name: "Andrey",
|
||||
// last_name: "Tkachenko",
|
||||
// email: "andrey@aidev.ru",
|
||||
// },
|
||||
// )
|
||||
// .await?;
|
||||
|
||||
api::start_server(api::ApiState { pool }).await;
|
||||
|
||||
Ok(())
|
||||
}
|
1658
ui/Cargo.lock
generated
Normal file
1658
ui/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
10
ui/Cargo.toml
Normal file
10
ui/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "ui"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = "0.3.2"
|
||||
dioxus-web = "0.3.1"
|
1029
ui/dist/assets/dioxus/dioxus.js
vendored
Normal file
1029
ui/dist/assets/dioxus/dioxus.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
ui/dist/assets/dioxus/dioxus_bg.wasm
vendored
Normal file
BIN
ui/dist/assets/dioxus/dioxus_bg.wasm
vendored
Normal file
Binary file not shown.
180
ui/dist/assets/dioxus/snippets/dioxus-interpreter-js-1676574062e4c953/inline0.js
vendored
Normal file
180
ui/dist/assets/dioxus/snippets/dioxus-interpreter-js-1676574062e4c953/inline0.js
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
let m,p,ls,lss,sp,d,t,c,s,sl,op,i,e,z,index,bubbles,n,len,field,root,text,ns,value,ptr,many,event_name,tmpl_id,id;const ns_cache = [];const evt = [];const attr = [];
|
||||
class ListenerMap {
|
||||
constructor(root) {
|
||||
// bubbling events can listen at the root element
|
||||
this.global = {};
|
||||
// non bubbling events listen at the element the listener was created at
|
||||
this.local = {};
|
||||
this.root = null;
|
||||
this.handler = null;
|
||||
}
|
||||
|
||||
create(event_name, element, bubbles) {
|
||||
if (bubbles) {
|
||||
if (this.global[event_name] === undefined) {
|
||||
this.global[event_name] = {};
|
||||
this.global[event_name].active = 1;
|
||||
this.root.addEventListener(event_name, this.handler);
|
||||
} else {
|
||||
this.global[event_name].active++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const id = element.getAttribute("data-dioxus-id");
|
||||
if (!this.local[id]) {
|
||||
this.local[id] = {};
|
||||
}
|
||||
element.addEventListener(event_name, this.handler);
|
||||
}
|
||||
}
|
||||
|
||||
remove(element, event_name, bubbles) {
|
||||
if (bubbles) {
|
||||
this.global[event_name].active--;
|
||||
if (this.global[event_name].active === 0) {
|
||||
this.root.removeEventListener(event_name, this.global[event_name].callback);
|
||||
delete this.global[event_name];
|
||||
}
|
||||
}
|
||||
else {
|
||||
const id = element.getAttribute("data-dioxus-id");
|
||||
delete this.local[id][event_name];
|
||||
if (this.local[id].length === 0) {
|
||||
delete this.local[id];
|
||||
}
|
||||
element.removeEventListener(event_name, this.handler);
|
||||
}
|
||||
}
|
||||
|
||||
removeAllNonBubbling(element) {
|
||||
const id = element.getAttribute("data-dioxus-id");
|
||||
delete this.local[id];
|
||||
}
|
||||
}
|
||||
function SetAttributeInner(node, field, value, ns) {
|
||||
const name = field;
|
||||
if (ns === "style") {
|
||||
// ????? why do we need to do this
|
||||
if (node.style === undefined) {
|
||||
node.style = {};
|
||||
}
|
||||
node.style[name] = value;
|
||||
} else if (ns !== null && ns !== undefined && ns !== "") {
|
||||
node.setAttributeNS(ns, name, value);
|
||||
} else {
|
||||
switch (name) {
|
||||
case "value":
|
||||
if (value !== node.value) {
|
||||
node.value = value;
|
||||
}
|
||||
break;
|
||||
case "checked":
|
||||
node.checked = value === "true";
|
||||
break;
|
||||
case "selected":
|
||||
node.selected = value === "true";
|
||||
break;
|
||||
case "dangerous_inner_html":
|
||||
node.innerHTML = value;
|
||||
break;
|
||||
default:
|
||||
// https://github.com/facebook/react/blob/8b88ac2592c5f555f315f9440cbb665dd1e7457a/packages/react-dom/src/shared/DOMProperty.js#L352-L364
|
||||
if (value === "false" && bool_attrs.hasOwnProperty(name)) {
|
||||
node.removeAttribute(name);
|
||||
} else {
|
||||
node.setAttribute(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function LoadChild(ptr, len) {
|
||||
// iterate through each number and get that child
|
||||
node = stack[stack.length - 1];
|
||||
ptr_end = ptr + len;
|
||||
for (; ptr < ptr_end; ptr++) {
|
||||
end = m.getUint8(ptr);
|
||||
for (node = node.firstChild; end > 0; end--) {
|
||||
node = node.nextSibling;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
const listeners = new ListenerMap();
|
||||
let nodes = [];
|
||||
let stack = [];
|
||||
const templates = {};
|
||||
let node, els, end, ptr_end, k;
|
||||
export function save_template(nodes, tmpl_id) {
|
||||
templates[tmpl_id] = nodes;
|
||||
}
|
||||
export function set_node(id, node) {
|
||||
nodes[id] = node;
|
||||
}
|
||||
export function initilize(root, handler) {
|
||||
listeners.handler = handler;
|
||||
nodes = [root];
|
||||
stack = [root];
|
||||
listeners.root = root;
|
||||
}
|
||||
function AppendChildren(id, many){
|
||||
root = nodes[id];
|
||||
els = stack.splice(stack.length-many);
|
||||
for (k = 0; k < many; k++) {
|
||||
root.appendChild(els[k]);
|
||||
}
|
||||
}
|
||||
const bool_attrs = {
|
||||
allowfullscreen: true,
|
||||
allowpaymentrequest: true,
|
||||
async: true,
|
||||
autofocus: true,
|
||||
autoplay: true,
|
||||
checked: true,
|
||||
controls: true,
|
||||
default: true,
|
||||
defer: true,
|
||||
disabled: true,
|
||||
formnovalidate: true,
|
||||
hidden: true,
|
||||
ismap: true,
|
||||
itemscope: true,
|
||||
loop: true,
|
||||
multiple: true,
|
||||
muted: true,
|
||||
nomodule: true,
|
||||
novalidate: true,
|
||||
open: true,
|
||||
playsinline: true,
|
||||
readonly: true,
|
||||
required: true,
|
||||
reversed: true,
|
||||
selected: true,
|
||||
truespeed: true,
|
||||
};
|
||||
export function create(r){d=r;c=new TextDecoder('utf-8',{fatal:true})}export function update_memory(r){m=new DataView(r.buffer)}export function set_buffer(b){m=new DataView(b)}export function run(){t=m.getUint8(d,true);if(t&1){ls=m.getUint32(d+1,true)}p=ls;if(t&2){lss=m.getUint32(d+5,true)}if(t&4){sl=m.getUint32(d+9,true);if(t&8){sp=lss;s="";e=sp+(sl/4|0)*4;while(sp<e){t=m.getUint32(sp,true);s+=String.fromCharCode(t&255,(t&65280)>>8,(t&16711680)>>16,t>>24);sp+=4}while(sp<lss+sl){s+=String.fromCharCode(m.getUint8(sp++));}}else{s=c.decode(new DataView(m.buffer,lss,sl))}sp=0}for(;;){op=m.getUint32(p,true);p+=4;z=0;while(z++<4){switch(op&255){case 0:{AppendChildren(root, stack.length-1);}break;case 1:{stack.push(nodes[m.getUint32(p,true)]);}p+=4;break;case 2:id=m.getUint32(p,true);p += 4;{AppendChildren(id, m.getUint32(p,true));}p+=4;break;case 3:{stack.pop();}break;case 4:id=m.getUint32(p,true);p += 4;{root = nodes[id]; els = stack.splice(stack.length-m.getUint32(p,true)); if (root.listening) { listeners.removeAllNonBubbling(root); } root.replaceWith(...els);}p+=4;break;case 5:id=m.getUint32(p,true);p += 4;{nodes[id].after(...stack.splice(stack.length-m.getUint32(p,true)));}p+=4;break;case 6:id=m.getUint32(p,true);p += 4;{nodes[id].before(...stack.splice(stack.length-m.getUint32(p,true)));}p+=4;break;case 7:{node = nodes[m.getUint32(p,true)]; if (node !== undefined) { if (node.listening) { listeners.removeAllNonBubbling(node); } node.remove(); }}p+=4;break;case 8:{stack.push(document.createTextNode(s.substring(sp,sp+=m.getUint32(p,true))));}p+=4;break;case 9:text=s.substring(sp,sp+=m.getUint32(p,true));p += 4;{node = document.createTextNode(text); nodes[m.getUint32(p,true)] = node; stack.push(node);}p+=4;break;case 10:{node = document.createElement('pre'); node.hidden = true; stack.push(node); nodes[m.getUint32(p,true)] = node;}p+=4;break;case 11:id=m.getUint32(p,true);p += 4;i=m.getUint32(p,true);if((i&128)!=0){event_name=s.substring(sp,sp+=(i>>>8)&255);evt[i&127]=event_name;}else{event_name=evt[i&127];}node = nodes[id]; if(node.listening){node.listening += 1;}else{node.listening = 1;} node.setAttribute('data-dioxus-id', `${id}`); listeners.create(event_name, node, (i>>>16)&255);p+=3;break;case 12:i=m.getUint32(p,true);p += 3;if((i&128)!=0){event_name=s.substring(sp,sp+=(i>>>8)&255);evt[i&127]=event_name;}else{event_name=evt[i&127];}bubbles=(i>>>16)&255;{node = nodes[m.getUint32(p,true)]; node.listening -= 1; node.removeAttribute('data-dioxus-id'); listeners.remove(node, event_name, bubbles);}p+=4;break;case 13:id=m.getUint32(p,true);p += 4;{nodes[id].textContent = s.substring(sp,sp+=m.getUint32(p,true));}p+=4;break;case 14:i=m.getUint32(p,true);p += 4;if((i&128)!=0){ns=s.substring(sp,sp+=(i>>>8)&255);ns_cache[i&127]=ns;}else{ns=ns_cache[i&127];}if((i&8388608)!=0){field=s.substring(sp,sp+=i>>>24);attr[(i>>>16)&127]=field;}else{field=attr[(i>>>16)&127];}id=m.getUint32(p,true);p += 4;{node = nodes[id]; SetAttributeInner(node, field, s.substring(sp,sp+=m.getUint32(p,true)), ns);}p+=4;break;case 15:i=m.getUint32(p,true);p += 4;if((i&128)!=0){ns=s.substring(sp,sp+=(i>>>8)&255);ns_cache[i&127]=ns;}else{ns=ns_cache[i&127];}if((i&8388608)!=0){field=s.substring(sp,sp+=i>>>24);attr[(i>>>16)&127]=field;}else{field=attr[(i>>>16)&127];}{name = field;
|
||||
node = nodes[m.getUint32(p,true)];
|
||||
if (ns == "style") {
|
||||
node.style.removeProperty(name);
|
||||
} else if (ns !== null && ns !== undefined && ns !== "") {
|
||||
node.removeAttributeNS(ns, name);
|
||||
} else if (name === "value") {
|
||||
node.value = "";
|
||||
} else if (name === "checked") {
|
||||
node.checked = false;
|
||||
} else if (name === "selected") {
|
||||
node.selected = false;
|
||||
} else if (name === "dangerous_inner_html") {
|
||||
node.innerHTML = "";
|
||||
} else {
|
||||
node.removeAttribute(name);
|
||||
}}p+=4;break;case 16:len=m.getUint8(p,true);p += 1;ptr=m.getUint32(p,true);p += 4;{nodes[m.getUint32(p,true)] = LoadChild(ptr, len);}p+=4;break;case 17:len=m.getUint8(p,true);p += 1;value=s.substring(sp,sp+=m.getUint32(p,true));p += 4;ptr=m.getUint32(p,true);p += 4;{
|
||||
node = LoadChild(ptr, len);
|
||||
if (node.nodeType == Node.TEXT_NODE) {
|
||||
node.textContent = value;
|
||||
} else {
|
||||
let text = document.createTextNode(value);
|
||||
node.replaceWith(text);
|
||||
node = text;
|
||||
}
|
||||
nodes[m.getUint32(p,true)] = node;
|
||||
}p+=4;break;case 18:len=m.getUint8(p,true);p += 1;ptr=m.getUint32(p,true);p += 4;{els = stack.splice(stack.length - m.getUint32(p,true)); node = LoadChild(ptr, len); node.replaceWith(...els);}p+=4;break;case 19:tmpl_id=m.getUint32(p,true);p += 4;index=m.getUint32(p,true);p += 4;{node = templates[tmpl_id][index].cloneNode(true); nodes[m.getUint32(p,true)] = node; stack.push(node);}p+=4;break;case 20:return true;}op>>>=8;}}}
|
46
ui/dist/index.html
vendored
Normal file
46
ui/dist/index.html
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>dioxus | ⛺</title>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="main"></div>
|
||||
<script type="module">
|
||||
import init from "/./assets/dioxus/dioxus.js";
|
||||
init("/./assets/dioxus/dioxus_bg.wasm").then(wasm => {
|
||||
if (wasm.__wbindgen_start == undefined) {
|
||||
wasm.main();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html><script>// Dioxus-CLI
|
||||
// https://github.com/DioxusLabs/cli
|
||||
|
||||
(function () {
|
||||
var protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
var url = protocol + '//' + window.location.host + '/_dioxus/ws';
|
||||
var poll_interval = 8080;
|
||||
var reload_upon_connect = () => {
|
||||
window.setTimeout(
|
||||
() => {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = () => window.location.reload();
|
||||
ws.onclose = reload_upon_connect;
|
||||
},
|
||||
poll_interval);
|
||||
};
|
||||
|
||||
var ws = new WebSocket(url);
|
||||
ws.onmessage = (ev) => {
|
||||
if (ev.data == "reload") {
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
ws.onclose = reload_upon_connect;
|
||||
})()</script>
|
19
ui/src/main.rs
Normal file
19
ui/src/main.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![allow(non_snake_case)]
|
||||
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
// launch the web app
|
||||
dioxus_web::launch(App);
|
||||
}
|
||||
|
||||
// create a component that renders a div with the text "Hello, world!"
|
||||
fn App(cx: Scope) -> Element {
|
||||
let mut count = use_state(cx, || 0);
|
||||
|
||||
cx.render(rsx! {
|
||||
h1 { "High-Five counter: {count}" }
|
||||
button { onclick: move |_| count += 1, "Up high!" }
|
||||
button { onclick: move |_| count -= 1, "Down low!" }
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user