Skip to content

Commit

Permalink
RA upload solution (#377)
Browse files Browse the repository at this point in the history
* add solution to RA

* create solution uploader

* fix showing event-registration references

* client-side filter

* create even registration in RA

* add event field to event registration

* add late_tag and is_online to solution

* Results changes after backend now returns the entire grade object

See ZdruzenieSTROM/webstrom-backend#426

* RA create solution also sending false-y but non-null values (e. g. 0)

* RA EventRegistration changes after backend update

* RA EventRegistrations fixed typing

---------

Co-authored-by: rtrembecky <[email protected]>
Co-authored-by: Michal Masrna <[email protected]>
  • Loading branch information
3 people authored Nov 22, 2024
1 parent 4c7f127 commit 9f01669
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 5 deletions.
27 changes: 27 additions & 0 deletions src/components/Admin/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ 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 {EventRegistrationCreate} from './resources/competition/event-registration/EventRegistrationCreate'
import {EventRegistrationEdit} from './resources/competition/event-registration/EventRegistrationEdit'
import {EventRegistrationList} from './resources/competition/event-registration/EventRegistrationList'
import {EventRegistrationShow} from './resources/competition/event-registration/EventRegistrationShow'
import {ProblemCreate} from './resources/competition/problems/ProblemCreate'
import {ProblemEdit} from './resources/competition/problems/ProblemEdit'
import {ProblemList} from './resources/competition/problems/ProblemList'
Expand All @@ -30,6 +34,10 @@ import {SeriesCreate} from './resources/competition/series/SeriesCreate'
import {SeriesEdit} from './resources/competition/series/SeriesEdit'
import {SeriesList} from './resources/competition/series/SeriesList'
import {SeriesShow} from './resources/competition/series/SeriesShow'
import {SolutionCreate} from './resources/competition/solution/SolutionCreate'
import {SolutionEdit} from './resources/competition/solution/SolutionEdit'
import {SolutionList} from './resources/competition/solution/SolutionList'
import {SolutionShow} from './resources/competition/solution/SolutionShow'
import {useAuthProvider} from './useAuthProvider'

export const Admin: FC = () => {
Expand Down Expand Up @@ -85,6 +93,25 @@ export const Admin: FC = () => {
show={ProblemShow}
create={ProblemCreate}
/>
<Resource
name="competition/solution"
recordRepresentation="verbose_name"
list={SolutionList}
edit={SolutionEdit}
show={SolutionShow}
create={SolutionCreate}
/>
<Resource
name="competition/event-registration"
recordRepresentation="verbose_name"
list={EventRegistrationList}
edit={EventRegistrationEdit}
show={EventRegistrationShow}
create={EventRegistrationCreate}
/>
<Resource name="personal/schools" recordRepresentation="verbose_name" />
<Resource name="personal/profiles" recordRepresentation="verbose_name" />
<Resource name="competition/late-tag" recordRepresentation="name" />
</ReactAdmin>
)
}
20 changes: 17 additions & 3 deletions src/components/Admin/dataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,32 @@ export const dataProvider: DataProvider = {
const stringifiedQuery = stringify(query)
const {data} = await axios.get(`${apiUrl}/${resource}${stringifiedQuery ? `/?${stringifiedQuery}` : ''}`)

// client-side filter
const filter = params.filter.q
let filteredData = data
if (filter) {
// v podstate vygenerovane Copilotom :D
// vyhladava to filter string vo vsetkych fieldoch kazdeho recordu
filteredData = data.filter((record: RaRecord) => {
return Object.keys(record).some((key) => {
const value = record[key]
return value && value.toString().toLowerCase().includes(filter.toLowerCase())
})
})
}

// client-side sort
const {field, order} = params.sort

data.sort(dynamicSort(field, order))
filteredData.sort(dynamicSort(field, order))

// client-side pagination
const {page, perPage} = params.pagination
const pagedData = data.slice((page - 1) * perPage, page * perPage)
const pagedData = filteredData.slice((page - 1) * perPage, page * perPage)

return {
data: pagedData,
total: data.length,
total: filteredData.length,
}
},
getOne: async (resource, params) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {FC} from 'react'
import {AutocompleteInput, ReferenceInput, required, SimpleForm} from 'react-admin'

import {MyCreate} from '@/components/Admin/custom/MyCreate'

export const EventRegistrationCreate: FC = () => (
<MyCreate>
<SimpleForm>
<ReferenceInput source="profile" reference="personal/profiles">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="school" reference="personal/schools">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="grade" reference="competition/grade">
<AutocompleteInput optionText="name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="event" reference="competition/event">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
</SimpleForm>
</MyCreate>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {FC} from 'react'
import {AutocompleteInput, ReferenceInput, required, SimpleForm} from 'react-admin'

import {MyEdit} from '@/components/Admin/custom/MyEdit'

export const EventRegistrationEdit: FC = () => (
<MyEdit
transform={(record) => {
record.profile = record.profile.id
record.school = record.school.code
record.grade = record.grade.id
return record
}}
>
<SimpleForm>
<ReferenceInput source="profile.id" reference="personal/profiles">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="school.code" reference="personal/schools">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="grade.id" reference="competition/grade">
<AutocompleteInput optionText="name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="event" reference="competition/event">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
</SimpleForm>
</MyEdit>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {FC} from 'react'
import {Datagrid, FunctionField, List, ReferenceField, TextField} from 'react-admin'

import {EventRegistration} from '@/types/api/competition'

export const EventRegistrationList: FC = () => (
<List>
<Datagrid rowClick="show">
<FunctionField
source="profile.last_name"
label="Meno a priezvisko"
render={(record: EventRegistration) => `${record.profile.first_name} ${record.profile.last_name}`}
/>
<TextField source="school.abbreviation" label="Škola" />
<TextField source="grade.tag" label="Ročník" />
<ReferenceField source="event" reference="competition/event" link={false} />
</Datagrid>
</List>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {FC} from 'react'
import {FunctionField, ReferenceField, SimpleShowLayout, TextField} from 'react-admin'

import {MyShow} from '@/components/Admin/custom/MyShow'
import {EventRegistration} from '@/types/api/competition'

export const EventRegistrationShow: FC = () => (
<MyShow>
<SimpleShowLayout>
<FunctionField
source="profile.last_name"
label="Meno a priezvisko"
render={(record: EventRegistration) => `${record.profile.first_name} ${record.profile.last_name}`}
/>
<TextField source="school.abbreviation" label="Škola" />
<TextField source="grade.tag" label="Ročník" />
<ReferenceField source="event" reference="competition/event" link={false} />
</SimpleShowLayout>
</MyShow>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {FC} from 'react'
import {AutocompleteInput, BooleanInput, FileInput, ReferenceInput, required, SimpleForm} from 'react-admin'

import {MyCreate} from '@/components/Admin/custom/MyCreate'
import {MyFileField} from '@/components/Admin/custom/MyFileField'

import {createSolutionFormData} from './createSolutionFormData'

export const SolutionCreate: FC = () => (
<MyCreate
transform={(record) => {
record.formData = createSolutionFormData(record)
return record
}}
>
<SimpleForm>
<ReferenceInput source="problem" reference="competition/problem">
<AutocompleteInput fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="semester_registration" reference="competition/event-registration">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
<FileInput source="solution" accept="application/pdf">
<MyFileField />
</FileInput>
<ReferenceInput source="late_tag" reference="competition/late-tag" label="Je riešenie po termíne?">
<AutocompleteInput optionText="name" fullWidth />
</ReferenceInput>
<BooleanInput source="is_online" label="Je to internetové riešenie?" />
</SimpleForm>
</MyCreate>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {FC} from 'react'
import {AutocompleteInput, BooleanInput, FileInput, ReferenceInput, required, SimpleForm} from 'react-admin'

import {MyEdit} from '@/components/Admin/custom/MyEdit'
import {MyFileField} from '@/components/Admin/custom/MyFileField'

import {createSolutionFormData} from './createSolutionFormData'

export const SolutionEdit: FC = () => (
<MyEdit
transform={(record) => {
record.formData = createSolutionFormData(record)
return record
}}
>
<SimpleForm>
<ReferenceInput source="problem" reference="competition/problem">
<AutocompleteInput fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="semester_registration" reference="competition/event-registration">
<AutocompleteInput optionText="verbose_name" fullWidth validate={required()} />
</ReferenceInput>
<FileInput source="solution" accept="application/pdf">
<MyFileField />
</FileInput>
<ReferenceInput source="late_tag" reference="competition/late-tag" label="Je riešenie po termíne?">
<AutocompleteInput optionText="name" fullWidth />
</ReferenceInput>
<BooleanInput source="is_online" label="Je to internetové riešenie?" />
</SimpleForm>
</MyEdit>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {FC} from 'react'
import {BooleanField, Datagrid, FunctionField, List, RaRecord, ReferenceField} from 'react-admin'

export const SolutionList: FC = () => (
<List>
<Datagrid rowClick="show">
<ReferenceField source="problem" reference="competition/problem" link={false} />
<ReferenceField source="semester_registration" reference="competition/event-registration" link={false} />
<FunctionField<RaRecord>
label="Má nahraté riešenie"
render={(record) => record && <BooleanField record={{xxx: !!record['solution']}} source="xxx" />}
/>
<ReferenceField source="late_tag" reference="competition/late-tag" label="Po termíne" link={false} />
<BooleanField source="is_online" label="Internetové riešenie" />
</Datagrid>
</List>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {FC} from 'react'
import {BooleanField, FileField, ReferenceField, SimpleShowLayout} from 'react-admin'

import {MyShow} from '@/components/Admin/custom/MyShow'

export const SolutionShow: FC = () => (
<MyShow>
<SimpleShowLayout>
<ReferenceField source="problem" reference="competition/problem" link="show" />
<ReferenceField source="semester_registration" reference="competition/event-registration" link="show" />
<FileField source="solution" title="Riešenie" />
<ReferenceField source="late_tag" reference="competition/late-tag" label="Po termíne" link="show" />
<BooleanField source="is_online" label="Internetové riešenie" />
</SimpleShowLayout>
</MyShow>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Solution} from '@/types/api/competition'

export const createSolutionFormData = ({
solution,
...data
}: Omit<Solution, 'solution'> & {
solution?: {rawFile: File}
}) => {
const formData = new FormData()
// vzdy appendneme kazdy kluc, aj tieto fily, len null sa tu neda pouzit. null znamena, ze file odstranujeme
formData.append('solution', solution?.rawFile ?? '')
Object.entries(data).forEach(([key, value]) => {
if (value != null) formData.append(key, value.toString())
})

return formData
}
9 changes: 7 additions & 2 deletions src/components/Results/ResultsRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ interface Registration {
city: string
zip_code: string
}
grade: string
grade: {
name: string
tag: string
years_until_graduation: number
is_active: boolean
}
profile: {
first_name: string
last_name: string
Expand Down Expand Up @@ -63,7 +68,7 @@ export const ResultsRow: FC<{result: Result}> = ({result}) => {
</Stack>
<Stack sx={{justifyContent: 'center'}}>
<Typography variant="h3" component="span" fontWeight={400} fontStyle="italic">
{registration.grade}
{registration.grade.tag}
</Typography>
</Stack>
<Stack sx={{justifyContent: 'center', px: '10px'}}>
Expand Down

0 comments on commit 9f01669

Please sign in to comment.