From 7224c59b4dc3ac901473f8e66f218f5e704f9043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Trembeck=C3=BD?= Date: Fri, 8 Dec 2023 15:51:31 +0100 Subject: [PATCH] React Admin - events, competitions, series - eh? (#233) * react admin: event management (unfinished) * unify pessimistic mutationMode with redirect to show * MyCreate to unify redirect to show on create going forward * some competition management, will be tested/adjusted later * some series management * new BE endpoint for competition slug, old used for ID access --- src/components/Admin/Admin.tsx | 23 ++++++- .../Admin/custom/CompetitionField.tsx | 13 ++++ .../Admin/custom/CompetitionInput.tsx | 13 ++++ src/components/Admin/custom/JsonField.tsx | 12 ++++ src/components/Admin/custom/MyCreate.tsx | 4 ++ src/components/Admin/custom/MyEdit.tsx | 10 ++++ .../Admin/resources/cms/post/PostCreate.tsx | 6 +- .../Admin/resources/cms/post/PostEdit.tsx | 7 +-- .../competition/CompetitionCreate.tsx | 47 +++++++++++++++ .../competition/CompetitionEdit.tsx | 36 +++++++++++ .../competition/CompetitionList.tsx | 28 +++++++++ .../competition/CompetitionShow.tsx | 55 +++++++++++++++++ .../competition/event/EventCreate.tsx | 51 ++++++++++++++++ .../resources/competition/event/EventEdit.tsx | 51 ++++++++++++++++ .../resources/competition/event/EventList.tsx | 30 ++++++++++ .../resources/competition/event/EventShow.tsx | 60 +++++++++++++++++++ .../competition/series/SeriesEdit.tsx | 26 ++++++++ .../competition/series/SeriesList.tsx} | 8 ++- .../competition/series/SeriesShow.tsx | 43 +++++++++++++ src/pages/strom/akcie/[[...params]].tsx | 2 +- 20 files changed, 511 insertions(+), 14 deletions(-) create mode 100644 src/components/Admin/custom/CompetitionField.tsx create mode 100644 src/components/Admin/custom/CompetitionInput.tsx create mode 100644 src/components/Admin/custom/JsonField.tsx create mode 100644 src/components/Admin/custom/MyCreate.tsx create mode 100644 src/components/Admin/custom/MyEdit.tsx create mode 100644 src/components/Admin/resources/competition/competition/CompetitionCreate.tsx create mode 100644 src/components/Admin/resources/competition/competition/CompetitionEdit.tsx create mode 100644 src/components/Admin/resources/competition/competition/CompetitionList.tsx create mode 100644 src/components/Admin/resources/competition/competition/CompetitionShow.tsx create mode 100644 src/components/Admin/resources/competition/event/EventCreate.tsx create mode 100644 src/components/Admin/resources/competition/event/EventEdit.tsx create mode 100644 src/components/Admin/resources/competition/event/EventList.tsx create mode 100644 src/components/Admin/resources/competition/event/EventShow.tsx create mode 100644 src/components/Admin/resources/competition/series/SeriesEdit.tsx rename src/components/Admin/{Competition/CompetitionList.tsx => resources/competition/series/SeriesList.tsx} (71%) create mode 100644 src/components/Admin/resources/competition/series/SeriesShow.tsx diff --git a/src/components/Admin/Admin.tsx b/src/components/Admin/Admin.tsx index 8ecdfa98..5d7f77d3 100644 --- a/src/components/Admin/Admin.tsx +++ b/src/components/Admin/Admin.tsx @@ -1,12 +1,22 @@ import {FC} from 'react' import {Admin as ReactAdmin, Resource} from 'react-admin' -import {CompetitionList} from './Competition/CompetitionList' import {dataProvider} from './dataProvider' import {PostCreate} from './resources/cms/post/PostCreate' import {PostEdit} from './resources/cms/post/PostEdit' import {PostList} from './resources/cms/post/PostList' import {PostShow} from './resources/cms/post/PostShow' +import {CompetitionCreate} from './resources/competition/competition/CompetitionCreate' +import {CompetitionEdit} from './resources/competition/competition/CompetitionEdit' +import {CompetitionList} from './resources/competition/competition/CompetitionList' +import {CompetitionShow} from './resources/competition/competition/CompetitionShow' +import {EventCreate} from './resources/competition/event/EventCreate' +import {EventEdit} from './resources/competition/event/EventEdit' +import {EventList} from './resources/competition/event/EventList' +import {EventShow} from './resources/competition/event/EventShow' +import {SeriesEdit} from './resources/competition/series/SeriesEdit' +import {SeriesList} from './resources/competition/series/SeriesList' +import {SeriesShow} from './resources/competition/series/SeriesShow' import {useAuthProvider} from './useAuthProvider' export const Admin: FC = () => { @@ -15,8 +25,15 @@ export const Admin: FC = () => { return ( - {/* TODO: create, edit, celkovo rozumne rozhranie pre sutaze/serie */} - + + + ) } diff --git a/src/components/Admin/custom/CompetitionField.tsx b/src/components/Admin/custom/CompetitionField.tsx new file mode 100644 index 00000000..29f31166 --- /dev/null +++ b/src/components/Admin/custom/CompetitionField.tsx @@ -0,0 +1,13 @@ +import {ComponentProps, FC} from 'react' +import {SelectField, useGetList} from 'react-admin' + +export const CompetitionField: FC> = (props) => { + const {data, isLoading, error} = useGetList('competition/competition') + + const typedData = data as {id: number; name: string}[] + + if (isLoading) return Loading... + if (error) return Error occured loading competitions: {error.message} + + return +} diff --git a/src/components/Admin/custom/CompetitionInput.tsx b/src/components/Admin/custom/CompetitionInput.tsx new file mode 100644 index 00000000..9017f65b --- /dev/null +++ b/src/components/Admin/custom/CompetitionInput.tsx @@ -0,0 +1,13 @@ +import {ComponentProps, FC} from 'react' +import {SelectInput, useGetList} from 'react-admin' + +export const CompetitionInput: FC> = (props) => { + const {data, isLoading, error} = useGetList('competition/competition') + + const typedData = data as {id: number; name: string}[] + + if (isLoading) return Loading... + if (error) return Error occured loading competitions: {error.message} + + return +} diff --git a/src/components/Admin/custom/JsonField.tsx b/src/components/Admin/custom/JsonField.tsx new file mode 100644 index 00000000..202c2df3 --- /dev/null +++ b/src/components/Admin/custom/JsonField.tsx @@ -0,0 +1,12 @@ +import {FC} from 'react' +import {FieldProps, useRecordContext} from 'react-admin' + +export const JsonField: FC = ({source}) => { + const record = useRecordContext() + if (!record || !source) return null + + const value = record[source] + const text = JSON.stringify(value, null, 2) + + return
{text}
+} diff --git a/src/components/Admin/custom/MyCreate.tsx b/src/components/Admin/custom/MyCreate.tsx new file mode 100644 index 00000000..173630b3 --- /dev/null +++ b/src/components/Admin/custom/MyCreate.tsx @@ -0,0 +1,4 @@ +import {FC, PropsWithChildren} from 'react' +import {Create} from 'react-admin' + +export const MyCreate: FC = ({children}) => {children} diff --git a/src/components/Admin/custom/MyEdit.tsx b/src/components/Admin/custom/MyEdit.tsx new file mode 100644 index 00000000..55f6fe9f --- /dev/null +++ b/src/components/Admin/custom/MyEdit.tsx @@ -0,0 +1,10 @@ +import {FC, PropsWithChildren} from 'react' +import {Edit} from 'react-admin' + +import {MyEditActions} from './MyEditActions' + +export const MyEdit: FC = ({children}) => ( + } mutationMode="pessimistic" redirect="show"> + {children} + +) diff --git a/src/components/Admin/resources/cms/post/PostCreate.tsx b/src/components/Admin/resources/cms/post/PostCreate.tsx index a4f34eb5..36798b4c 100644 --- a/src/components/Admin/resources/cms/post/PostCreate.tsx +++ b/src/components/Admin/resources/cms/post/PostCreate.tsx @@ -1,7 +1,6 @@ import {FC} from 'react' import { ArrayInput, - Create, DateTimeInput, FormTab, NumberInput, @@ -11,10 +10,11 @@ import { TextInput, } from 'react-admin' +import {MyCreate} from '@/components/Admin/custom/MyCreate' import {SitesCheckboxInput} from '@/components/Admin/custom/SitesCheckboxInput' export const PostCreate: FC = () => ( - + @@ -36,5 +36,5 @@ export const PostCreate: FC = () => ( - + ) diff --git a/src/components/Admin/resources/cms/post/PostEdit.tsx b/src/components/Admin/resources/cms/post/PostEdit.tsx index 5f344b9b..4d8d3215 100644 --- a/src/components/Admin/resources/cms/post/PostEdit.tsx +++ b/src/components/Admin/resources/cms/post/PostEdit.tsx @@ -2,7 +2,6 @@ import {FC} from 'react' import { ArrayInput, DateTimeInput, - Edit, FormTab, NumberInput, required, @@ -11,11 +10,11 @@ import { TextInput, } from 'react-admin' -import {MyEditActions} from '@/components/Admin/custom/MyEditActions' +import {MyEdit} from '@/components/Admin/custom/MyEdit' import {SitesCheckboxInput} from '@/components/Admin/custom/SitesCheckboxInput' export const PostEdit: FC = () => ( - } redirect="show" mutationMode="undoable"> + @@ -37,5 +36,5 @@ export const PostEdit: FC = () => ( - + ) diff --git a/src/components/Admin/resources/competition/competition/CompetitionCreate.tsx b/src/components/Admin/resources/competition/competition/CompetitionCreate.tsx new file mode 100644 index 00000000..0a33a3da --- /dev/null +++ b/src/components/Admin/resources/competition/competition/CompetitionCreate.tsx @@ -0,0 +1,47 @@ +import {FC} from 'react' +import { + ArrayInput, + DateTimeInput, + FormTab, + NumberInput, + required, + SimpleFormIterator, + TabbedForm, + TextInput, +} from 'react-admin' + +import {MyCreate} from '@/components/Admin/custom/MyCreate' +import {SitesCheckboxInput} from '@/components/Admin/custom/SitesCheckboxInput' + +export const CompetitionCreate: FC = () => ( + + + + {/* */} + + + + + {/* TODO: radio buttons / select */} + + + + + {/* maju sa dat eventy vytvarat pri tvoreni competition? */} + + + + {/* */} + + + + + + {/* unspecifiedpublication_set: UnspecifiedPublication[] + registration_links: RegistrationLink[] */} + + + + + +) diff --git a/src/components/Admin/resources/competition/competition/CompetitionEdit.tsx b/src/components/Admin/resources/competition/competition/CompetitionEdit.tsx new file mode 100644 index 00000000..06e8ef6f --- /dev/null +++ b/src/components/Admin/resources/competition/competition/CompetitionEdit.tsx @@ -0,0 +1,36 @@ +import {FC} from 'react' +import {ArrayInput, FormTab, NumberInput, required, SimpleFormIterator, TabbedForm, TextInput} from 'react-admin' + +import {MyEdit} from '@/components/Admin/custom/MyEdit' +import {SitesCheckboxInput} from '@/components/Admin/custom/SitesCheckboxInput' + +export const CompetitionEdit: FC = () => ( + + + + + + + + + + + + + + + + + {/* unspecifiedpublication_set: UnspecifiedPublication[] + registration_links: RegistrationLink[] */} + + + + + + + + + + +) diff --git a/src/components/Admin/resources/competition/competition/CompetitionList.tsx b/src/components/Admin/resources/competition/competition/CompetitionList.tsx new file mode 100644 index 00000000..2401ff02 --- /dev/null +++ b/src/components/Admin/resources/competition/competition/CompetitionList.tsx @@ -0,0 +1,28 @@ +import {FC} from 'react' +import {Datagrid, FunctionField, List, NumberField, RaRecord, TextField} from 'react-admin' + +import {SitesArrayField} from '@/components/Admin/custom/SitesArrayField' +import {TruncatedTextField} from '@/components/Admin/custom/TruncatedTextField' + +export const CompetitionList: FC = () => ( + + + + + + + + + {/* */} + + + + + + source="history_events" + label="History events count" + render={(record) => record && {record['history_events'].length}} + /> + + +) diff --git a/src/components/Admin/resources/competition/competition/CompetitionShow.tsx b/src/components/Admin/resources/competition/competition/CompetitionShow.tsx new file mode 100644 index 00000000..b022f33b --- /dev/null +++ b/src/components/Admin/resources/competition/competition/CompetitionShow.tsx @@ -0,0 +1,55 @@ +import {FC} from 'react' +import { + ArrayField, + Datagrid, + DateField, + NumberField, + Show, + SimpleShowLayout, + Tab, + TabbedShowLayout, + TextField, +} from 'react-admin' + +import {JsonField} from '@/components/Admin/custom/JsonField' +import {MyShowActions} from '@/components/Admin/custom/MyShowActions' +import {SitesArrayField} from '@/components/Admin/custom/SitesArrayField' +import {TruncatedTextField} from '@/components/Admin/custom/TruncatedTextField' + +export const CompetitionShow: FC = () => ( + }> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/src/components/Admin/resources/competition/event/EventCreate.tsx b/src/components/Admin/resources/competition/event/EventCreate.tsx new file mode 100644 index 00000000..ee5b682d --- /dev/null +++ b/src/components/Admin/resources/competition/event/EventCreate.tsx @@ -0,0 +1,51 @@ +import {FC} from 'react' +import { + ArrayInput, + DateTimeInput, + FormTab, + NumberInput, + required, + SimpleFormIterator, + TabbedForm, + TextInput, +} from 'react-admin' + +import {CompetitionInput} from '@/components/Admin/custom/CompetitionInput' +import {MyCreate} from '@/components/Admin/custom/MyCreate' + +export const EventCreate: FC = () => ( + + + + + + + napr. 2023/2024 + + + + + TODO: always sends null as registration_link + + + TODO: publikacie treba vediet nahrat, nie tu editovat db + + + + + + + + + + + + + +) diff --git a/src/components/Admin/resources/competition/event/EventEdit.tsx b/src/components/Admin/resources/competition/event/EventEdit.tsx new file mode 100644 index 00000000..efb20c6a --- /dev/null +++ b/src/components/Admin/resources/competition/event/EventEdit.tsx @@ -0,0 +1,51 @@ +import {FC} from 'react' +import { + ArrayInput, + DateTimeInput, + FormTab, + NumberInput, + required, + SimpleFormIterator, + TabbedForm, + TextInput, +} from 'react-admin' + +import {CompetitionInput} from '@/components/Admin/custom/CompetitionInput' +import {MyEdit} from '@/components/Admin/custom/MyEdit' + +export const EventEdit: FC = () => ( + + + + + + + napr. 2023/2024 + + + + + TODO: always sends null as registration_link + + + TODO: publikacie treba vediet nahrat, nie tu editovat db + + + + + + + + + + + + + +) diff --git a/src/components/Admin/resources/competition/event/EventList.tsx b/src/components/Admin/resources/competition/event/EventList.tsx new file mode 100644 index 00000000..5869f109 --- /dev/null +++ b/src/components/Admin/resources/competition/event/EventList.tsx @@ -0,0 +1,30 @@ +import {FC} from 'react' +import {BooleanField, Datagrid, DateField, FunctionField, List, NumberField, RaRecord, TextField} from 'react-admin' + +import {CompetitionField} from '@/components/Admin/custom/CompetitionField' + +export const EventList: FC = () => ( + + + + + + + + + + + + + + + + + + source="publication_set" + label="Publication count" + render={(record) => record && {record['publication_set'].length}} + /> + + +) diff --git a/src/components/Admin/resources/competition/event/EventShow.tsx b/src/components/Admin/resources/competition/event/EventShow.tsx new file mode 100644 index 00000000..ae4dc711 --- /dev/null +++ b/src/components/Admin/resources/competition/event/EventShow.tsx @@ -0,0 +1,60 @@ +import {FC} from 'react' +import { + ArrayField, + BooleanField, + Datagrid, + DateField, + NumberField, + Show, + SimpleShowLayout, + Tab, + TabbedShowLayout, + TextField, +} from 'react-admin' + +import {CompetitionField} from '@/components/Admin/custom/CompetitionField' +import {MyShowActions} from '@/components/Admin/custom/MyShowActions' + +export const EventShow: FC = () => ( + }> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/src/components/Admin/resources/competition/series/SeriesEdit.tsx b/src/components/Admin/resources/competition/series/SeriesEdit.tsx new file mode 100644 index 00000000..9d8b7b5c --- /dev/null +++ b/src/components/Admin/resources/competition/series/SeriesEdit.tsx @@ -0,0 +1,26 @@ +import {FC} from 'react' +import {ArrayInput, DateInput, FormTab, NumberInput, SimpleFormIterator, TabbedForm, TextInput} from 'react-admin' + +import {MyEdit} from '@/components/Admin/custom/MyEdit' + +// TODO: premysliet a prerobit rozhranie, mozno ako u postov - pri kliku na riadok ukazat Show, kde budu priklady +// (nie ako teraz v zanorenom Datagride) +export const SeriesEdit: FC = () => ( + + + + + + + + + + + + + + + + + +) diff --git a/src/components/Admin/Competition/CompetitionList.tsx b/src/components/Admin/resources/competition/series/SeriesList.tsx similarity index 71% rename from src/components/Admin/Competition/CompetitionList.tsx rename to src/components/Admin/resources/competition/series/SeriesList.tsx index 9d2453ba..ab1f7e53 100644 --- a/src/components/Admin/Competition/CompetitionList.tsx +++ b/src/components/Admin/resources/competition/series/SeriesList.tsx @@ -1,18 +1,20 @@ import {FC} from 'react' import {ArrayField, Datagrid, DateField, List, TextField} from 'react-admin' +import {TruncatedTextField} from '@/components/Admin/custom/TruncatedTextField' + // TODO: premysliet a prerobit rozhranie, mozno ako u postov - pri kliku na riadok ukazat Show, kde budu priklady // (nie ako teraz v zanorenom Datagride) -export const CompetitionList: FC = () => ( +export const SeriesList: FC = () => ( - + - + diff --git a/src/components/Admin/resources/competition/series/SeriesShow.tsx b/src/components/Admin/resources/competition/series/SeriesShow.tsx new file mode 100644 index 00000000..76a10161 --- /dev/null +++ b/src/components/Admin/resources/competition/series/SeriesShow.tsx @@ -0,0 +1,43 @@ +import {FC} from 'react' +import { + ArrayField, + BooleanField, + Datagrid, + DateField, + NumberField, + Show, + SimpleShowLayout, + Tab, + TabbedShowLayout, + TextField, +} from 'react-admin' + +import {MyShowActions} from '@/components/Admin/custom/MyShowActions' +import {TruncatedTextField} from '@/components/Admin/custom/TruncatedTextField' + +export const SeriesShow: FC = () => ( + }> + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/src/pages/strom/akcie/[[...params]].tsx b/src/pages/strom/akcie/[[...params]].tsx index 492d3857..7cf9ebbf 100644 --- a/src/pages/strom/akcie/[[...params]].tsx +++ b/src/pages/strom/akcie/[[...params]].tsx @@ -45,7 +45,7 @@ export const competitionBasedGetServerSideProps = try { const {data} = await axios.get( - `${process.env.NEXT_PUBLIC_BE_PROTOCOL}://${process.env.NEXT_PUBLIC_BE_HOSTNAME}:${process.env.NEXT_PUBLIC_BE_PORT}/competition/competition/${requestedUrl}`, + `${process.env.NEXT_PUBLIC_BE_PROTOCOL}://${process.env.NEXT_PUBLIC_BE_HOSTNAME}:${process.env.NEXT_PUBLIC_BE_PORT}/competition/competition/slug/${requestedUrl}`, ) if (!data) return redirectToSeminar