From db3e2d4e0fa9801e2e860e5a77df0ce8eec4bb94 Mon Sep 17 00:00:00 2001 From: Guntis Smaukstelis Date: Wed, 17 May 2023 20:41:53 +0300 Subject: [PATCH] Implement calendar for csv viewing --- web/src/css/calendar.css | 55 ++++++++++++++++++++ web/src/fileManager/Calendar.tsx | 77 ++++++++++++++++++++++++++++ web/src/fileManager/DateList.tsx | 21 ++++---- web/src/fileManager/FileManager.tsx | 10 ++-- web/src/fileManager/FileNameList.tsx | 10 ++-- 5 files changed, 156 insertions(+), 17 deletions(-) create mode 100644 web/src/css/calendar.css create mode 100644 web/src/fileManager/Calendar.tsx diff --git a/web/src/css/calendar.css b/web/src/css/calendar.css new file mode 100644 index 0000000..e731a63 --- /dev/null +++ b/web/src/css/calendar.css @@ -0,0 +1,55 @@ +.calendar { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 5px; + } + + .calendar-top { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + } + + .calendar-nav { + display: flex; + align-items: center; + } + + .calendar-nav button { + margin-right: 5px; + background-color: #fff; + border: none; + padding: 5px; + cursor: pointer; + } + + .calendar-year-month { + text-align: center; + } + + .calendar-cell { + display: flex; + justify-content: center; + align-items: center; + height: 40px; + background-color: #fff; + } + + .prev-month, + .next-month { + opacity: 0.3; + } + + .data-date { + background-color: #99ccff; + } + + .current-date { + background-color: #ffcc66; + } + + .calendar-cell:hover { + background-color: #f2f2f2; + cursor: pointer; + } \ No newline at end of file diff --git a/web/src/fileManager/Calendar.tsx b/web/src/fileManager/Calendar.tsx new file mode 100644 index 0000000..f846162 --- /dev/null +++ b/web/src/fileManager/Calendar.tsx @@ -0,0 +1,77 @@ +import moment from "moment"; +import { Accessor, Component, createSignal, Setter } from "solid-js"; + +import "../css/calendar.css"; + +export const Calendar: Component<{ + getSelectedDate: Accessor, + setSelectedDate: Setter, + datesWithData: Date[], +}> = ({getSelectedDate, setSelectedDate, datesWithData}) => { + const dateStrArr = () => datesWithData.map(d => d.toDateString()); + + return ( +
+

Calendar

+
+ +
+ {moment(getSelectedDate()).format("YYYY, MMM")} +
+ +
+
+ { getPaddedMonth(getSelectedDate()).map(d => { + const classArr = ["calendar-cell"]; + if (d.getMonth() !== getSelectedDate().getMonth()) classArr.push("prev-month"); + if (dateStrArr().includes(d.toDateString())) classArr.push("data-date"); + if (d.toDateString() === getSelectedDate().toDateString()) classArr.push("current-date"); + return ( +
setSelectedDate(d)} + > + {d.getDate()} +
+ )})} +
+
+ ) +} + +function getPaddedMonth(date: Date): Date[] { + const firstDayOfMonth = new Date(new Date(date).setDate(1)); + const datesArr = getMonthDates(firstDayOfMonth); + + // padd start of the month + const dateIterator = new Date(firstDayOfMonth); + while (toEuropeanDay(dateIterator.getDay()) > 0) { + dateIterator.setDate(dateIterator.getDate() - 1); + datesArr.unshift(new Date(dateIterator)); + } + + // padd end of the month + dateIterator.setMonth(firstDayOfMonth.getMonth()) + dateIterator.setDate(datesArr[datesArr.length - 1].getDate()) + while (toEuropeanDay(dateIterator.getDay()) < 6) { + dateIterator.setDate(dateIterator.getDate() + 1); + datesArr.push(new Date(dateIterator)); + } + + return datesArr; +} + +function getMonthDates(firstDayOfMonth: Date): Date[] { + const date = new Date(firstDayOfMonth); + const month = date.getMonth(); + const arr: Date[] = []; + while (date.getMonth() === month) { + arr.push(new Date(date)); + date.setDate(date.getDate() + 1); + } + return arr; +} + +function toEuropeanDay(usaDay: number): number { + return --usaDay === -1 ? 6 : usaDay; +} diff --git a/web/src/fileManager/DateList.tsx b/web/src/fileManager/DateList.tsx index fa74f46..589dd62 100644 --- a/web/src/fileManager/DateList.tsx +++ b/web/src/fileManager/DateList.tsx @@ -1,9 +1,10 @@ -import { Component, createResource, Setter } from "solid-js"; +import { Accessor, Component, createResource, Setter } from "solid-js"; import { apiHost } from "../consts"; import "../css/spinner.css"; +import { Calendar } from "./Calendar"; -export const DateList: Component<{setDate: Setter;}> = (props) => { +export const DateList: Component<{getDate: Accessor, setDate: Setter;}> = (props) => { const fetchDates = async () => { await new Promise(resolve => setTimeout(resolve, 500)) const response = await fetch(`${apiHost}/api/show/all_dates`); @@ -13,11 +14,6 @@ export const DateList: Component<{setDate: Setter;}> = (props) => { const [datesResource] = createResource(fetchDates); - const clickDate = (date: string) => { - console.log("setDate", date); - props.setDate(date); - } - return (
{ datesResource.loading && ( @@ -29,11 +25,18 @@ export const DateList: Component<{setDate: Setter;}> = (props) => { { datesResource.error && (
Error while loading dates: ${datesResource.error}
)} + { datesResource() && new Date(str))} + /> } + + {/* Backup date view */} { datesResource() && (
    - { (datesResource() as any).map((date: any) => + {/* { (datesResource() as any).map((date: any) =>
  • clickDate(date)}>{date}
  • - )} + )} */}
)}
diff --git a/web/src/fileManager/FileManager.tsx b/web/src/fileManager/FileManager.tsx index 54c3257..abcf344 100644 --- a/web/src/fileManager/FileManager.tsx +++ b/web/src/fileManager/FileManager.tsx @@ -1,4 +1,6 @@ +import moment from "moment"; import { createSignal } from "solid-js"; + import "../css/FileManager.css" import { DateList } from "./DateList"; import { FetchFiles } from "./FetchFiles"; @@ -6,19 +8,21 @@ import { FileContent } from "./FileContent"; import { FileNameList } from "./FileNameList"; export function FileManager() { - const [getDate, setDate] = createSignal(""); + const [getDate, setDate] = createSignal(new Date()); const [getFileName, setFileName] = createSignal(""); + const stringDate = () => moment(getDate()).format("YYYYMMDD"); + return (

File manager

+ -
-

{getDate()}

+

{stringDate()}

diff --git a/web/src/fileManager/FileNameList.tsx b/web/src/fileManager/FileNameList.tsx index 42b5c23..e89869e 100644 --- a/web/src/fileManager/FileNameList.tsx +++ b/web/src/fileManager/FileNameList.tsx @@ -1,16 +1,16 @@ +import moment from "moment"; import { Accessor, Component, createResource, Setter } from "solid-js"; import { apiHost } from "../consts"; import "../css/spinner.css"; export const FileNameList: Component<{ - getDate: Accessor, + getDate: Accessor, setFileName: Setter, }> = (props) => { - const fetchFileNames = async (date: string) => { - if (props.getDate() === "") return; + const fetchFileNames = async (fetchDate: Date) => { await new Promise(resolve => setTimeout(resolve, 500)) - const response = await fetch(`${apiHost}/api/show/date/${date.replace(/-/g, "")}`); + const response = await fetch(`${apiHost}/api/show/date/${moment(fetchDate).format("YYYYMMDD")}`); const json = await response.json(); return json; } @@ -27,7 +27,7 @@ export const FileNameList: Component<{ { fileNameResource.loading && (
- loading {props.getDate()} + loading {moment(props.getDate()).format("YYYYMMDD")}
)} { fileNameResource.error && (