Create sidebar layout and begin on structure of pages for projects and documents
This commit is contained in:
parent
5b117e9a8c
commit
35c75cdc5c
11 changed files with 380 additions and 1080 deletions
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -341,6 +341,15 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bincode"
|
||||||
|
version = "1.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -611,6 +620,15 @@ version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.12"
|
version = "0.5.12"
|
||||||
|
@ -792,7 +810,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -828,6 +846,16 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs2"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fsevent-sys"
|
name = "fsevent-sys"
|
||||||
version = "4.1.0"
|
version = "4.1.0"
|
||||||
|
@ -892,7 +920,7 @@ checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"parking_lot",
|
"parking_lot 0.12.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -942,6 +970,15 @@ dependencies = [
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
|
@ -1244,6 +1281,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -1457,7 +1503,7 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot 0.12.1",
|
||||||
"quanta",
|
"quanta",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"skeptic",
|
"skeptic",
|
||||||
|
@ -1633,6 +1679,17 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core 0.8.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -1640,7 +1697,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"parking_lot_core",
|
"parking_lot_core 0.9.9",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"instant",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.2.16",
|
||||||
|
"smallvec",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1651,7 +1722,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
@ -1730,6 +1801,7 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-htmx",
|
"axum-htmx",
|
||||||
"axum-login",
|
"axum-login",
|
||||||
|
"bincode",
|
||||||
"clap",
|
"clap",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
@ -1738,6 +1810,7 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde",
|
"serde",
|
||||||
|
"sled",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
@ -1929,6 +2002,15 @@ dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -2430,6 +2512,22 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sled"
|
||||||
|
version = "0.34.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"fs2",
|
||||||
|
"fxhash",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"parking_lot 0.11.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.1"
|
version = "1.13.1"
|
||||||
|
@ -2884,7 +2982,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"parking_lot",
|
"parking_lot 0.12.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
|
@ -2972,7 +3070,7 @@ dependencies = [
|
||||||
"cookie",
|
"cookie",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"parking_lot",
|
"parking_lot 0.12.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
@ -3044,7 +3142,7 @@ dependencies = [
|
||||||
"base64 0.22.0",
|
"base64 0.22.0",
|
||||||
"futures",
|
"futures",
|
||||||
"http",
|
"http",
|
||||||
"parking_lot",
|
"parking_lot 0.12.1",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -3363,7 +3461,7 @@ version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9"
|
checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
"wasite",
|
"wasite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ async-trait = "0.1.78"
|
||||||
axum = "0.7.4"
|
axum = "0.7.4"
|
||||||
axum-htmx = { version = "0.5.0", features = ["guards", "serde"] }
|
axum-htmx = { version = "0.5.0", features = ["guards", "serde"] }
|
||||||
axum-login = "0.14.0"
|
axum-login = "0.14.0"
|
||||||
|
bincode = "1.3.3"
|
||||||
clap = { version = "4.5.3", features = ["derive", "env"] }
|
clap = { version = "4.5.3", features = ["derive", "env"] }
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
|
@ -21,6 +22,7 @@ minijinja-autoreload = "1.0.14"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
sea-orm = { version = "0.12.15", features = ["sqlx-sqlite", "macros", "runtime-tokio-rustls"] }
|
sea-orm = { version = "0.12.15", features = ["sqlx-sqlite", "macros", "runtime-tokio-rustls"] }
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
|
sled = "0.34.7"
|
||||||
thiserror = "1.0.58"
|
thiserror = "1.0.58"
|
||||||
tokio = { version = "1.36.0", features = ["rt", "full"] }
|
tokio = { version = "1.36.0", features = ["rt", "full"] }
|
||||||
tower-http = { version = "0.5.2", features = ["fs", "trace"] }
|
tower-http = { version = "0.5.2", features = ["fs", "trace"] }
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
use axum::response::Redirect;
|
use axum::response::Redirect;
|
||||||
use axum_login::AuthSession;
|
use axum_login::AuthSession;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::{models::Project, prelude::*};
|
||||||
|
|
||||||
pub async fn home_page(State(ctx): State<Context>, auth_session: AuthSession<Context>) -> Response {
|
pub async fn home_page(State(ctx): State<Context>, auth_session: AuthSession<Context>) -> Response {
|
||||||
if let Some(user) = auth_session.user {
|
if let Some(user) = auth_session.user {
|
||||||
|
let projects: Vec<Project> = vec![
|
||||||
|
Project {
|
||||||
|
id: 1,
|
||||||
|
owner_id: 1,
|
||||||
|
name: "Blog posts".to_owned(),
|
||||||
|
key: "BLOG".to_owned(),
|
||||||
|
},
|
||||||
|
Project {
|
||||||
|
id: 2,
|
||||||
|
owner_id: 1,
|
||||||
|
name: "Bugs (Pique)".to_owned(),
|
||||||
|
key: "BUG".to_owned(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
let values = context! {
|
let values = context! {
|
||||||
user => user,
|
user => user,
|
||||||
|
projects => projects,
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.render_resp("home.html", values)
|
ctx.render_resp("home.html", values)
|
||||||
|
|
|
@ -4,8 +4,10 @@ pub mod db;
|
||||||
pub mod entity;
|
pub mod entity;
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
|
pub mod models;
|
||||||
pub mod password;
|
pub mod password;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
|
pub mod serialize;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod templates;
|
pub mod templates;
|
||||||
|
|
23
src/models.rs
Normal file
23
src/models.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub struct Project {
|
||||||
|
pub id: u64,
|
||||||
|
pub owner_id: i32,
|
||||||
|
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
// The key is the short code, like BUG, which is used to refer to a project
|
||||||
|
// quickly and to display it more compactly. This must be unique across the
|
||||||
|
// projects a user owns.
|
||||||
|
pub key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub struct Document {
|
||||||
|
pub id: u64,
|
||||||
|
pub project_id: u64,
|
||||||
|
|
||||||
|
pub title: String,
|
||||||
|
pub content: String,
|
||||||
|
}
|
16
src/serialize.rs
Normal file
16
src/serialize.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
use bincode::{DefaultOptions, Options};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
fn bincode_options() -> impl Options {
|
||||||
|
DefaultOptions::new().with_big_endian()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialize<T: ?Sized + Serialize>(value: &T) -> Result<Vec<u8>, bincode::Error> {
|
||||||
|
let options = bincode_options();
|
||||||
|
options.serialize(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'a, T: Deserialize<'a>>(bytes: &'a [u8]) -> Result<T, bincode::Error> {
|
||||||
|
let options = bincode_options();
|
||||||
|
options.deserialize(bytes)
|
||||||
|
}
|
993
static/main.css
993
static/main.css
File diff suppressed because it is too large
Load diff
|
@ -1,46 +1,46 @@
|
||||||
let mobile_open_button = document.getElementById("mobile-menu-open-button");
|
//let mobile_open_button = document.getElementById("mobile-menu-open-button");
|
||||||
let mobile_close_button = document.getElementById("mobile-menu-close-button");
|
//let mobile_close_button = document.getElementById("mobile-menu-close-button");
|
||||||
let mobile_menu = document.getElementById("mobile-menu");
|
//let mobile_menu = document.getElementById("mobile-menu");
|
||||||
|
//
|
||||||
const profile_button = document.getElementById("profile-menu-button");
|
//const profile_button = document.getElementById("profile-menu-button");
|
||||||
let profile_dropdown = document.getElementById("profile-dropdown");
|
//let profile_dropdown = document.getElementById("profile-dropdown");
|
||||||
|
//
|
||||||
function toggle_mobile_menu() {
|
//function toggle_mobile_menu() {
|
||||||
|
//
|
||||||
if (mobile_open_button.classList.contains("block")) {
|
// if (mobile_open_button.classList.contains("block")) {
|
||||||
mobile_menu.classList.remove("hidden");
|
// mobile_menu.classList.remove("hidden");
|
||||||
mobile_open_button.classList.remove("block");
|
// mobile_open_button.classList.remove("block");
|
||||||
mobile_open_button.classList.add("hidden");
|
// mobile_open_button.classList.add("hidden");
|
||||||
mobile_close_button.classList.remove("hidden");
|
// mobile_close_button.classList.remove("hidden");
|
||||||
mobile_close_button.classList.add("block");
|
// mobile_close_button.classList.add("block");
|
||||||
} else {
|
// } else {
|
||||||
mobile_menu.classList.add("hidden");
|
// mobile_menu.classList.add("hidden");
|
||||||
mobile_close_button.classList.remove("block");
|
// mobile_close_button.classList.remove("block");
|
||||||
mobile_close_button.classList.add("hidden");
|
// mobile_close_button.classList.add("hidden");
|
||||||
mobile_open_button.classList.remove("hidden");
|
// mobile_open_button.classList.remove("hidden");
|
||||||
mobile_open_button.classList.add("block");
|
// mobile_open_button.classList.add("block");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
function toggle_profile_dropdown() {
|
//function toggle_profile_dropdown() {
|
||||||
|
//
|
||||||
if (profile_dropdown.classList.contains("hidden")) {
|
// if (profile_dropdown.classList.contains("hidden")) {
|
||||||
profile_dropdown.classList.remove("hidden");
|
// profile_dropdown.classList.remove("hidden");
|
||||||
} else {
|
// } else {
|
||||||
profile_dropdown.classList.add("hidden");
|
// profile_dropdown.classList.add("hidden");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
function hide_profile_dropdown() {
|
//function hide_profile_dropdown() {
|
||||||
let profile_dropdown = document.getElementById("profile-dropdown");
|
// let profile_dropdown = document.getElementById("profile-dropdown");
|
||||||
|
//
|
||||||
if (!profile_dropdown.classList.contains("hidden")) {
|
// if (!profile_dropdown.classList.contains("hidden")) {
|
||||||
profile_dropdown.classList.add("hidden");
|
// profile_dropdown.classList.add("hidden");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
document.addEventListener("click", (event) => {
|
//document.addEventListener("click", (event) => {
|
||||||
if (!profile_button.contains(event.target) && !profile_dropdown.contains(event.target)) {
|
// if (!profile_button.contains(event.target) && !profile_dropdown.contains(event.target)) {
|
||||||
profile_dropdown.classList.add("hidden");
|
// profile_dropdown.classList.add("hidden");
|
||||||
}
|
// }
|
||||||
});
|
//});
|
||||||
|
|
85
templates/components/sidebar.html
Normal file
85
templates/components/sidebar.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<div class="fixed inset-y-0 z-50 flex w-72 flex-col">
|
||||||
|
<div class="flex grow flex-col gap-y-5 overflow-y-auto border-r border-gray-20 bg-white px-6">
|
||||||
|
|
||||||
|
<div class="flex h-16 shrink-0 items-center">
|
||||||
|
<span class="h-8 w-auto text-xl">⛰️</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="flex flex-1 flex-col">
|
||||||
|
<ul role="list" class="flex flex-1 flex-col gap-y-7">
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<ul role="list" class="-mx-2 space-y-1">
|
||||||
|
<li>
|
||||||
|
<!-- Current: "bg-gray-50 text-indigo-600", Default: "text-gray-700 hover:text-indigo-600 hover:bg-gray-50" -->
|
||||||
|
<a href="#" class="bg-gray-50 text-indigo-600 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
|
||||||
|
<svg class="h-6 w-6 shrink-0 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
||||||
|
</svg>
|
||||||
|
Dashboard
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="#" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-50 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
|
||||||
|
<svg class="h-6 w-6 shrink-0 text-gray-400 group-hover:text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" />
|
||||||
|
</svg>
|
||||||
|
Projects
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-50 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
|
||||||
|
<svg class="h-6 w-6 shrink-0 text-gray-400 group-hover:text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" />
|
||||||
|
</svg>
|
||||||
|
Documents
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-50 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
|
||||||
|
<svg class="h-6 w-6 shrink-0 text-gray-400 group-hover:text-indigo-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155" />
|
||||||
|
</svg>
|
||||||
|
Chats
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<div class="text-xs font-semibold leading-6 text-gray-400">Your projects</div>
|
||||||
|
<ul role="list" class="-mx-2 mt-2 space-y-1">
|
||||||
|
|
||||||
|
{% for project in projects %}
|
||||||
|
<li>
|
||||||
|
<!-- Current: "bg-gray-50 text-indigo-600", Default: "text-gray-700 hover:text-indigo-600 hover:bg-gray-50" -->
|
||||||
|
<a href="#" class="text-gray-700 hover:text-indigo-600 hover:bg-gray-50 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
|
||||||
|
<span class="flex h-6 w-10 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600">{{ project.key }}</span>
|
||||||
|
<span class="truncate">{{ project.name }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="-mx-6 mt-auto">
|
||||||
|
<a href="/profile" class="flex items-center gap-x-4 px-6 py-3 text-sm font-semibold leading-6 text-gray-900 hover:bg-gray-50">
|
||||||
|
<div class="h-8 w-8 rounded-full bg-gray-50">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="sr-only">Your profile</span>
|
||||||
|
<span aria-hidden="true">{{ user.full_name }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -4,5 +4,5 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Pique</title>
|
<title>Pique</title>
|
||||||
<link rel="stylesheet" href="/static/main.css">
|
<link rel="stylesheet" href="/static/main.css">
|
||||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>👀</text></svg>"/>
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⛰️</text></svg>"/>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -2,115 +2,16 @@
|
||||||
<html lang="en" class="h-full bg-white">
|
<html lang="en" class="h-full bg-white">
|
||||||
{% include "head.html" %}
|
{% include "head.html" %}
|
||||||
<body class="h-full">
|
<body class="h-full">
|
||||||
<!--
|
|
||||||
This example requires updating your template:
|
|
||||||
|
|
||||||
```
|
<div>
|
||||||
<html class="h-full bg-gray-100">
|
{% include "components/sidebar.html" %}
|
||||||
<body class="h-full">
|
|
||||||
```
|
|
||||||
-->
|
|
||||||
<div class="min-h-full">
|
|
||||||
<nav class="bg-purple-200">
|
|
||||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
||||||
<div class="flex h-16 items-center justify-between">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
👀
|
|
||||||
</div>
|
|
||||||
<div class="hidden md:block">
|
|
||||||
<div class="ml-10 flex items-baseline space-x-4">
|
|
||||||
<!-- Current: "bg-purple-700 text-white", Default: "text-gray-700 hover:bg-purple-500 hover:bg-opacity-75" -->
|
|
||||||
<a href="#" class="bg-purple-700 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">Dashboard</a>
|
|
||||||
<a href="#" class="text-gray-700 hover:text-white hover:bg-purple-500 hover:bg-opacity-75 rounded-md px-3 py-2 text-sm font-medium">Placeholder</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="hidden md:block">
|
|
||||||
<div class="ml-4 flex items-center md:ml-6">
|
|
||||||
<!-- Profile dropdown -->
|
|
||||||
<div class="relative ml-3">
|
|
||||||
<div>
|
|
||||||
<button type="button" class="relative flex max-w-xs items-center rounded-full bg-purple-600 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-purple-600" id="profile-menu-button" aria-expanded="false" aria-haspopup="true" onClick="toggle_profile_dropdown()">
|
|
||||||
<span class="absolute -inset-1.5"></span>
|
|
||||||
<span class="sr-only">Open user menu</span>
|
|
||||||
|
|
||||||
<!-- placeholder icon -->
|
|
||||||
<span class="inline-block h-6 w-6 overflow-hidden rounded-full bg-gray-200">
|
|
||||||
<svg class="h-full w-full text-gray-400" fill="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="hidden absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1" id="profile-dropdown">
|
|
||||||
|
|
||||||
<div class="ml-3">
|
|
||||||
<div class="text-base font-medium text-gray-600">{{ user.full_name }}</div>
|
|
||||||
<div class="text-sm font-medium text-gray-400">{{ user.email }}</div>
|
|
||||||
</div>
|
|
||||||
<!-- Active: "bg-gray-100", Not Active: "" -->
|
|
||||||
<a href="/logout" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="-mr-2 flex md:hidden">
|
|
||||||
<!-- Mobile menu button -->
|
|
||||||
<button type="button" class="relative inline-flex items-center justify-center rounded-md bg-purple-600 p-2 text-purple-200 hover:bg-purple-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-purple-600" aria-controls="mobile-menu" aria-expanded="false" onClick="toggle_mobile_menu()">
|
|
||||||
<span class="absolute -inset-0.5"></span>
|
|
||||||
<span class="sr-only">Open main menu</span>
|
|
||||||
<!-- Menu open: "hidden", Menu closed: "block" -->
|
|
||||||
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" id="mobile-menu-open-button">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
|
||||||
</svg>
|
|
||||||
<!-- Menu open: "block", Menu closed: "hidden" -->
|
|
||||||
<svg class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" id="mobile-menu-close-button">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile menu, show/hide based on menu state. -->
|
|
||||||
<div class="md:hidden hidden" id="mobile-menu">
|
|
||||||
<div class="space-y-1 px-2 pb-3 pt-2 sm:px-3">
|
|
||||||
<!-- Current: "bg-purple-700 text-white", Default: "text-white hover:bg-purple-500 hover:bg-opacity-75" -->
|
|
||||||
<a href="#" class="bg-purple-700 text-white block rounded-md px-3 py-2 text-base font-medium" aria-current="page">Dashboard</a>
|
|
||||||
<a href="#" class="text-gray-700 hover:text-white hover:bg-purple-500 hover:bg-opacity-75 block rounded-md px-3 py-2 text-base font-medium">Placeholder</a>
|
|
||||||
</div>
|
|
||||||
<div class="border-t border-purple-700 pb-3 pt-4">
|
|
||||||
<div class="flex items-center px-5">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<!-- placeholder icon -->
|
|
||||||
<span class="inline-block h-6 w-6 overflow-hidden rounded-full bg-gray-200">
|
|
||||||
<svg class="h-full w-full text-gray-400" fill="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="ml-3">
|
|
||||||
<div class="text-base font-medium text-gray-600">{{ user.full_name }}</div>
|
|
||||||
<div class="text-sm font-medium text-gray-400">{{ user.email }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-3 space-y-1 px-2">
|
|
||||||
<a href="/logout" class="block rounded-md px-3 py-2 text-base font-medium text-gray-700 hover:bg-purple-500 hover:bg-opacity-75">Sign out</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8">
|
|
||||||
|
|
||||||
Hi there!
|
|
||||||
|
|
||||||
|
<main class="py-10 pl-72">
|
||||||
|
<div class="px-8">
|
||||||
|
Main content.
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/main.js"></script>
|
<script type="text/javascript" src="/static/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue