From a7323d8c4c45312a551c8e82472e4bcd982bca08 Mon Sep 17 00:00:00 2001 From: Alperen Elhan Date: Thu, 27 Oct 2022 15:09:11 +0300 Subject: [PATCH] feat: add support for custom interval. closes #12 --- package.json | 2 ++ pnpm-lock.yaml | 8 +++++ .../migration.sql | 3 ++ src/components/addManga/form.tsx | 13 ++++++- .../addManga/steps/downloadStep.tsx | 36 +++++++++++++++---- src/components/addManga/steps/index.tsx | 3 +- src/components/mangaDetail.tsx | 11 ++---- src/server/queue/checkChapters.ts | 11 ++---- src/server/queue/download.ts | 2 +- src/server/trpc/router/manga.ts | 10 ++++-- src/server/utils/mangal.ts | 2 +- src/utils/sanitize.ts | 6 ---- 12 files changed, 71 insertions(+), 36 deletions(-) create mode 100644 prisma/migrations/20221027101522_fix_intervals/migration.sql delete mode 100644 src/utils/sanitize.ts diff --git a/package.json b/package.json index 999c472..9fa0bcf 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,8 @@ "@trpc/server": "^10.0.0-proxy-beta.23", "bullmq": "^2.3.2", "contrast-color": "^1.0.1", + "cron-parser": "^4.6.0", + "cronstrue": "^2.14.0", "dayjs": "^1.11.5", "execa": "5.1.1", "express": "^4.18.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 764f070..8b87f45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,6 +34,8 @@ specifiers: autoprefixer: ^10.4.12 bullmq: ^2.3.2 contrast-color: ^1.0.1 + cron-parser: ^4.6.0 + cronstrue: ^2.14.0 dayjs: ^1.11.5 eslint: 8.25.0 eslint-config-airbnb: ^19.0.4 @@ -93,6 +95,8 @@ dependencies: '@trpc/server': 10.0.0-rc.0 bullmq: 2.4.0 contrast-color: 1.0.1 + cron-parser: 4.6.0 + cronstrue: 2.14.0 dayjs: 1.11.6 execa: 5.1.1 express: 4.18.2 @@ -2264,6 +2268,10 @@ packages: luxon: 3.0.4 dev: false + /cronstrue/2.14.0: + resolution: {integrity: sha512-rUTXOwOYrw7o4iV+Wg7fUXjMXDuqAMnhU007LrvaGbfVx73aiZz2e5SYjsAt6Q7ML2/z7Gq3qTncy3GKO9MLSQ==} + dev: false + /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} diff --git a/prisma/migrations/20221027101522_fix_intervals/migration.sql b/prisma/migrations/20221027101522_fix_intervals/migration.sql new file mode 100644 index 0000000..5ac9c33 --- /dev/null +++ b/prisma/migrations/20221027101522_fix_intervals/migration.sql @@ -0,0 +1,3 @@ +update "Manga" set interval = '0 0 * * *' where interval = 'daily'; +update "Manga" set interval = '0 * * * *' where interval = 'hourly'; +update "Manga" set interval = '0 0 * * 7' where interval = 'weekly'; \ No newline at end of file diff --git a/src/components/addManga/form.tsx b/src/components/addManga/form.tsx index 1e3845e..90101e7 100644 --- a/src/components/addManga/form.tsx +++ b/src/components/addManga/form.tsx @@ -4,6 +4,7 @@ import { showNotification } from '@mantine/notifications'; import { IconCheck, IconX } from '@tabler/icons'; import { useState } from 'react'; import { z } from 'zod'; +import { isCronValid } from '../../utils'; import { trpc } from '../../utils/trpc'; import AddMangaSteps from './steps'; @@ -28,7 +29,14 @@ const schema = z.object({ source: z.string().min(1, { message: 'You must select a source' }), query: z.string().min(1, { message: 'Cannot be empty' }), mangaTitle: z.string().min(1, { message: 'Please select a manga' }), - interval: z.string().min(1, { message: 'Please select an interval' }), + interval: z + .string({ + invalid_type_error: 'Invalid interval', + }) + .min(1, { message: 'Please select an interval' }) + .refine((value) => isCronValid(value), { + message: 'Invalid interval', + }), }); export type FormType = z.TypeOf; @@ -96,6 +104,9 @@ export function AddMangaForm({ onClose }: { onClose: () => void }) { }; const onSubmit = form.onSubmit(async (values) => { + if (active !== 3) { + return; + } setVisible((v) => !v); const { mangaTitle, source, interval } = values; try { diff --git a/src/components/addManga/steps/downloadStep.tsx b/src/components/addManga/steps/downloadStep.tsx index a0aabc1..56ade8e 100644 --- a/src/components/addManga/steps/downloadStep.tsx +++ b/src/components/addManga/steps/downloadStep.tsx @@ -1,19 +1,22 @@ import { Box, LoadingOverlay, Select, Stack, TextInput } from '@mantine/core'; import { UseFormReturnType } from '@mantine/form'; import { IconFolderPlus } from '@tabler/icons'; -import { sanitizer } from '../../../utils/sanitize'; +import { useState } from 'react'; +import { getCronLabel, isCronValid, sanitizer } from '../../../utils'; import { trpc } from '../../../utils/trpc'; import type { FormType } from '../form'; -const availableIntervals = ['daily', 'hourly', 'weekly']; - export function DownloadStep({ form }: { form: UseFormReturnType }) { + const [data, setData] = useState( + ['0 0 * * *', '0 * * * *', '0 0 * * 7', 'never'].map((value) => ({ + label: getCronLabel(value), + value, + })), + ); const libraryQuery = trpc.library.query.useQuery(); const libraryPath = libraryQuery.data?.path; - const intervalSelectData = availableIntervals.map((k) => ({ label: k, value: k })); - if (libraryQuery.isLoading) { return ; } @@ -25,10 +28,29 @@ export function DownloadStep({ form }: { form: UseFormReturnType }) {