Compare commits
1 Commits
main
...
8181cc823e
| Author | SHA1 | Date | |
|---|---|---|---|
|
8181cc823e
|
11
.github/workflows/actionlint-check.yaml
vendored
11
.github/workflows/actionlint-check.yaml
vendored
@@ -26,16 +26,7 @@ jobs:
|
||||
ACTIONLINT_VERSION="1.7.5"
|
||||
|
||||
INSTALL_SCRIPT_CHECKSUM="99ab9f1d97c31c9a051e6902305f7ea9f48e7e7e1b0ee41f64aa831c86655168 download-actionlint.bash"
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
|
||||
ACTIONLINT_CHECKSUM="76e1b008a05f55effccb39355d76c74e5312fefa6c98253032a499b227d01149 actionlint"
|
||||
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
|
||||
ACTIONLINT_CHECKSUM="3d74253aa0cf645e6224fd53f2d56776998c7c05a0d3c12307463285515898f8 actionlint"
|
||||
else
|
||||
echo "Unsupported architecture: $ARCH" >&2
|
||||
exit 1
|
||||
fi
|
||||
ACTIONLINT_CHECKSUM="3d74253aa0cf645e6224fd53f2d56776998c7c05a0d3c12307463285515898f8 actionlint"
|
||||
|
||||
wget -O download-actionlint.bash "$INSTALL_SCRIPT_URL"
|
||||
echo "$INSTALL_SCRIPT_CHECKSUM" | sha256sum --check
|
||||
|
||||
2
.github/workflows/checkov-check.yaml
vendored
2
.github/workflows/checkov-check.yaml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
with:
|
||||
python-version: "3.13.1"
|
||||
- name: Rust toolchain installation
|
||||
uses: dtolnay/rust-toolchain@c2b55edffaf41a251c410bb32bed22afefa800f1 # 1.92.0
|
||||
uses: dtolnay/rust-toolchain@9bc92bc5598b4f3bec5d910d352094982cb0c3b9 # 1.92.0
|
||||
- name: code checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
|
||||
11
.github/workflows/dotenv-linter-check.yaml
vendored
11
.github/workflows/dotenv-linter-check.yaml
vendored
@@ -26,16 +26,7 @@ jobs:
|
||||
DOTENV_LINTER_VERSION="v3.3.0"
|
||||
|
||||
INSTALL_SCRIPT_CHECKSUM="3b883cbc2bc3b48b6acd794802326a50fcbfeff7d5cd61e457c54fd6072bd809 dotenv-linter-install.sh"
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
|
||||
DOTENV_LINTER_CHECKSUM="cfd8c16319d8ebfd7849016ed381f239e5e26e4ea5d957a26e32c12813658f26 dotenv-linter"
|
||||
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
|
||||
DOTENV_LINTER_CHECKSUM="4bf3efb743a1e3383ab3407ff48c6147dd527dac35b736e224a26425df00a2ee dotenv-linter"
|
||||
else
|
||||
echo "Unsupported architecture: $ARCH" >&2
|
||||
exit 1
|
||||
fi
|
||||
DOTENV_LINTER_CHECKSUM="4bf3efb743a1e3383ab3407ff48c6147dd527dac35b736e224a26425df00a2ee dotenv-linter"
|
||||
|
||||
wget -O dotenv-linter-install.sh "$INSTALL_SCRIPT_URL"
|
||||
echo "$INSTALL_SCRIPT_CHECKSUM" | sha256sum --check
|
||||
|
||||
17
.github/workflows/gitleaks-check.yaml
vendored
17
.github/workflows/gitleaks-check.yaml
vendored
@@ -22,21 +22,10 @@ jobs:
|
||||
run: |
|
||||
set -e
|
||||
|
||||
VERSION="8.22.0"
|
||||
VERSION="v8.22.0"
|
||||
CHECKSUM="3f95fef7e361adafed2b1bb9c591ba3bc6b595b4f296b346257301b7bf04be15 gitleaks.tar.gz"
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
|
||||
TARBALL="gitleaks_${VERSION}_linux_x64.tar.gz"
|
||||
CHECKSUM="ad66410e1e0bf262f864b6837b09cfa585f6b5816164023ee64847d3f7415eed gitleaks.tar.gz"
|
||||
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
|
||||
TARBALL="gitleaks_${VERSION}_linux_arm64.tar.gz"
|
||||
CHECKSUM="3f95fef7e361adafed2b1bb9c591ba3bc6b595b4f296b346257301b7bf04be15 gitleaks.tar.gz"
|
||||
else
|
||||
echo "Unsupported architecture: $ARCH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wget -O "gitleaks.tar.gz" "https://github.com/gitleaks/gitleaks/releases/download/v${VERSION}/${TARBALL}"
|
||||
wget -O "gitleaks.tar.gz" "https://github.com/gitleaks/gitleaks/releases/download/$VERSION/gitleaks_8.22.0_linux_arm64.tar.gz"
|
||||
echo "$CHECKSUM" | sha256sum --check
|
||||
|
||||
tar xzf gitleaks.tar.gz
|
||||
|
||||
17
.github/workflows/hadolint-check.yaml
vendored
17
.github/workflows/hadolint-check.yaml
vendored
@@ -22,21 +22,10 @@ jobs:
|
||||
run: |
|
||||
set -e
|
||||
|
||||
VERSION="2.12.0"
|
||||
VERSION="v2.12.0"
|
||||
CHECKSUM="5798551bf19f33951881f15eb238f90aef023f11e7ec7e9f4c37961cb87c5df6 hadolint"
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "amd64" ]; then
|
||||
ASSET="hadolint-Linux-x86_64"
|
||||
CHECKSUM="56de6d5e5ec427e17b74fa48d51271c7fc0d61244bf5c90e828aab8362d55010 hadolint"
|
||||
elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
|
||||
ASSET="hadolint-Linux-arm64"
|
||||
CHECKSUM="5798551bf19f33951881f15eb238f90aef023f11e7ec7e9f4c37961cb87c5df6 hadolint"
|
||||
else
|
||||
echo "Unsupported architecture: $ARCH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wget -O hadolint "https://github.com/hadolint/hadolint/releases/download/v${VERSION}/${ASSET}"
|
||||
wget -O hadolint "https://github.com/hadolint/hadolint/releases/download/$VERSION/hadolint-Linux-arm64"
|
||||
echo "$CHECKSUM" | sha256sum --check
|
||||
|
||||
chmod +x hadolint
|
||||
|
||||
2
.github/workflows/rust-check.yaml
vendored
2
.github/workflows/rust-check.yaml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
libwebkit2gtk-4.1-dev=2.50.4-0ubuntu0.22.04.1
|
||||
libxdo-dev=1:3.20160805.1-4
|
||||
- name: Rust toolchain installation
|
||||
uses: dtolnay/rust-toolchain@c2b55edffaf41a251c410bb32bed22afefa800f1 # 1.92.0
|
||||
uses: dtolnay/rust-toolchain@9bc92bc5598b4f3bec5d910d352094982cb0c3b9 # 1.92.0
|
||||
with:
|
||||
components: clippy, rustfmt
|
||||
- name: code checkout
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
/.env
|
||||
|
||||
/docker-compose.yaml
|
||||
/docker-compose.override.yaml
|
||||
|
||||
/node_modules
|
||||
/target
|
||||
|
||||
@@ -5,6 +5,8 @@ services:
|
||||
dockerfile: docker/prod/app/Dockerfile
|
||||
networks:
|
||||
- default
|
||||
- web-server-network
|
||||
ports: ["8000:80"]
|
||||
restart: always
|
||||
depends_on: ["db"]
|
||||
|
||||
@@ -21,3 +23,7 @@ services:
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
|
||||
networks:
|
||||
web-server-network:
|
||||
external: true
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
services:
|
||||
app:
|
||||
networks:
|
||||
- default
|
||||
- web-server-network
|
||||
|
||||
networks:
|
||||
web-server-network:
|
||||
external: true
|
||||
@@ -21,7 +21,7 @@ ENV ANDROID_SDK_ROOT=/opt/android-sdk
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
openjdk-17-jdk-headless=17.0.18+8-1~deb12u1 \
|
||||
openjdk-17-jdk-headless=17.0.17+10-1~deb12u1 \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rustup target add aarch64-linux-android \
|
||||
@@ -46,14 +46,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
|
||||
|
||||
FROM builder_base AS builder_web
|
||||
|
||||
|
||||
RUN dx bundle --locked --release
|
||||
|
||||
|
||||
FROM debian:bookworm@sha256:b877a1a3fdf02469440f1768cf69c9771338a875b7add5e80c45b756c92ac20a AS runner_web
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends libpq5=15.16-0+deb12u1 \
|
||||
&& apt-get install -y --no-install-recommends libpq5=15.10-0+deb12u1 \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ pub(crate) fn App() -> Element {
|
||||
document::Link { rel: "manifest", href: MANIFEST, crossorigin: "use-credentials" }
|
||||
|
||||
div {
|
||||
class: "min-h-screen flex flex-col text-gray-300 bg-gray-900",
|
||||
class: "min-h-screen py-4 flex flex-col text-gray-300 bg-gray-900",
|
||||
Router::<Route> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::components::navigation::Navigation;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use crate::components::navigation;
|
||||
|
||||
#[component]
|
||||
pub(crate) fn BottomPanel() -> Element {
|
||||
let navigation_expanded = use_signal(|| false);
|
||||
@@ -11,12 +10,12 @@ pub(crate) fn BottomPanel() -> Element {
|
||||
class: format!(
|
||||
"flex flex-col pointer-events-auto bg-gray-800 transition-[height] duration-[500ms] ease-[cubic-bezier(0.79,0.14,0.15,0.86)] overflow-y-scroll {}",
|
||||
if navigation_expanded() {
|
||||
"h-[132px]"
|
||||
"h-[130px]"
|
||||
} else {
|
||||
"h-[66px]"
|
||||
}
|
||||
),
|
||||
navigation::Bottom {
|
||||
Navigation {
|
||||
is_expanded: navigation_expanded,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ pub(crate) fn CategoryCalendarTaskList() -> Element {
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: "pt-3 flex flex-col gap-8",
|
||||
class: "pt-4 flex flex-col gap-8",
|
||||
for date_current in today_date.iter_days().take(CALENDAR_LENGTH_DAYS) {
|
||||
div {
|
||||
class: "flex flex-col gap-4",
|
||||
div {
|
||||
class: "px-7 sm:px-8 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
class: "px-7 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
div {
|
||||
class: "pt-1",
|
||||
{
|
||||
|
||||
@@ -2,9 +2,8 @@ use crate::components::task_list::TaskList;
|
||||
use crate::hooks::use_tasks_with_subtasks_in_category;
|
||||
use crate::internationalization::LocaleFromLanguageIdentifier;
|
||||
use crate::models::category::Category;
|
||||
use crate::models::task::{Task, TaskWithSubtasks};
|
||||
use crate::route::Route;
|
||||
use chrono::{Local, NaiveDateTime};
|
||||
use crate::models::task::TaskWithSubtasks;
|
||||
use chrono::Local;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_free_icons::Icon;
|
||||
use dioxus_free_icons::icons::fa_solid_icons::{FaCalendarCheck, FaCalendarXmark, FaWater};
|
||||
@@ -43,7 +42,6 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
|
||||
.cloned()
|
||||
.collect::<Vec<TaskWithSubtasks>>();
|
||||
let long_term_tasks = use_tasks_with_subtasks_in_category(Category::LongTerm)?;
|
||||
let inbox_tasks = use_tasks_with_subtasks_in_category(Category::Inbox)?;
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
@@ -52,7 +50,7 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
|
||||
div {
|
||||
class: "flex flex-col gap-4",
|
||||
div {
|
||||
class: "px-7 sm:px-8 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
class: "px-7 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
Icon {
|
||||
class: "mx-1.5",
|
||||
icon: FaWater
|
||||
@@ -70,7 +68,7 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
|
||||
div {
|
||||
class: "flex flex-col gap-4",
|
||||
div {
|
||||
class: "px-7 sm:px-8 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
class: "px-7 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
Icon {
|
||||
class: "mx-1.25",
|
||||
height: 22,
|
||||
@@ -90,7 +88,7 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
|
||||
div {
|
||||
class: "flex flex-col gap-4",
|
||||
div {
|
||||
class: "px-7 sm:px-8 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
class: "px-7 flex flex-row items-center gap-2 text-gray-500 font-bold",
|
||||
Icon {
|
||||
class: "mx-1.25",
|
||||
height: 22,
|
||||
@@ -118,32 +116,8 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
|
||||
}
|
||||
}
|
||||
}
|
||||
div {
|
||||
TaskList {
|
||||
tasks: today_tasks
|
||||
}
|
||||
if !inbox_tasks.is_empty() {
|
||||
Link {
|
||||
to: Route::CategoryInboxPage {},
|
||||
TaskList {
|
||||
is_interactive: false,
|
||||
tasks: vec![
|
||||
TaskWithSubtasks {
|
||||
task: Task {
|
||||
id: 0,
|
||||
title: t!("empty-inbox")._upper_first(),
|
||||
deadline: None,
|
||||
category: Category::Inbox,
|
||||
project_id: None,
|
||||
created_at: NaiveDateTime::default(),
|
||||
updated_at: NaiveDateTime::default()
|
||||
},
|
||||
subtasks: Vec::new()
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskList {
|
||||
tasks: today_tasks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ pub(crate) fn CreateButton() -> Element {
|
||||
let current_route = use_route();
|
||||
rsx! {
|
||||
ButtonPrimary {
|
||||
class: "pointer-events-auto sm:self-auto *:rounded-full! *:p-4",
|
||||
class: "pointer-events-auto m-4 self-end *:rounded-full! *:p-4",
|
||||
onclick: move |_| {
|
||||
*TASK_BEING_EDITED.write() = None;
|
||||
*PROJECT_BEING_EDITED.write() = None;
|
||||
|
||||
@@ -10,6 +10,7 @@ pub(crate) mod error_boundary_message;
|
||||
pub(crate) mod input;
|
||||
pub(crate) mod input_label;
|
||||
pub(crate) mod navigation;
|
||||
pub(crate) mod navigation_item;
|
||||
pub(crate) mod project_form;
|
||||
pub(crate) mod project_list;
|
||||
pub(crate) mod project_select;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::components::navigation_item::NavigationItem;
|
||||
use crate::route::Route;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_free_icons::Icon;
|
||||
@@ -8,13 +9,13 @@ use dioxus_free_icons::icons::fa_solid_icons::{
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub(crate) fn Bottom(is_expanded: Signal<bool>) -> Element {
|
||||
pub(crate) fn Navigation(is_expanded: Signal<bool>) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: "grid grid-cols-5 justify-stretch",
|
||||
button {
|
||||
class: format!(
|
||||
"py-2 flex flex-row justify-center items-center sm:hidden cursor-pointer",
|
||||
"py-2 flex flex-row justify-center items-center cursor-pointer",
|
||||
),
|
||||
onclick: move |_| is_expanded.set(!is_expanded()),
|
||||
div {
|
||||
@@ -29,41 +30,41 @@ pub(crate) fn Bottom(is_expanded: Signal<bool>) -> Element {
|
||||
}
|
||||
}
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryNextStepsPage,
|
||||
icon: FaSignsPost
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryCalendarPage,
|
||||
icon: FaCalendarDays
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryTodayPage,
|
||||
icon: FaCalendarDay
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryInboxPage,
|
||||
icon: FaInbox
|
||||
},
|
||||
{if is_expanded() {
|
||||
rsx! {
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::ProjectsPage,
|
||||
icon: FaList
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryTrashPage,
|
||||
icon: FaTrashCan
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryDonePage,
|
||||
icon: FaVolcano
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategorySomedayMaybePage,
|
||||
icon: FaLightbulb
|
||||
},
|
||||
super::Item {
|
||||
NavigationItem {
|
||||
route: Route::CategoryWaitingForPage,
|
||||
icon: FaHourglassHalf
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
mod bottom;
|
||||
mod item;
|
||||
mod side;
|
||||
|
||||
pub(crate) use bottom::Bottom;
|
||||
use item::Item;
|
||||
pub(crate) use side::Side;
|
||||
@@ -1,52 +0,0 @@
|
||||
use crate::route::Route;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_free_icons::icons::fa_regular_icons::FaLightbulb;
|
||||
use dioxus_free_icons::icons::fa_solid_icons::{
|
||||
FaCalendarDay, FaCalendarDays, FaHourglassHalf, FaInbox, FaList, FaSignsPost, FaTrashCan,
|
||||
FaVolcano,
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub(crate) fn Side(class: Option<String>) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: format!("flex flex-col {}", class.unwrap_or(String::new())),
|
||||
super::Item {
|
||||
route: Route::CategoryInboxPage,
|
||||
icon: FaInbox
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategoryTodayPage,
|
||||
icon: FaCalendarDay
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategoryCalendarPage,
|
||||
icon: FaCalendarDays
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategoryNextStepsPage,
|
||||
icon: FaSignsPost
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategoryWaitingForPage,
|
||||
icon: FaHourglassHalf
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategorySomedayMaybePage,
|
||||
icon: FaLightbulb
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategoryDonePage,
|
||||
icon: FaVolcano
|
||||
},
|
||||
super::Item {
|
||||
route: Route::CategoryTrashPage,
|
||||
icon: FaTrashCan
|
||||
},
|
||||
super::Item {
|
||||
route: Route::ProjectsPage,
|
||||
icon: FaList
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,17 @@ use dioxus::prelude::*;
|
||||
use dioxus_free_icons::{Icon, IconShape};
|
||||
|
||||
#[component]
|
||||
pub(crate) fn Item<I: IconShape + Clone + PartialEq + 'static>(route: Route, icon: I) -> Element {
|
||||
pub(crate) fn NavigationItem<I: IconShape + Clone + PartialEq + 'static>(
|
||||
route: Route,
|
||||
icon: I,
|
||||
) -> Element {
|
||||
let current_route = use_route::<Route>();
|
||||
|
||||
rsx! {
|
||||
Link {
|
||||
to: route.clone(),
|
||||
class: format!(
|
||||
"py-2.5 sm:px-6 flex flex-row justify-center items-center hover:*:bg-gray-900 active:*:text-gray-400",
|
||||
"py-2.5 flex flex-row justify-center items-center hover:*:bg-gray-900 active:*:text-gray-400",
|
||||
),
|
||||
div {
|
||||
class: format!("pt-2.5 px-4 {} transition-all duration-150",
|
||||
@@ -11,7 +11,7 @@ pub(crate) fn ProjectList() -> Element {
|
||||
class: "flex flex-col",
|
||||
for project in projects {
|
||||
div {
|
||||
class: "px-7 sm:px-8 py-4 hover:bg-gray-800 font-medium text-pretty wrap-anywhere select-none transition-all duration-150 cursor-pointer",
|
||||
class: "px-7 py-4 hover:bg-gray-800 font-medium text-pretty wrap-anywhere select-none transition-all duration-150 cursor-pointer",
|
||||
key: "{project.id}",
|
||||
onclick: move |_| {
|
||||
*PROJECT_BEING_EDITED.write() = Some(project.clone());
|
||||
|
||||
@@ -4,7 +4,7 @@ use dioxus::prelude::*;
|
||||
pub(crate) fn StickyBottom(children: Element) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
class: "fixed bottom-0 left-0 right-0 flex flex-col pointer-events-none sm:hidden",
|
||||
class: "fixed bottom-0 left-0 right-0 flex flex-col pointer-events-none",
|
||||
{children}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,7 @@ use dioxus::dioxus_core::Element;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub(crate) fn TaskList(
|
||||
tasks: Vec<TaskWithSubtasks>,
|
||||
/// Whether to open and complete tasks on clicks.
|
||||
is_interactive: Option<bool>,
|
||||
class: Option<&'static str>,
|
||||
) -> Element {
|
||||
pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>) -> Element {
|
||||
let navigator = use_navigator();
|
||||
rsx! {
|
||||
div {
|
||||
@@ -23,7 +18,7 @@ pub(crate) fn TaskList(
|
||||
div {
|
||||
key: "{task.task.id}",
|
||||
class: format!(
|
||||
"px-7 sm:px-8 pt-3.75 {} flex flex-row items-start gap-4 hover:bg-gray-800 cursor-pointer select-none transition-all duration-150",
|
||||
"px-7 pt-3.75 {} flex flex-row items-start gap-4 hover:bg-gray-800 cursor-pointer select-none transition-all duration-150",
|
||||
if task.task.deadline.is_some() || !task.subtasks.is_empty() {
|
||||
"pb-0.25"
|
||||
} else if let Category::Calendar { time, .. } = &task.task.category {
|
||||
@@ -39,9 +34,6 @@ pub(crate) fn TaskList(
|
||||
onclick: {
|
||||
let task = task.clone();
|
||||
move |_| {
|
||||
if let Some(false) = is_interactive {
|
||||
return;
|
||||
}
|
||||
*TASK_BEING_EDITED.write() = Some(task.task.clone());
|
||||
navigator.push(Route::TaskFormPage);
|
||||
}
|
||||
@@ -57,9 +49,6 @@ pub(crate) fn TaskList(
|
||||
// To prevent editing the task.
|
||||
event.stop_propagation();
|
||||
async move {
|
||||
if let Some(false) = is_interactive {
|
||||
return;
|
||||
}
|
||||
let _ = complete_task(task.task.id).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ yesterday = včera
|
||||
today = dnes
|
||||
tomorrow = zítra
|
||||
overdue = zpožděné
|
||||
empty-inbox = vyprázdnit schránku
|
||||
|
||||
## Date and time formats
|
||||
date-format = %-d. %B
|
||||
|
||||
@@ -4,7 +4,6 @@ yesterday = yesterday
|
||||
today = today
|
||||
tomorrow = tomorrow
|
||||
overdue = overdue
|
||||
empty-inbox = empty the inbox
|
||||
|
||||
## Date and time formats
|
||||
date-format = %B %-d
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::components;
|
||||
use crate::components::bottom_panel::BottomPanel;
|
||||
use crate::components::create_button::CreateButton;
|
||||
use crate::components::sticky_bottom::StickyBottom;
|
||||
@@ -28,24 +27,11 @@ pub(crate) fn Navigation() -> Element {
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: "grow flex flex-col sm:flex-row pb-36 sm:pb-0",
|
||||
div {
|
||||
class: "hidden sm:flex sm:flex-col gap-4 py-3.25 items-center bg-gray-800",
|
||||
components::navigation::Side {},
|
||||
div {
|
||||
CreateButton {}
|
||||
}
|
||||
}
|
||||
div {
|
||||
class: "grow flex flex-col py-4",
|
||||
Outlet::<Route> {}
|
||||
}
|
||||
class: "grow flex flex-col pb-36",
|
||||
Outlet::<Route> {}
|
||||
}
|
||||
StickyBottom {
|
||||
div {
|
||||
class: "m-4 self-end",
|
||||
CreateButton {},
|
||||
}
|
||||
CreateButton {},
|
||||
BottomPanel {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,11 +152,11 @@ pub(crate) async fn complete_task(task_id: i32) -> Result<Task> {
|
||||
*date = NaiveDate::from_ymd_opt(
|
||||
date.year(),
|
||||
date.month(),
|
||||
reoccurrence.start_date.day().min(u32::from(
|
||||
Month::try_from(u8::try_from(date.month()).unwrap())
|
||||
reoccurrence.start_date.day().min(
|
||||
u32::from(Month::try_from(u8::try_from(date.month()).unwrap())
|
||||
.unwrap()
|
||||
.length(date.year()),
|
||||
)),
|
||||
.length(date.year())),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
||||
pub(crate) fn ProjectFormPage() -> Element {
|
||||
rsx! {
|
||||
ErrorBoundaryMessage {
|
||||
class: "grow py-8 max-w-xl w-full mx-auto flex flex-col gap-12",
|
||||
class: "grow py-4 flex flex-col gap-12",
|
||||
ProjectForm {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use dioxus::prelude::*;
|
||||
pub(crate) fn TaskFormPage() -> Element {
|
||||
rsx! {
|
||||
ErrorBoundaryMessage {
|
||||
class: "grow py-8 max-w-xl w-full mx-auto flex flex-col gap-12",
|
||||
class: "grow py-4 flex flex-col gap-12",
|
||||
TaskForm {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user