diff --git a/src/components/custom_link/custom_link_component.rs b/src/components/custom_link/custom_link_component.rs index e69de29..92036a8 100644 --- a/src/components/custom_link/custom_link_component.rs +++ b/src/components/custom_link/custom_link_component.rs @@ -0,0 +1,14 @@ +use dioxus::prelude::*; +use crate::components::custom_link::custom_link_props::CustomLinkProps; + +#[allow(non_snake_case)] +pub fn CustomLink(props: CustomLinkProps) -> Element { + rsx! { + Link { + class: "{props.css}", + to: props.href, + active_class: "active", + { props.label }, + } + } +} diff --git a/src/components/custom_link/custom_link_props.rs b/src/components/custom_link/custom_link_props.rs index e69de29..f2beb04 100644 --- a/src/components/custom_link/custom_link_props.rs +++ b/src/components/custom_link/custom_link_props.rs @@ -0,0 +1,11 @@ +use dioxus::prelude::*; + +#[derive(Props, Clone, PartialEq)] +pub struct CustomLinkProps { + #[props(into)] + pub label: String, + #[props(into)] + pub href: NavigationTarget, + #[props(into)] + pub css: String, +} diff --git a/src/components/custom_link/mod.rs b/src/components/custom_link/mod.rs index e69de29..f2505f9 100644 --- a/src/components/custom_link/mod.rs +++ b/src/components/custom_link/mod.rs @@ -0,0 +1,2 @@ +pub mod custom_link_component; +pub mod custom_link_props; \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs index e69de29..c73b5d6 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -0,0 +1 @@ +pub mod custom_link; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..03fd349 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,43 @@ +mod views; +mod components; + +use dioxus::prelude::*; +use crate::views::editor::dionotes_editor::EditorRoute; +use crate::views::workspace_selector::selector::WorkspaceRoute; + +const FAVICON: Asset = asset!("/assets/favicon.ico"); + +// Linked individually rather than via @import in a single entry file: asset!() +// only emits files it is given by name, so an @import chain would 404 at runtime. +// Order matters — tokens, then baseline, then layout, then components. +const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css"); +const TOKENS_CSS: Asset = asset!("/assets/css/tokens.css"); +const BASE_CSS: Asset = asset!("/assets/css/base.css"); +const LAYOUT_CSS: Asset = asset!("/assets/css/layout.css"); +const COMPONENTS_CSS: Asset = asset!("/assets/css/components.css"); + +fn main() { + launch(App); +} + +#[component] +fn App() -> Element { + let workspace_selected: Signal = use_signal(|| false); + rsx! { + document::Link { rel: "icon", href: FAVICON } + // Tailwind first: its preflight lives in @layer base, our unlayered + // rules win the cascade regardless, but this keeps source order honest. + document::Link { rel: "stylesheet", href: TAILWIND_CSS } + document::Link { rel: "stylesheet", href: TOKENS_CSS } + document::Link { rel: "stylesheet", href: BASE_CSS } + document::Link { rel: "stylesheet", href: LAYOUT_CSS } + document::Link { rel: "stylesheet", href: COMPONENTS_CSS } + if workspace_selected() { + Router:: {} + } else { + Router:: {} + } + } +} + + diff --git a/src/views/editor/dionotes_editor.rs b/src/views/editor/dionotes_editor.rs index e69de29..5895874 100644 --- a/src/views/editor/dionotes_editor.rs +++ b/src/views/editor/dionotes_editor.rs @@ -0,0 +1,86 @@ +use dioxus::prelude::*; +use dioxus_code::Theme; +use dioxus_code_editor::{CodeEditor, Language}; +use crate::components::custom_link::custom_link_component::CustomLink; +use strum::{EnumMessage, IntoEnumIterator}; +use strum_macros::EnumIter; + +const HEADER_SVG: Asset = asset!("/assets/header.svg"); + +#[derive(Debug, Clone, Routable, PartialEq, EnumIter, EnumMessage)] +#[rustfmt::skip] +pub enum EditorRoute { + #[layout(Navbar)] + #[route("/")] + #[strum(message = "Home")] + Home {}, + #[route("/editor")] + #[strum(message = "Editor")] + Editor {}, +} + +/// Home page +#[component] +fn Home() -> Element { + rsx! { + Hero {} + } +} + +#[component] +pub fn Hero() -> Element { + rsx! { + div { + id: "hero", + img { src: HEADER_SVG, id: "header" } + div { id: "links", + a { href: "https://dioxuslabs.com/learn/0.7/", "📚 Learn Dioxus" } + a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" } + a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" } + a { href: "https://github.com/DioxusLabs/sdk", "⚙️ Dioxus Development Kit" } + a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" } + a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" } + } + } + } +} + +#[component] +fn Editor() -> Element { + let mut source = use_signal(String::new); + + rsx! { + CodeEditor { + class: "editor-class", + value: source(), + language: Language::Markdown, + theme: Theme::CATPPUCCIN_MOCHA, + oninput: move |value| source.set(value), + } + } +} + +/// Shared navbar component. +#[component] +fn Navbar() -> Element { + rsx! { + div { + class: "layout-container", + div { + class: "files-bar", + for entry in EditorRoute::iter() { + CustomLink { + key: "{entry}", + label: entry.get_message().unwrap_or_default(), + href: entry.clone(), + css: "file-selector" + } + } + } + div { + class: "editor-container", + Outlet:: { } + } + } + } +} \ No newline at end of file diff --git a/src/views/editor/mod.rs b/src/views/editor/mod.rs new file mode 100644 index 0000000..d760eb3 --- /dev/null +++ b/src/views/editor/mod.rs @@ -0,0 +1 @@ +pub mod dionotes_editor; \ No newline at end of file diff --git a/src/views/mod.rs b/src/views/mod.rs new file mode 100644 index 0000000..f0c3a43 --- /dev/null +++ b/src/views/mod.rs @@ -0,0 +1,2 @@ +pub mod editor; +pub mod workspace_selector; \ No newline at end of file diff --git a/src/views/workspace_selector/create_new_workspace.rs b/src/views/workspace_selector/create_new_workspace.rs index e69de29..76a4e86 100644 --- a/src/views/workspace_selector/create_new_workspace.rs +++ b/src/views/workspace_selector/create_new_workspace.rs @@ -0,0 +1,11 @@ +use dioxus::prelude::*; + +/// Create new Workspace Layout +// TODO: Platzhalter — Formular zum Anlegen eines Workspace (Name, Pfad) und +// Verdrahtung als Ziel von WorkspaceRoute::NewWorkspace fehlen noch. +#[component] +fn NewWorkspaceLayout() -> Element { + rsx! { + div {} + } +} \ No newline at end of file diff --git a/src/views/workspace_selector/mod.rs b/src/views/workspace_selector/mod.rs new file mode 100644 index 0000000..94569ef --- /dev/null +++ b/src/views/workspace_selector/mod.rs @@ -0,0 +1,2 @@ +pub mod selector; +pub mod create_new_workspace; \ No newline at end of file diff --git a/src/views/workspace_selector/selector.rs b/src/views/workspace_selector/selector.rs index e69de29..dbddde8 100644 --- a/src/views/workspace_selector/selector.rs +++ b/src/views/workspace_selector/selector.rs @@ -0,0 +1,61 @@ +use dioxus::prelude::*; +use strum::{EnumMessage, IntoEnumIterator}; +use strum_macros::EnumIter; +use crate::components::custom_link::custom_link_component::CustomLink; + +#[derive(Debug, Clone, Routable, PartialEq, EnumIter, EnumMessage)] +#[rustfmt::skip] +pub enum WorkspaceRoute { + #[layout(Workspace)] + #[route("/")] + #[strum(message = "Create new Workspace")] + NewWorkspace {}, + #[route("/ws_open")] + #[strum(message = "Open Workspace")] + OpenWorkspace {}, +} + +/// Page to create new Workspace +#[component] +fn NewWorkspace() -> Element { + rsx! { + div { + "New Workspace", + } + } +} + +/// Page to open available Workspaces +#[component] +fn OpenWorkspace() -> Element { + rsx! { + div { + "Open Workspace", + } + } +} + +/// Workspace Layout +#[component] +fn Workspace() -> Element { + rsx! { + div { + class: "workspace-selector-layout", + div { + class: "workspace-selector-links", + for route in WorkspaceRoute::iter() { + CustomLink { + key: "{route}", + label: route.get_message().unwrap_or_default(), + href: route.clone(), + css: "workspace-selector", + } + } + } + div { + class: "workspace-selector-view", + Outlet:: { } + } + } + } +}