From 02a1f1be3adc110a64b719e426ddcfbf214be1a3 Mon Sep 17 00:00:00 2001 From: Yadro Date: Mon, 16 May 2022 00:45:40 +0300 Subject: [PATCH 1/7] Init Timeline --- package.json | 2 +- src/components/Header.tsx | 3 + src/screens/Main.tsx | 6 +- src/screens/hours/HoursScreen.tsx | 2 +- src/screens/timeline/TimelineScreen.tsx | 48 ++++ yarn.lock | 319 ++---------------------- 6 files changed, 72 insertions(+), 308 deletions(-) create mode 100644 src/screens/timeline/TimelineScreen.tsx diff --git a/package.json b/package.json index 7d71bb7..4d86ced 100644 --- a/package.json +++ b/package.json @@ -210,7 +210,6 @@ "jest": "^27.0.6", "lint-staged": "^10.2.11", "mini-css-extract-plugin": "^1.3.1", - "node-sass": "^5.0.0", "opencollective-postinstall": "^2.0.3", "prettier": "^2.0.5", "react-refresh": "^0.9.0", @@ -248,6 +247,7 @@ "moment": "2.29.1", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-google-charts": "4.0.0", "react-hook-media-query": "^1.0.5", "react-jss": "^10.6.0", "react-router-dom": "^5.2.0", diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 0922a97..e698c1a 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -28,6 +28,9 @@ function Header() { Dashboard + + TL + {isBigScreen && } diff --git a/src/screens/Main.tsx b/src/screens/Main.tsx index 7cc471d..6a6aace 100644 --- a/src/screens/Main.tsx +++ b/src/screens/Main.tsx @@ -4,7 +4,8 @@ import { Layout } from 'antd'; import ProjectsScreen from './projects/ProjectsScreen'; import HoursScreen from './hours/HoursScreen'; -import Dashboard from './dashboard/Dashboard'; +import DashboardScreen from './dashboard/Dashboard'; +import TimelineScreen from './timeline/TimelineScreen'; import GaService from '../services/gaService/GaService'; import Header from '../components/Header'; @@ -25,7 +26,8 @@ const Main = () => { - + + diff --git a/src/screens/hours/HoursScreen.tsx b/src/screens/hours/HoursScreen.tsx index 39110da..e40a118 100644 --- a/src/screens/hours/HoursScreen.tsx +++ b/src/screens/hours/HoursScreen.tsx @@ -1,6 +1,7 @@ import React, { useMemo, useState } from 'react'; import { Layout, Space } from 'antd'; import { observer } from 'mobx-react'; +import { createUseStyles } from 'react-jss'; import rootStore from '../../modules/RootStore'; import HoursCard from './components/HoursCard/HoursCard'; @@ -10,7 +11,6 @@ import TimeRangeModal from '../../components/TimeRangeModal/TimeRangeModal'; import TaskTimeItemModel from '../../modules/tasks/models/TaskTimeItemModel'; import { Undefined } from '../../types/CommonTypes'; import TotalHours from './components/TotalHours/TotalHours'; -import { createUseStyles } from 'react-jss'; import { mapCurrentNext } from '../../helpers/ArrayHelper'; import { ITimeRangeModel } from '../../modules/tasks/models/TaskModel'; import { msToTime } from '../../helpers/DateTime'; diff --git a/src/screens/timeline/TimelineScreen.tsx b/src/screens/timeline/TimelineScreen.tsx new file mode 100644 index 0000000..552e361 --- /dev/null +++ b/src/screens/timeline/TimelineScreen.tsx @@ -0,0 +1,48 @@ +import React, { FC, memo, useMemo } from 'react'; +import { Chart } from 'react-google-charts'; +import { createUseStyles } from 'react-jss'; + +import rootStore from '../../modules/RootStore'; +import { getTimeItems } from '../../helpers/TaskHelper'; + +const { tasksStore } = rootStore; + +const columns = [ + { type: 'string', id: 'Task' }, + { type: 'date', id: 'Start' }, + { type: 'date', id: 'End' }, +]; + +const nowDate = new Date(); + +const Timeline: FC = () => { + const classes = useStyles(); + + const tasks = useMemo(() => tasksStore.getTasksByDate(nowDate), []); + const filteredTimeItems = useMemo(() => getTimeItems(tasks, nowDate), [ + tasks, + ]); + + const data = useMemo(() => { + const items = filteredTimeItems.map(({ task, time }) => [ + task.title, + time.start, + time.end || new Date(), + ]); + return [columns, ...items]; + }, [filteredTimeItems]); + + return ( +
+ ; +
+ ); +}; + +export default memo(Timeline); + +const useStyles = createUseStyles({ + main: { + padding: 10, + }, +}); diff --git a/yarn.lock b/yarn.lock index 6205b4a..4d31ad3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2343,11 +2343,6 @@ alphanum-sort@^1.0.2: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - ansi-align@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" @@ -2397,11 +2392,6 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -2573,11 +2563,6 @@ array-back@^4.0.1: resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.1.tgz#9b80312935a52062e1a233a9c7abeb5481b30e90" integrity sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg== -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - array-find@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8" @@ -2725,11 +2710,6 @@ async-exit-hook@^2.0.1: resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -3330,19 +3310,6 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -3390,17 +3357,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4161,13 +4117,6 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.5.tgz#7fdec6a28a67ae18647c51668a9ff95bb2fa7bb8" integrity sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ== -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - damerau-levenshtein@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" @@ -4225,7 +4174,7 @@ debug@^3.1.1, debug@^3.2.6: dependencies: ms "^2.1.1" -decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -4934,7 +4883,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -5611,14 +5560,6 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -5796,13 +5737,6 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== - dependencies: - globule "^1.0.0" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -5832,11 +5766,6 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" @@ -5893,7 +5822,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -5905,18 +5834,6 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl once "^1.3.0" path-is-absolute "^1.0.0" -glob@~7.1.1: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - global-agent@^2.0.2: version "2.1.12" resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.12.tgz#e4ae3812b731a9e81cbf825f9377ef450a8e4195" @@ -5989,15 +5906,6 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globule@^1.0.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" - integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== - dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" - got@^11.7.0: version "11.8.0" resolved "https://registry.yarnpkg.com/got/-/got-11.8.0.tgz#be0920c3586b07fd94add3b5b27cb28f49e6545f" @@ -6073,13 +5981,6 @@ harmony-reflect@^1.4.6: resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -6492,13 +6393,6 @@ indefinite-observable@^2.0.1: dependencies: symbol-observable "1.2.0" -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -6712,11 +6606,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -6883,11 +6772,6 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - is-what@^3.12.0: version "3.14.1" resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" @@ -7487,11 +7371,6 @@ jest@^27.0.6: import-local "^3.0.2" jest-cli "^27.3.1" -js-base64@^2.1.8: - version "2.6.4" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" - integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -7984,17 +7863,6 @@ listr2@^3.2.2: rxjs "^6.6.3" through "^2.3.8" -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -8075,7 +7943,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0, lodash@~4.17.10: +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8109,14 +7977,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3 dependencies: js-tokens "^3.0.0 || ^4.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -8176,11 +8036,6 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -8244,22 +8099,6 @@ memory-fs@^0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -8384,14 +8223,14 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -8501,7 +8340,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== @@ -8657,28 +8496,6 @@ node-releases@^2.0.1: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== -node-sass@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-5.0.0.tgz#4e8f39fbef3bac8d2dc72ebe3b539711883a78d2" - integrity sha512-opNgmlu83ZCF792U281Ry7tak9IbVC+AKnXGovcQ8LG8wFaJv6cLnRlc6DIHlmNxWEexB5bZxi9SZ9JyUuOYjw== - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^7.0.3" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - lodash "^4.17.15" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.13.2" - node-gyp "^7.1.0" - npmlog "^4.0.0" - request "^2.88.0" - sass-graph "2.2.5" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - nopt@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" @@ -8694,7 +8511,7 @@ nopt@^5.0.0: dependencies: abbrev "1" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -8769,7 +8586,7 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -9176,13 +8993,6 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -9230,15 +9040,6 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" @@ -10197,6 +9998,11 @@ react-dom@^17.0.1: object-assign "^4.1.1" scheduler "^0.20.1" +react-google-charts@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/react-google-charts/-/react-google-charts-4.0.0.tgz#f648e4fe8ac8a1f47542c2cac040df6afb21e2d6" + integrity sha512-9OG0EkBb9JerKEPQYdhmAXnhGLzOdOHOPS9j7l+P1a3z1kcmq9mGDa7PUoX/VQUY4IjZl2/81nsO4o+1cuYsuw== + react-hook-media-query@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/react-hook-media-query/-/react-hook-media-query-1.0.5.tgz#e5d8282c5cd5b54f7b72923f6b05c92ab3e74ba8" @@ -10282,14 +10088,6 @@ read-config-file@6.2.0: json5 "^2.2.0" lazy-val "^1.0.4" -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" @@ -10298,15 +10096,6 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" @@ -10363,14 +10152,6 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - reduce-flatten@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" @@ -10474,14 +10255,7 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - -request@^2.88.0, request@^2.88.2: +request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -10733,16 +10507,6 @@ sanitize-filename@^1.6.2, sanitize-filename@^1.6.3: dependencies: truncate-utf8-bytes "^1.0.0" -sass-graph@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" - integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^13.3.2" - sass-loader@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.1.0.tgz#1727fcc0c32ab3eb197cda61d78adf4e9174a4b3" @@ -10808,14 +10572,6 @@ scroll-into-view-if-needed@^2.2.25: dependencies: compute-scroll-into-view "^1.0.17" -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -11159,13 +10915,6 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" - source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -11302,13 +11051,6 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -11460,13 +11202,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -11487,13 +11222,6 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -11527,11 +11255,6 @@ sumchecker@^3.0.1: dependencies: debug "^4.1.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -11849,18 +11572,6 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" - truncate-utf8-bytes@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" From b1e4d0e837e186a9c56e51669af7a8cc3991174b Mon Sep 17 00:00:00 2001 From: yadro Date: Mon, 16 May 2022 10:45:36 +0300 Subject: [PATCH 2/7] Up version & small fix --- package.json | 2 +- src/package.json | 4 +-- src/screens/timeline/TimelineScreen.tsx | 35 ++++++++++++------------- yarn.lock | 2 +- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 4d86ced..0a95e07 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "time-tracker", "productName": "TimeTracker", - "description": "Start and stop time, jump between tasks, and add details on how time was spent.", + "description": "Todo list with stopwatch on each task", "scripts": { "build": "concurrently \"yarn build:main\" \"yarn build:renderer\"", "build-dll": "cross-env NODE_ENV=development webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.babel.js", diff --git a/src/package.json b/src/package.json index 76ccac7..8fb15fd 100644 --- a/src/package.json +++ b/src/package.json @@ -1,8 +1,8 @@ { "name": "time-tracker", "productName": "TimeTracker", - "version": "1.0.9", - "description": "Start and stop time, jump between tasks, and add details on how time was spent.", + "version": "1.0.10", + "description": "Todo list with stopwatch on each task", "main": "./main.prod.js", "author": { "name": "Dmitry Yadrikhinsky", diff --git a/src/screens/timeline/TimelineScreen.tsx b/src/screens/timeline/TimelineScreen.tsx index 552e361..f2f66c1 100644 --- a/src/screens/timeline/TimelineScreen.tsx +++ b/src/screens/timeline/TimelineScreen.tsx @@ -1,16 +1,16 @@ -import React, { FC, memo, useMemo } from 'react'; -import { Chart } from 'react-google-charts'; -import { createUseStyles } from 'react-jss'; +import React, {FC, memo, useMemo} from 'react'; +import {Chart} from 'react-google-charts'; +import {createUseStyles} from 'react-jss'; import rootStore from '../../modules/RootStore'; -import { getTimeItems } from '../../helpers/TaskHelper'; +import {getTimeItems} from '../../helpers/TaskHelper'; -const { tasksStore } = rootStore; +const {tasksStore} = rootStore; const columns = [ - { type: 'string', id: 'Task' }, - { type: 'date', id: 'Start' }, - { type: 'date', id: 'End' }, + {type: 'string', id: 'Task'}, + {type: 'date', id: 'Start'}, + {type: 'date', id: 'End'}, ]; const nowDate = new Date(); @@ -18,23 +18,20 @@ const nowDate = new Date(); const Timeline: FC = () => { const classes = useStyles(); - const tasks = useMemo(() => tasksStore.getTasksByDate(nowDate), []); - const filteredTimeItems = useMemo(() => getTimeItems(tasks, nowDate), [ - tasks, - ]); - const data = useMemo(() => { - const items = filteredTimeItems.map(({ task, time }) => [ - task.title, - time.start, + const tasks = tasksStore.getTasksByDate(nowDate); + const filteredTimeItems = getTimeItems(tasks, nowDate); + const items = filteredTimeItems.map(({task, time}) => [ + task.title || '-', + time.start || new Date(), time.end || new Date(), ]); return [columns, ...items]; - }, [filteredTimeItems]); + }, []); return (
- ; +
); }; @@ -44,5 +41,7 @@ export default memo(Timeline); const useStyles = createUseStyles({ main: { padding: 10, + display: 'flex', + height: '100%', }, }); diff --git a/yarn.lock b/yarn.lock index 4d31ad3..4b94192 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9998,7 +9998,7 @@ react-dom@^17.0.1: object-assign "^4.1.1" scheduler "^0.20.1" -react-google-charts@^4.0.0: +react-google-charts@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/react-google-charts/-/react-google-charts-4.0.0.tgz#f648e4fe8ac8a1f47542c2cac040df6afb21e2d6" integrity sha512-9OG0EkBb9JerKEPQYdhmAXnhGLzOdOHOPS9j7l+P1a3z1kcmq9mGDa7PUoX/VQUY4IjZl2/81nsO4o+1cuYsuw== From 103a8346ee5ac66934a004120c0a80ff4c5a56e5 Mon Sep 17 00:00:00 2001 From: yadro Date: Mon, 16 May 2022 23:53:50 +0300 Subject: [PATCH 3/7] Header --- src/screens/hours/HoursScreen.tsx | 6 +-- src/screens/hours/components/Header.tsx | 43 +++++++++++++++++++ .../components/RadioGroupChangeHoursView.tsx | 29 +++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/screens/hours/components/Header.tsx create mode 100644 src/screens/hours/components/RadioGroupChangeHoursView.tsx diff --git a/src/screens/hours/HoursScreen.tsx b/src/screens/hours/HoursScreen.tsx index e40a118..c8880c4 100644 --- a/src/screens/hours/HoursScreen.tsx +++ b/src/screens/hours/HoursScreen.tsx @@ -6,7 +6,6 @@ import { createUseStyles } from 'react-jss'; import rootStore from '../../modules/RootStore'; import HoursCard from './components/HoursCard/HoursCard'; import { getTimeItems } from '../../helpers/TaskHelper'; -import SelectDate from '../../components/SelectDate'; import TimeRangeModal from '../../components/TimeRangeModal/TimeRangeModal'; import TaskTimeItemModel from '../../modules/tasks/models/TaskTimeItemModel'; import { Undefined } from '../../types/CommonTypes'; @@ -14,6 +13,7 @@ import TotalHours from './components/TotalHours/TotalHours'; import { mapCurrentNext } from '../../helpers/ArrayHelper'; import { ITimeRangeModel } from '../../modules/tasks/models/TaskModel'; import { msToTime } from '../../helpers/DateTime'; +import Header from './components/Header'; const { tasksStore } = rootStore; @@ -28,7 +28,7 @@ function getDiff( return ''; } -export default observer(function HoursView() { +export default observer(function HoursScreen() { const classes = useStyles(); const [date, setDate] = useState(new Date()); const [currentTaskTime, setCurrentTaskTime] = useState< @@ -44,7 +44,7 @@ export default observer(function HoursView() { return ( - +
{mapCurrentNext(timeItems, (item, next, index) => ( diff --git a/src/screens/hours/components/Header.tsx b/src/screens/hours/components/Header.tsx new file mode 100644 index 0000000..c884348 --- /dev/null +++ b/src/screens/hours/components/Header.tsx @@ -0,0 +1,43 @@ +import React, { FC } from 'react'; +import { observer } from 'mobx-react'; +import { Col, Row } from 'antd'; +import { createUseStyles } from 'react-jss'; + +import SelectDate from '../../../components/SelectDate'; +import RadioGroupChangeHoursView from './RadioGroupChangeHoursView'; + +type Props = { + date: Date; + setDate(date: Date): void; +}; + +const Header: FC = ({ date, setDate }: Props) => { + const classes = useStyles(); + + return ( + + + + + + {}} /> + + + ); +}; + +export default observer(Header); + +const useStyles = createUseStyles({ + main: { + flex: 1, + }, + alignCenter: { + display: 'flex', + justifyContent: 'center', + }, + alignRight: { + display: 'flex', + justifyContent: 'flex-end', + }, +}); diff --git a/src/screens/hours/components/RadioGroupChangeHoursView.tsx b/src/screens/hours/components/RadioGroupChangeHoursView.tsx new file mode 100644 index 0000000..55224e6 --- /dev/null +++ b/src/screens/hours/components/RadioGroupChangeHoursView.tsx @@ -0,0 +1,29 @@ +import React, { FC } from 'react'; +import { CheckboxOptionType } from 'antd/lib/checkbox/Group'; +import { AppstoreOutlined, BuildOutlined } from '@ant-design/icons'; +import { Radio } from 'antd'; +import { observer } from 'mobx-react'; + +enum Options { + Edit, + Timeline, +} + +const ICON_STYLE = { fontSize: '20px' }; + +const options: CheckboxOptionType[] = [ + { label: , value: Options.Edit }, + { label: , value: Options.Timeline }, +]; + +type Props = { + onChange(val: Options): void; +}; + +const RadioGroupChangeHoursView: FC = () => { + return ( + + ); +}; + +export default observer(RadioGroupChangeHoursView); From f0909f18aa7ff75bf28e12a9da06b8880ba72192 Mon Sep 17 00:00:00 2001 From: yadro Date: Tue, 17 May 2022 00:10:20 +0300 Subject: [PATCH 4/7] EditableTimeItemsView.tsx --- src/screens/hours/HoursScreen.tsx | 51 +----------- .../components/EditableTimeItemsView.tsx | 81 +++++++++++++++++++ 2 files changed, 83 insertions(+), 49 deletions(-) create mode 100644 src/screens/hours/components/EditableTimeItemsView.tsx diff --git a/src/screens/hours/HoursScreen.tsx b/src/screens/hours/HoursScreen.tsx index c8880c4..1446ce9 100644 --- a/src/screens/hours/HoursScreen.tsx +++ b/src/screens/hours/HoursScreen.tsx @@ -4,36 +4,16 @@ import { observer } from 'mobx-react'; import { createUseStyles } from 'react-jss'; import rootStore from '../../modules/RootStore'; -import HoursCard from './components/HoursCard/HoursCard'; import { getTimeItems } from '../../helpers/TaskHelper'; -import TimeRangeModal from '../../components/TimeRangeModal/TimeRangeModal'; -import TaskTimeItemModel from '../../modules/tasks/models/TaskTimeItemModel'; -import { Undefined } from '../../types/CommonTypes'; import TotalHours from './components/TotalHours/TotalHours'; -import { mapCurrentNext } from '../../helpers/ArrayHelper'; -import { ITimeRangeModel } from '../../modules/tasks/models/TaskModel'; -import { msToTime } from '../../helpers/DateTime'; import Header from './components/Header'; +import EditableTimeItemsView from './components/EditableTimeItemsView'; const { tasksStore } = rootStore; -function getDiff( - prev: ITimeRangeModel | undefined, - next: ITimeRangeModel | undefined -) { - if (prev?.end && next?.start) { - return msToTime(next.start.getTime() - prev.end.getTime()); - } - - return ''; -} - export default observer(function HoursScreen() { const classes = useStyles(); const [date, setDate] = useState(new Date()); - const [currentTaskTime, setCurrentTaskTime] = useState< - Undefined - >(); const tasks = useMemo(() => tasksStore.getTasksByDate(date), [ tasksStore.tasks, @@ -46,25 +26,8 @@ export default observer(function HoursScreen() {
-
- {mapCurrentNext(timeItems, (item, next, index) => ( -
- setCurrentTaskTime(taskTime)} - /> -
- {getDiff(item.time, next?.time)} -
-
- ))} -
+ - setCurrentTaskTime(undefined)} - taskTime={currentTaskTime} - /> ); }); @@ -83,14 +46,4 @@ const useStyles = createUseStyles({ padding: 8, }, }, - cards: { - display: 'flex', - flexWrap: 'wrap', - }, - breakTime: { - display: 'flex', - justifyContent: 'flex-end', - margin: '0 13px', - fontSize: 11, - }, }); diff --git a/src/screens/hours/components/EditableTimeItemsView.tsx b/src/screens/hours/components/EditableTimeItemsView.tsx new file mode 100644 index 0000000..fd9bd1e --- /dev/null +++ b/src/screens/hours/components/EditableTimeItemsView.tsx @@ -0,0 +1,81 @@ +import React, { FC, useMemo, useState } from 'react'; +import { observer } from 'mobx-react'; +import { createUseStyles } from 'react-jss'; + +import HoursCard from './HoursCard/HoursCard'; +import TimeRangeModal from '../../../components/TimeRangeModal/TimeRangeModal'; +import { mapCurrentNext } from '../../../helpers/ArrayHelper'; +import { msToTime } from '../../../helpers/DateTime'; +import { getTimeItems } from '../../../helpers/TaskHelper'; +import rootStore from '../../../modules/RootStore'; +import { ITimeRangeModel } from '../../../modules/tasks/models/TaskModel'; +import TaskTimeItemModel from '../../../modules/tasks/models/TaskTimeItemModel'; +import { Undefined } from '../../../types/CommonTypes'; + +const { tasksStore } = rootStore; + +function getDiff( + prev: ITimeRangeModel | undefined, + next: ITimeRangeModel | undefined +) { + if (prev?.end && next?.start) { + return msToTime(next.start.getTime() - prev.end.getTime()); + } + + return ''; +} + +type Props = { + date: Date; +}; + +const EditableTimeItemsView: FC = ({ date }: Props) => { + const classes = useStyles(); + + const [currentTaskTime, setCurrentTaskTime] = useState< + Undefined + >(); + + const timeItems = useMemo(() => { + const tasks = tasksStore.getTasksByDate(date); + return getTimeItems(tasks, date); + }, [tasksStore.tasks, date]); + + return ( + <> +
+ {mapCurrentNext(timeItems, (item, next, index) => ( +
+ setCurrentTaskTime(taskTime)} + /> +
+ {getDiff(item.time, next?.time)} +
+
+ ))} +
+ setCurrentTaskTime(undefined)} + taskTime={currentTaskTime} + /> + + ); +}; + +export default observer(EditableTimeItemsView); + +const useStyles = createUseStyles({ + cards: { + display: 'flex', + flexWrap: 'wrap', + }, + breakTime: { + display: 'flex', + justifyContent: 'flex-end', + margin: '0 13px', + fontSize: 11, + }, +}); From 10fec666711fa36695c55dc48ede9fc92d2687fa Mon Sep 17 00:00:00 2001 From: yadro Date: Tue, 17 May 2022 22:31:26 +0300 Subject: [PATCH 5/7] Prototype --- src/components/Header.tsx | 3 - src/menu.ts | 7 +-- src/screens/Main.tsx | 2 - src/screens/hours/HoursScreen.tsx | 26 +++++--- ...temsView.tsx => GridWithTimeItemsView.tsx} | 9 ++- src/screens/hours/components/Header.tsx | 7 ++- .../components/RadioGroupChangeHoursView.tsx | 37 +++++++---- .../hours/components/TimelineScreen.tsx | 62 +++++++++++++++++++ src/screens/hours/types.ts | 4 ++ src/screens/timeline/TimelineScreen.tsx | 27 ++++---- 10 files changed, 141 insertions(+), 43 deletions(-) rename src/screens/hours/components/{EditableTimeItemsView.tsx => GridWithTimeItemsView.tsx} (91%) create mode 100644 src/screens/hours/components/TimelineScreen.tsx create mode 100644 src/screens/hours/types.ts diff --git a/src/components/Header.tsx b/src/components/Header.tsx index e698c1a..0922a97 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -28,9 +28,6 @@ function Header() { Dashboard - - TL - {isBigScreen && } diff --git a/src/menu.ts b/src/menu.ts index 66f3381..cebece1 100644 --- a/src/menu.ts +++ b/src/menu.ts @@ -27,10 +27,8 @@ export default class MenuBuilder { } const template = - process.platform === 'darwin' - ? this.buildDarwinTemplate() - : []; - // : this.buildDefaultTemplate(); // Disable menu for Win and Linux + process.platform === 'darwin' ? this.buildDarwinTemplate() : []; + // : this.buildDefaultTemplate(); // Disable menu for Win and Linux const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); @@ -54,6 +52,7 @@ export default class MenuBuilder { } buildDarwinTemplate(): MenuItemConstructorOptions[] { + // TODO const subMenuAbout: DarwinMenuItemConstructorOptions = { label: 'Electron', submenu: [ diff --git a/src/screens/Main.tsx b/src/screens/Main.tsx index 6a6aace..0c598b9 100644 --- a/src/screens/Main.tsx +++ b/src/screens/Main.tsx @@ -5,7 +5,6 @@ import { Layout } from 'antd'; import ProjectsScreen from './projects/ProjectsScreen'; import HoursScreen from './hours/HoursScreen'; import DashboardScreen from './dashboard/Dashboard'; -import TimelineScreen from './timeline/TimelineScreen'; import GaService from '../services/gaService/GaService'; import Header from '../components/Header'; @@ -27,7 +26,6 @@ const Main = () => { - diff --git a/src/screens/hours/HoursScreen.tsx b/src/screens/hours/HoursScreen.tsx index 1446ce9..305d750 100644 --- a/src/screens/hours/HoursScreen.tsx +++ b/src/screens/hours/HoursScreen.tsx @@ -7,13 +7,16 @@ import rootStore from '../../modules/RootStore'; import { getTimeItems } from '../../helpers/TaskHelper'; import TotalHours from './components/TotalHours/TotalHours'; import Header from './components/Header'; -import EditableTimeItemsView from './components/EditableTimeItemsView'; +import GridWithTimeItemsView from './components/GridWithTimeItemsView'; +import { HoursTabView } from './types'; +import TimelineScreen from './components/TimelineScreen'; const { tasksStore } = rootStore; export default observer(function HoursScreen() { const classes = useStyles(); const [date, setDate] = useState(new Date()); + const [tab, setTab] = useState(HoursTabView.Edit); const tasks = useMemo(() => tasksStore.getTasksByDate(date), [ tasksStore.tasks, @@ -22,28 +25,35 @@ export default observer(function HoursScreen() { const timeItems = getTimeItems(tasks, date); return ( - - -
+ + +
- + {tab === HoursTabView.Edit ? ( + + ) : ( + + )} ); }); const useStyles = createUseStyles({ - hours: { + hoursView: { overflowY: 'auto', padding: 12, + }, + space: { + flex: 1, '& .ant-space-item': { display: 'flex', justifyContent: 'center', }, - '& .ant-card-body': { - padding: 8, + '& .ant-space-item:last-child': { + flex: 1, }, }, }); diff --git a/src/screens/hours/components/EditableTimeItemsView.tsx b/src/screens/hours/components/GridWithTimeItemsView.tsx similarity index 91% rename from src/screens/hours/components/EditableTimeItemsView.tsx rename to src/screens/hours/components/GridWithTimeItemsView.tsx index fd9bd1e..af5cd06 100644 --- a/src/screens/hours/components/EditableTimeItemsView.tsx +++ b/src/screens/hours/components/GridWithTimeItemsView.tsx @@ -29,7 +29,7 @@ type Props = { date: Date; }; -const EditableTimeItemsView: FC = ({ date }: Props) => { +const GridWithTimeItemsView: FC = ({ date }: Props) => { const classes = useStyles(); const [currentTaskTime, setCurrentTaskTime] = useState< @@ -37,6 +37,7 @@ const EditableTimeItemsView: FC = ({ date }: Props) => { >(); const timeItems = useMemo(() => { + // TODO Doesn't update const tasks = tasksStore.getTasksByDate(date); return getTimeItems(tasks, date); }, [tasksStore.tasks, date]); @@ -65,12 +66,16 @@ const EditableTimeItemsView: FC = ({ date }: Props) => { ); }; -export default observer(EditableTimeItemsView); +export default observer(GridWithTimeItemsView); const useStyles = createUseStyles({ cards: { display: 'flex', flexWrap: 'wrap', + + '& .ant-card-body': { + padding: 8, + }, }, breakTime: { display: 'flex', diff --git a/src/screens/hours/components/Header.tsx b/src/screens/hours/components/Header.tsx index c884348..04a3d2d 100644 --- a/src/screens/hours/components/Header.tsx +++ b/src/screens/hours/components/Header.tsx @@ -5,13 +5,16 @@ import { createUseStyles } from 'react-jss'; import SelectDate from '../../../components/SelectDate'; import RadioGroupChangeHoursView from './RadioGroupChangeHoursView'; +import { HoursTabView } from '../types'; type Props = { date: Date; setDate(date: Date): void; + tab: HoursTabView; + setTab(tab: HoursTabView): void; }; -const Header: FC = ({ date, setDate }: Props) => { +const Header: FC = ({ date, setDate, tab, setTab }: Props) => { const classes = useStyles(); return ( @@ -20,7 +23,7 @@ const Header: FC = ({ date, setDate }: Props) => { - {}} /> + ); diff --git a/src/screens/hours/components/RadioGroupChangeHoursView.tsx b/src/screens/hours/components/RadioGroupChangeHoursView.tsx index 55224e6..68d4e55 100644 --- a/src/screens/hours/components/RadioGroupChangeHoursView.tsx +++ b/src/screens/hours/components/RadioGroupChangeHoursView.tsx @@ -1,28 +1,43 @@ -import React, { FC } from 'react'; +import React, { FC, useCallback } from 'react'; import { CheckboxOptionType } from 'antd/lib/checkbox/Group'; import { AppstoreOutlined, BuildOutlined } from '@ant-design/icons'; -import { Radio } from 'antd'; +import { Radio, RadioChangeEvent } from 'antd'; import { observer } from 'mobx-react'; -enum Options { - Edit, - Timeline, -} +import { HoursTabView } from '../types'; const ICON_STYLE = { fontSize: '20px' }; +const ICON_MIRRORED_STYLE = { ...ICON_STYLE, transform: 'scale(-1, 1)' }; const options: CheckboxOptionType[] = [ - { label: , value: Options.Edit }, - { label: , value: Options.Timeline }, + { label: , value: HoursTabView.Edit }, + { + label: , + value: HoursTabView.Timeline, + }, ]; type Props = { - onChange(val: Options): void; + tab: HoursTabView; + onChange(val: HoursTabView): void; }; -const RadioGroupChangeHoursView: FC = () => { +const RadioGroupChangeHoursView: FC = ({ tab, onChange }: Props) => { + const handleOnChange = useCallback( + (e: RadioChangeEvent) => { + onChange(e.target.value); + }, + [onChange] + ); + return ( - + ); }; diff --git a/src/screens/hours/components/TimelineScreen.tsx b/src/screens/hours/components/TimelineScreen.tsx new file mode 100644 index 0000000..a07cc9e --- /dev/null +++ b/src/screens/hours/components/TimelineScreen.tsx @@ -0,0 +1,62 @@ +import React, { FC, memo, useMemo } from 'react'; +import { Chart } from 'react-google-charts'; +import { createUseStyles } from 'react-jss'; + +import rootStore from '../../../modules/RootStore'; +import { getTimeItems } from '../../../helpers/TaskHelper'; +import TaskTimeItemModel from '../../../modules/tasks/models/TaskTimeItemModel'; + +const { tasksStore } = rootStore; + +const columns = [ + { type: 'string', id: 'Task' }, + { type: 'date', id: 'Start' }, + { type: 'date', id: 'End' }, +]; + +function mapTimeItemToChartItem({ task, time }: TaskTimeItemModel): any[] { + return [task.title || '-', time.start || new Date(), time.end || new Date()]; +} + +type Props = { + date: Date; +}; + +const Timeline: FC = ({ date }: Props) => { + const classes = useStyles(); + + const data = useMemo(() => { + const tasks = tasksStore.getTasksByDate(date); + const filteredTimeItems = getTimeItems(tasks, date); + const items = filteredTimeItems.map(mapTimeItemToChartItem); + if (items.length === 0) { + return undefined; + } + return [columns, ...items]; + }, [date]); + + if (!data) { + return null; + } + + return ( +
+ +
+ ); +}; + +export default memo(Timeline); + +const useStyles = createUseStyles({ + main: { + display: 'flex', + flex: 1, + height: '100%', + }, +}); diff --git a/src/screens/hours/types.ts b/src/screens/hours/types.ts new file mode 100644 index 0000000..5413698 --- /dev/null +++ b/src/screens/hours/types.ts @@ -0,0 +1,4 @@ +export enum HoursTabView { + Edit, + Timeline, +} diff --git a/src/screens/timeline/TimelineScreen.tsx b/src/screens/timeline/TimelineScreen.tsx index f2f66c1..0a31f0c 100644 --- a/src/screens/timeline/TimelineScreen.tsx +++ b/src/screens/timeline/TimelineScreen.tsx @@ -1,27 +1,27 @@ -import React, {FC, memo, useMemo} from 'react'; -import {Chart} from 'react-google-charts'; -import {createUseStyles} from 'react-jss'; +import React, { FC, memo, useMemo } from 'react'; +import { Chart } from 'react-google-charts'; +import { createUseStyles } from 'react-jss'; import rootStore from '../../modules/RootStore'; -import {getTimeItems} from '../../helpers/TaskHelper'; +import { getTimeItems } from '../../helpers/TaskHelper'; -const {tasksStore} = rootStore; +const { tasksStore } = rootStore; const columns = [ - {type: 'string', id: 'Task'}, - {type: 'date', id: 'Start'}, - {type: 'date', id: 'End'}, + { type: 'string', id: 'Task' }, + { type: 'date', id: 'Start' }, + { type: 'date', id: 'End' }, ]; const nowDate = new Date(); - +// TODO remove const Timeline: FC = () => { const classes = useStyles(); const data = useMemo(() => { const tasks = tasksStore.getTasksByDate(nowDate); const filteredTimeItems = getTimeItems(tasks, nowDate); - const items = filteredTimeItems.map(({task, time}) => [ + const items = filteredTimeItems.map(({ task, time }) => [ task.title || '-', time.start || new Date(), time.end || new Date(), @@ -31,7 +31,12 @@ const Timeline: FC = () => { return (
- +
); }; From 4773d1b63ed0466cb9a4733efb649e33b273485a Mon Sep 17 00:00:00 2001 From: yadro Date: Wed, 18 May 2022 23:47:01 +0300 Subject: [PATCH 6/7] Save in localstorage --- src/consts/index.ts | 5 ++++ src/hooks/useLocalStorage.ts | 47 +++++++++++++++++++++++++++++++ src/screens/hours/HoursScreen.tsx | 21 +++++++++++--- 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 src/hooks/useLocalStorage.ts diff --git a/src/consts/index.ts b/src/consts/index.ts index 012e828..8fb8a4d 100644 --- a/src/consts/index.ts +++ b/src/consts/index.ts @@ -1 +1,6 @@ export const PURPLE_COLOR = '#713A91'; + +export const LOCAL_STORAGE_KEY = { + HOURS_TAB: 'hours:view_tab', + HOURS_SELECTED_DATE: 'hours:view_date', +}; diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts new file mode 100644 index 0000000..93e4f1b --- /dev/null +++ b/src/hooks/useLocalStorage.ts @@ -0,0 +1,47 @@ +import { useCallback, useState } from 'react'; + +type Value = boolean | number | string | any[] | Record; +type ParseFn = (raw: string) => T; + +function readFromStorage( + key: string, + valueParse?: ParseFn +): T | null { + const raw = window.localStorage.getItem(key); + if (raw === null) { + return raw; + } + try { + const value = JSON.parse(raw); + if (typeof valueParse === 'function') { + return valueParse(value); + } + return value; + } catch { + return null; + } +} + +export default function useLocalStorage( + key: string, + defaultValue: T, + getFromStorageFirst: boolean, + valueParse?: (raw: string) => T +): [T, (t: T) => void] { + const [value, setValue] = useState(() => { + if (getFromStorageFirst) { + return readFromStorage(key, valueParse) ?? defaultValue; + } + return defaultValue; + }); + + const setItem = useCallback( + (value: T) => { + window.localStorage.setItem(key, JSON.stringify(value)); + setValue(value); + }, + [key] + ); + + return [value, setItem]; +} diff --git a/src/screens/hours/HoursScreen.tsx b/src/screens/hours/HoursScreen.tsx index 305d750..9cb44c9 100644 --- a/src/screens/hours/HoursScreen.tsx +++ b/src/screens/hours/HoursScreen.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { Layout, Space } from 'antd'; import { observer } from 'mobx-react'; import { createUseStyles } from 'react-jss'; @@ -8,15 +8,28 @@ import { getTimeItems } from '../../helpers/TaskHelper'; import TotalHours from './components/TotalHours/TotalHours'; import Header from './components/Header'; import GridWithTimeItemsView from './components/GridWithTimeItemsView'; -import { HoursTabView } from './types'; import TimelineScreen from './components/TimelineScreen'; +import { HoursTabView } from './types'; +import useLocalStorage from '../../hooks/useLocalStorage'; +import { LOCAL_STORAGE_KEY } from '../../consts'; const { tasksStore } = rootStore; +const parseDateFromString = (value: string) => new Date(value); + export default observer(function HoursScreen() { const classes = useStyles(); - const [date, setDate] = useState(new Date()); - const [tab, setTab] = useState(HoursTabView.Edit); + const [date, setDate] = useLocalStorage( + LOCAL_STORAGE_KEY.HOURS_SELECTED_DATE, + new Date(), + true, + parseDateFromString + ); + const [tab, setTab] = useLocalStorage( + LOCAL_STORAGE_KEY.HOURS_TAB, + HoursTabView.Edit, + true + ); const tasks = useMemo(() => tasksStore.getTasksByDate(date), [ tasksStore.tasks, From 45b4e59e1bc9543c6ee8f666e0a47297320d5c6e Mon Sep 17 00:00:00 2001 From: yadro Date: Sat, 28 May 2022 14:26:16 +0300 Subject: [PATCH 7/7] WIP --- src/screens/hours/HoursScreen.tsx | 14 ++++++++++++-- src/screens/hours/components/BackOnToday.tsx | 13 +++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/screens/hours/components/BackOnToday.tsx diff --git a/src/screens/hours/HoursScreen.tsx b/src/screens/hours/HoursScreen.tsx index 9cb44c9..5839e17 100644 --- a/src/screens/hours/HoursScreen.tsx +++ b/src/screens/hours/HoursScreen.tsx @@ -1,7 +1,8 @@ -import React, { useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Layout, Space } from 'antd'; import { observer } from 'mobx-react'; import { createUseStyles } from 'react-jss'; +import { isToday } from 'date-fns'; import rootStore from '../../modules/RootStore'; import { getTimeItems } from '../../helpers/TaskHelper'; @@ -12,6 +13,7 @@ import TimelineScreen from './components/TimelineScreen'; import { HoursTabView } from './types'; import useLocalStorage from '../../hooks/useLocalStorage'; import { LOCAL_STORAGE_KEY } from '../../consts'; +import BackOnToday from './components/BackOnToday'; const { tasksStore } = rootStore; @@ -19,12 +21,18 @@ const parseDateFromString = (value: string) => new Date(value); export default observer(function HoursScreen() { const classes = useStyles(); + const [date, setDate] = useLocalStorage( LOCAL_STORAGE_KEY.HOURS_SELECTED_DATE, new Date(), true, parseDateFromString ); + + const goTodayDate = useCallback(() => { + setDate(new Date()); + }, [setDate]); + const [tab, setTab] = useLocalStorage( LOCAL_STORAGE_KEY.HOURS_TAB, HoursTabView.Edit, @@ -42,7 +50,9 @@ export default observer(function HoursScreen() {
- {tab === HoursTabView.Edit ? ( + {!timeItems.length && !isToday(date) ? ( + + ) : tab === HoursTabView.Edit ? ( ) : ( diff --git a/src/screens/hours/components/BackOnToday.tsx b/src/screens/hours/components/BackOnToday.tsx new file mode 100644 index 0000000..c634916 --- /dev/null +++ b/src/screens/hours/components/BackOnToday.tsx @@ -0,0 +1,13 @@ +import React, { FC } from 'react'; +import { Button } from 'antd'; +import { observer } from 'mobx-react'; + +type Props = { + goToday(): void; +}; + +const BackOnToday: FC = ({ goToday }: Props) => { + return