diff --git a/README.md b/README.md index 2e4840c..b6f04b2 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,9 @@ 3. `docker compose up -d && docker compose logs -f` - Frontend: [localhost:8080](http://localhost:8080) -- ICal Calendar: [localhost:8080/ical?u=1&l=Tutorium](http://localhost:8080/ical?u=1&l=Tutorium) +- ICal Calendar: [localhost:8080/ical?e=1&ty=Tutorium&to=Informatik](http://localhost:8080/ical?e=1&ty=Tutorium&to=Informatik) - API: [localhost:8080/api](http://localhost:8080/api) - GraphQL Playground: [localhost:8080/playground](http://localhost:8080/playground) - - Documentation for all endpoints can be found in the [`server/README.md`](server/README.md) ### dev #### frontend diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 738612b..9d968e0 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -91,7 +91,8 @@ export default function Home() { const [types, setTypes] = useState([]); const [topics, setTopics] = useState([]); const [loading, setLoading] = useState(true); - const [filter, setFilter] = useState([]); + const [toFilter, setToFilter] = useState([]); + const [tyFilter, setTyFilter] = useState([]); const [umbrellaSelectionOpen, setUmbrellaSelectionOpen] = useState(false); const [popupId, setPopupId] = useState(0); @@ -101,7 +102,8 @@ export default function Home() { const vars: PlannerEventsQueryVariables = { umbrellaID: umbrella, - filter: filter.length == 0 ? undefined : filter, + topic: toFilter.length == 0 ? undefined : toFilter, + type: tyFilter.length == 0 ? undefined : tyFilter, }; await new Promise((resolve) => setTimeout(resolve, 250)); @@ -135,7 +137,7 @@ export default function Home() { getUmbrellas(); fetchData(); - }, [filter, umbrella]); + }, [toFilter, tyFilter, umbrella]); const groupedEvents = groupEvents(events); @@ -204,14 +206,14 @@ export default function Home() { t.name)} - filter={filter} - setFilter={setFilter} + filter={toFilter} + setFilter={setToFilter} /> t.name)} - filter={filter} - setFilter={setFilter} + filter={tyFilter} + setFilter={setTyFilter} /> )} diff --git a/frontend/lib/gql/generated/gql.ts b/frontend/lib/gql/generated/gql.ts index 30f80dc..28d979e 100644 --- a/frontend/lib/gql/generated/gql.ts +++ b/frontend/lib/gql/generated/gql.ts @@ -15,7 +15,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ const documents = { "mutation addStudentApplicationForEvent($application: NewUserToEventApplication!) {\n addStudentApplicationForEvent(application: $application) {\n fn\n }\n}": types.AddStudentApplicationForEventDocument, "mutation addTutor($firstName: String!, $lastName: String!, $email: String!, $eventsAvailable: [Int!]!) {\n addTutor(\n tutor: {fn: $firstName, sn: $lastName, mail: $email}\n availability: {userMail: $email, eventID: $eventsAvailable}\n ) {\n fn\n }\n}": types.AddTutorDocument, - "query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}\n\nquery plannerEvents($umbrellaID: Int!, $filter: [String!]) {\n umbrellas(id: [$umbrellaID]) {\n title\n }\n typeLabels: labels(kind: EVENT_TYPE, umbrellaID: [$umbrellaID]) {\n name\n }\n topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) {\n name\n }\n events(umbrellaID: [$umbrellaID], label: $filter) {\n ID\n title\n from\n to\n topic {\n color\n }\n }\n}\n\nquery eventCloseup($id: Int!) {\n events(id: [$id]) {\n ID\n title\n description\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n tutorsAssigned {\n tutors {\n fn\n sn\n mail\n }\n room {\n capacity\n floor\n name\n number\n building {\n name\n street\n number\n city\n zip\n latitude\n longitude\n zoomLevel\n }\n }\n registrations\n }\n }\n}": types.TutorFormEventsDocument, + "query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}\n\nquery plannerEvents($umbrellaID: Int!, $type: [String!], $topic: [String!]) {\n umbrellas(id: [$umbrellaID]) {\n title\n }\n typeLabels: labels(kind: EVENT_TYPE, umbrellaID: [$umbrellaID]) {\n name\n }\n topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) {\n name\n }\n events(umbrellaID: [$umbrellaID], type: $type, topic: $topic) {\n ID\n title\n from\n to\n topic {\n color\n }\n }\n}\n\nquery eventCloseup($id: Int!) {\n events(id: [$id]) {\n ID\n title\n description\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n tutorsAssigned {\n tutors {\n fn\n sn\n mail\n }\n room {\n capacity\n floor\n name\n number\n building {\n name\n street\n number\n city\n zip\n latitude\n longitude\n zoomLevel\n }\n }\n registrations\n }\n }\n}": types.TutorFormEventsDocument, "query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n ID\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}": types.RegistrationFormDocument, "query umbrellas {\n umbrellas {\n ID\n title\n }\n}": types.UmbrellasDocument, }; @@ -45,7 +45,7 @@ export function graphql(source: "mutation addTutor($firstName: String!, $lastNam /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}\n\nquery plannerEvents($umbrellaID: Int!, $filter: [String!]) {\n umbrellas(id: [$umbrellaID]) {\n title\n }\n typeLabels: labels(kind: EVENT_TYPE, umbrellaID: [$umbrellaID]) {\n name\n }\n topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) {\n name\n }\n events(umbrellaID: [$umbrellaID], label: $filter) {\n ID\n title\n from\n to\n topic {\n color\n }\n }\n}\n\nquery eventCloseup($id: Int!) {\n events(id: [$id]) {\n ID\n title\n description\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n tutorsAssigned {\n tutors {\n fn\n sn\n mail\n }\n room {\n capacity\n floor\n name\n number\n building {\n name\n street\n number\n city\n zip\n latitude\n longitude\n zoomLevel\n }\n }\n registrations\n }\n }\n}"): (typeof documents)["query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}\n\nquery plannerEvents($umbrellaID: Int!, $filter: [String!]) {\n umbrellas(id: [$umbrellaID]) {\n title\n }\n typeLabels: labels(kind: EVENT_TYPE, umbrellaID: [$umbrellaID]) {\n name\n }\n topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) {\n name\n }\n events(umbrellaID: [$umbrellaID], label: $filter) {\n ID\n title\n from\n to\n topic {\n color\n }\n }\n}\n\nquery eventCloseup($id: Int!) {\n events(id: [$id]) {\n ID\n title\n description\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n tutorsAssigned {\n tutors {\n fn\n sn\n mail\n }\n room {\n capacity\n floor\n name\n number\n building {\n name\n street\n number\n city\n zip\n latitude\n longitude\n zoomLevel\n }\n }\n registrations\n }\n }\n}"]; +export function graphql(source: "query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}\n\nquery plannerEvents($umbrellaID: Int!, $type: [String!], $topic: [String!]) {\n umbrellas(id: [$umbrellaID]) {\n title\n }\n typeLabels: labels(kind: EVENT_TYPE, umbrellaID: [$umbrellaID]) {\n name\n }\n topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) {\n name\n }\n events(umbrellaID: [$umbrellaID], type: $type, topic: $topic) {\n ID\n title\n from\n to\n topic {\n color\n }\n }\n}\n\nquery eventCloseup($id: Int!) {\n events(id: [$id]) {\n ID\n title\n description\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n tutorsAssigned {\n tutors {\n fn\n sn\n mail\n }\n room {\n capacity\n floor\n name\n number\n building {\n name\n street\n number\n city\n zip\n latitude\n longitude\n zoomLevel\n }\n }\n registrations\n }\n }\n}"): (typeof documents)["query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}\n\nquery plannerEvents($umbrellaID: Int!, $type: [String!], $topic: [String!]) {\n umbrellas(id: [$umbrellaID]) {\n title\n }\n typeLabels: labels(kind: EVENT_TYPE, umbrellaID: [$umbrellaID]) {\n name\n }\n topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) {\n name\n }\n events(umbrellaID: [$umbrellaID], type: $type, topic: $topic) {\n ID\n title\n from\n to\n topic {\n color\n }\n }\n}\n\nquery eventCloseup($id: Int!) {\n events(id: [$id]) {\n ID\n title\n description\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n tutorsAssigned {\n tutors {\n fn\n sn\n mail\n }\n room {\n capacity\n floor\n name\n number\n building {\n name\n street\n number\n city\n zip\n latitude\n longitude\n zoomLevel\n }\n }\n registrations\n }\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/lib/gql/generated/graphql.ts b/frontend/lib/gql/generated/graphql.ts index 79b36da..599f6ff 100644 --- a/frontend/lib/gql/generated/graphql.ts +++ b/frontend/lib/gql/generated/graphql.ts @@ -424,9 +424,10 @@ export type QueryBuildingsArgs = { export type QueryEventsArgs = { id?: InputMaybe>; - label?: InputMaybe>; needsTutors?: InputMaybe; onlyFuture?: InputMaybe; + topic?: InputMaybe>; + type?: InputMaybe>; umbrellaID?: InputMaybe>; userMail?: InputMaybe>; }; @@ -562,7 +563,8 @@ export type TutorFormEventsQuery = { __typename?: 'Query', events: Array<{ __typ export type PlannerEventsQueryVariables = Exact<{ umbrellaID: Scalars['Int']['input']; - filter?: InputMaybe | Scalars['String']['input']>; + type?: InputMaybe | Scalars['String']['input']>; + topic?: InputMaybe | Scalars['String']['input']>; }>; @@ -591,7 +593,7 @@ export type UmbrellasQuery = { __typename?: 'Query', umbrellas: Array<{ __typena export const AddStudentApplicationForEventDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"addStudentApplicationForEvent"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"application"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"NewUserToEventApplication"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"addStudentApplicationForEvent"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"application"},"value":{"kind":"Variable","name":{"kind":"Name","value":"application"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fn"}}]}}]}}]} as unknown as DocumentNode; export const AddTutorDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"addTutor"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"firstName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"lastName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"eventsAvailable"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"addTutor"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"tutor"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"fn"},"value":{"kind":"Variable","name":{"kind":"Name","value":"firstName"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"sn"},"value":{"kind":"Variable","name":{"kind":"Name","value":"lastName"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"mail"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}}]}},{"kind":"Argument","name":{"kind":"Name","value":"availability"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"userMail"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"eventID"},"value":{"kind":"Variable","name":{"kind":"Name","value":"eventsAvailable"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fn"}}]}}]}}]} as unknown as DocumentNode; export const TutorFormEventsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"tutorFormEvents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"events"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"needsTutors"},"value":{"kind":"BooleanValue","value":true}},{"kind":"Argument","name":{"kind":"Name","value":"onlyFuture"},"value":{"kind":"BooleanValue","value":true}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"from"}},{"kind":"Field","name":{"kind":"Name","value":"to"}},{"kind":"Field","name":{"kind":"Name","value":"topic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"type"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}}]}}]}}]} as unknown as DocumentNode; -export const PlannerEventsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"plannerEvents"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"umbrellas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"typeLabels"},"name":{"kind":"Name","value":"labels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"kind"},"value":{"kind":"EnumValue","value":"EVENT_TYPE"}},{"kind":"Argument","name":{"kind":"Name","value":"umbrellaID"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"topicLabels"},"name":{"kind":"Name","value":"labels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"kind"},"value":{"kind":"EnumValue","value":"TOPIC"}},{"kind":"Argument","name":{"kind":"Name","value":"umbrellaID"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"events"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"umbrellaID"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"label"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"from"}},{"kind":"Field","name":{"kind":"Name","value":"to"}},{"kind":"Field","name":{"kind":"Name","value":"topic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"color"}}]}}]}}]}}]} as unknown as DocumentNode; +export const PlannerEventsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"plannerEvents"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"type"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"topic"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"umbrellas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"typeLabels"},"name":{"kind":"Name","value":"labels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"kind"},"value":{"kind":"EnumValue","value":"EVENT_TYPE"}},{"kind":"Argument","name":{"kind":"Name","value":"umbrellaID"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"topicLabels"},"name":{"kind":"Name","value":"labels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"kind"},"value":{"kind":"EnumValue","value":"TOPIC"}},{"kind":"Argument","name":{"kind":"Name","value":"umbrellaID"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"events"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"umbrellaID"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"umbrellaID"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"type"},"value":{"kind":"Variable","name":{"kind":"Name","value":"type"}}},{"kind":"Argument","name":{"kind":"Name","value":"topic"},"value":{"kind":"Variable","name":{"kind":"Name","value":"topic"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"from"}},{"kind":"Field","name":{"kind":"Name","value":"to"}},{"kind":"Field","name":{"kind":"Name","value":"topic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"color"}}]}}]}}]}}]} as unknown as DocumentNode; export const EventCloseupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"eventCloseup"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"events"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"id"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"from"}},{"kind":"Field","name":{"kind":"Name","value":"to"}},{"kind":"Field","name":{"kind":"Name","value":"topic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"type"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"tutorsAssigned"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"tutors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fn"}},{"kind":"Field","name":{"kind":"Name","value":"sn"}},{"kind":"Field","name":{"kind":"Name","value":"mail"}}]}},{"kind":"Field","name":{"kind":"Name","value":"room"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"capacity"}},{"kind":"Field","name":{"kind":"Name","value":"floor"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"number"}},{"kind":"Field","name":{"kind":"Name","value":"building"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"street"}},{"kind":"Field","name":{"kind":"Name","value":"number"}},{"kind":"Field","name":{"kind":"Name","value":"city"}},{"kind":"Field","name":{"kind":"Name","value":"zip"}},{"kind":"Field","name":{"kind":"Name","value":"latitude"}},{"kind":"Field","name":{"kind":"Name","value":"longitude"}},{"kind":"Field","name":{"kind":"Name","value":"zoomLevel"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"registrations"}}]}}]}}]}}]} as unknown as DocumentNode; export const RegistrationFormDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"registrationForm"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"eventID"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"forms"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"ListValue","values":[{"kind":"Variable","name":{"kind":"Name","value":"eventID"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"questions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"required"}},{"kind":"Field","name":{"kind":"Name","value":"answers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"points"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const UmbrellasDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"umbrellas"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"umbrellas"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ID"}},{"kind":"Field","name":{"kind":"Name","value":"title"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/frontend/lib/gql/queries/events.graphql b/frontend/lib/gql/queries/events.graphql index b0bbe7c..787ede4 100644 --- a/frontend/lib/gql/queries/events.graphql +++ b/frontend/lib/gql/queries/events.graphql @@ -15,7 +15,7 @@ query tutorFormEvents { } } -query plannerEvents($umbrellaID: Int!, $filter: [String!]) { +query plannerEvents($umbrellaID: Int!, $type: [String!], $topic: [String!]) { umbrellas(id: [$umbrellaID]) { title } @@ -25,7 +25,7 @@ query plannerEvents($umbrellaID: Int!, $filter: [String!]) { topicLabels: labels(kind: TOPIC, umbrellaID: [$umbrellaID]) { name } - events(umbrellaID: [$umbrellaID], label: $filter) { + events(umbrellaID: [$umbrellaID], type: $type, topic: $topic) { ID title from diff --git a/server/README.md b/server/README.md index da54e89..7ac3248 100644 --- a/server/README.md +++ b/server/README.md @@ -1,327 +1,7 @@ +# Welcome to the backend. -# GraphQL Schema Documentation +## api +See [https://fachschaftmathphysinfo.github.io/pepp](https://fachschaftmathphysinfo.github.io/pepp) for documentation on the API. -## Scalars -### `HexColorCode` -Represents a color in hex code format. - -### `timestamptz` -Represents a timestamp with timezone. - -## Enums -### `ScalarType` -- `STRING` -- `INT` -- `FLOAT` -- `BOOLEAN` -- `COLOR` -- `TIMESTAMP` - -### `LabelKind` -- `EVENT_TYPE` -- `TOPIC` - -## Types - -### `User` -Represents a user in the system. -- `fn: String!` - First name. -- `sn: String!` - Surname. -- `mail: String!` - Email. -- `confirmed: Boolean!` - Whether the user is confirmed. -- `eventsRegistered: [Event!]` - Events the user is registered to. -- `eventsAvailable: [Event!]` - Events available to the user. -- `eventsAssigned: [Event!]` - Events assigned to the user. - -### `Label` -Represents a label used for events. -- `name: String!` - Name of the label. -- `color: HexColorCode` - Color of the label. - -### `EventTutorRoomPair` -Represents a pairing of tutors and rooms for an event. -- `tutors: [User!]` - Tutors assigned to the event in the room. -- `room: Room` - Room where the event is held. -- `registrations: Int` - Number of registrations for the event in the room. - -### `Event` -Represents an event. -- `ID: Int!` - ID of the event. -- `tutorsAssigned: [EventTutorRoomPair!]` - Tutors assigned to the event. -- `tutorsAvailable: [User!]` - Tutors available for the event. -- `roomsAvailable: [Room!]` - Rooms available for the event. -- `umbrella: Event` - The umbrella event this event is under. -- `needsTutors: Boolean!` - Whether the event needs tutors. -- `title: String!` - Title of the event. -- `description: String` - Description of the event. -- `topic: Label!` - Topic of the event. -- `type: Label!` - Type of the event. -- `from: timestamptz!` - Start time of the event. -- `to: timestamptz!` - End time of the event. - -### `Room` -Represents a room in a building. -- `name: String` - Name of the room. -- `number: String!` - Room number. -- `capacity: Int` - Capacity of the room. -- `floor: Int` - Floor where the room is located. -- `building: Building!` - The building where the room is located. - -### `Building` -Represents a building. -- `ID: Int!` - ID of the building. -- `name: String!` - Name of the building. -- `street: String!` - Street where the building is located. -- `number: String!` - Number on the street. -- `city: String!` - City where the building is located. -- `zip: Int!` - ZIP code. -- `osm: String!` - OpenStreetMap link. -- `rooms: [Room!]` - Rooms in the building. - -### `Setting` -Represents a system setting. -- `key: String!` - Key of the setting. -- `value: String!` - Value of the setting. -- `type: ScalarType!` - Type of the setting. - -## Queries - -### `events` -Fetches a list of events. -#### Arguments: -- `id: [Int!]` (optional) - List of event IDs to filter events. -- `umbrellaID: [Int!]` (optional) - Filter events by umbrella ID. -- `label: [String!]` (optional) - List of labels to filter events. -- `needsTutors: Boolean` (optional) - Filter events whether it needs tutors. -- `onlyFuture: Boolean` (optional) - Filter to only future events. -- `userMail: [String!]` (optional) - Filter events by user email. -#### Example: -```graphql -query { - events(id: [1], label: ["Math"], needsTutors: true) { - ID - title - description - topic { - name - color - } - tutorsAssigned { - tutors { - fn - sn - } - room { - number - name - capacity - } - registrations - } - needsTutors - tutorsAvailable { - fn - sn - } - roomsAvailable { - name - number - } - from - to - } -} -``` - -### `umbrellas` -Fetches a list of umbrella events. -#### Arguments: -- `id: [Int!]` (optional) - List of umbrella event IDs. -- `onlyFuture: Boolean` (optional) - Filter to only future umbrella events. - -### `buildings` -Fetches a list of buildings. -#### Arguments: -- `id: [Int!]` (optional) - List of building IDs to filter buildings. - -### `rooms` -Fetches a list of rooms. -#### Arguments: -- `number: [String!]` (optional) - List of room numbers to filter rooms. -- `buildingID: Int!` - Building ID to filter rooms. - -### `labels` -Fetches a list of labels. -#### Arguments: -- `name: [String!]` (optional) - List of label names to filter labels. -- `kind: [LabelKind!]` (optional) - List of label kinds to filter labels. - -### `settings` -Fetches a list of system settings. -#### Arguments: -- `key: [String!]` (optional) - List of setting keys to filter. -- `type: [ScalarType!]` (optional) - List of setting types to filter. - -### `users` -Fetches a list of users. -#### Arguments: -- `mail: [String!]` (optional) - List of user emails to filter. - -## Mutations - -**Note:** -- `add` and `update` mutations return the object they have worked on -- `delete` mutation returns the number of objects affected. When deleting references between objects, `delete` returns the outgoing object. - -### `addUser` -Adds a new user. -#### Arguments: -- `user: NewUser!` - Details of the new user. - -### `updateUser` -Updates the information of a user. -#### Arguments: -- `user: NewUser!` - Details of the user. - -### `deleteUser` -Deletes a user. -#### Arguments: -- `mail: [String!]!` - E-Mail adresses of the user(s) to delete. - -### `addTutor` -Combines the creation of a user and setting initial availabilitys. -#### Arguments: -- `tutor: NewUser!` - Details of the new user. -- `availability: UserToEventAvailability` - Pair of tutor mail and event ids. -#### Example: -```graphql -mutation { - addTutor( - tutor: {fn: "Jane", sn: "Doe", mail: "jane.doe@example.de"} - availability: {userMail: "jane.doe@example.de", eventID: [2, 3]} - ) { - fn - confirmed - eventsAvailable { - ID - title - } - } -} -``` - -### `addEvent` -Adds a new event. -#### Arguments: -- `event: NewEvent!` - Details of the new event. - -### `updateEvent` -Updates an event's details. -#### Arguments: -- `id: Int!` - ID of the event. -- `event: NewEvent!` - Updated details of the event. - -### `deleteEvent` -Deletes a list of events. *Note: deleting an umbrella event will delete all events assigned to it* -#### Arguments: -- `id: [Int!]!` - IDs of the event - -### `addBuilding` -Adds a new building. -#### Arguments: -- `building: NewBuilding!` - Details of the new building. - -### `updateBuilding` -Updates a building's details. -#### Arguments: -- `id: Int!` - ID of the building. -- `building: NewBuilding!` - Updated details of the building. - -### `deleteBuilding` -Deletes a list of buildings. *Note: This also deletes all rooms in the buildings* -#### Arguments: -- `id: [Int!]!` - IDs of buildings - -### `addRoom` -Adds a new room. -#### Arguments: -- `room: NewRoom!` - Details of the new room. - -### `updateRoom` -Updates a room's details. -#### Arguments: -- `room: NewRoom!` - Details of the updated room. - -### `deleteRoom` -Deletes a room in a building. -#### Arguments: -- `number: [String!]!` - List of room numbers -- `buildingID: Int!` - ID of building - -### `addLabel` -Adds a new label. -#### Arguments: -- `label: NewLabel!` - Details of the new label. - -### `updateLabel` -Updates a label's details. -#### Arguments: -- `label: NewLabel!` - Details of the updated new label. - -### `deleteLabel` -Deletes a list of labels. -#### Arguments: -- `name: [String!]!` - Names of labels - -### `addEventAssignmentForTutor` -Assigns a user to an event as tutor. -#### Arguments: -- `assignment: EventToUserAssignment!` - Event, User, Room pair -#### Example: -```graphql -mutation { - addEventAssignmentForTutor( - assignment: {eventID: 1, userMail: "john.doe@example.de", roomNumber: "101", buildingID: 1} - ) { - title - roomsAvailable { - number - } - } -} -``` - -### `deleteEventAssignmentForTutor` -Unassigns a user from an event as tutor. -#### Arguments: -- `assignment: EventToUserAssignment!` - Event, User, Room pair - -### `addTutorAvailabilityForEvent` -Marks user as available for an event as tutor. -#### Arguments: -- `availability: NewUserToEventAvailability!` - User, Event pair - -### `deleteTutorAvailabilityForEvent` -Unmarks user as available for an event as tutor. -#### Arguments: -- `availability: NewUserToEventAvailability!` - User, Event pair - -### `addRoomAvailabilityForEvent` -Marks room as available for an event -#### Arguments: -- `availability: RoomToEventAvailability!` - Room, Event pair - -### `deleteRoomAvailabilityForEvent` -Unmarks room as available for an event -#### Arguments: -- `availability: RoomToEventAvailability!` - Room, Event pair - -### `addStudentRegistrationForEvent` -Registers a user to an event. -#### Arguments: -- `registration: UserToEventRegistration!` - User, Event, Room pair - -### `deleteStudentRegistrationForEvent` -Unregisters a user from an event. -#### Arguments: -- `registration: UserToEventRegistration!` - User, Event, Room pair +## database er-diagram +![ER-Diagram](pepp-er.jpg) diff --git a/server/db/README.md b/server/db/README.md deleted file mode 100644 index b7d3266..0000000 --- a/server/db/README.md +++ /dev/null @@ -1 +0,0 @@ -![ER-Diagram](pepp-er-diagram.jpg) diff --git a/server/db/pepp-er-diagram.jpg b/server/db/pepp-er-diagram.jpg deleted file mode 100644 index 0114ec4..0000000 Binary files a/server/db/pepp-er-diagram.jpg and /dev/null differ diff --git a/server/graph/generated.go b/server/graph/generated.go index 280e835..50cc96b 100644 --- a/server/graph/generated.go +++ b/server/graph/generated.go @@ -167,7 +167,7 @@ type ComplexityRoot struct { Query struct { Applications func(childComplexity int, eventID *int, studentMail []string) int Buildings func(childComplexity int, id []int) int - Events func(childComplexity int, id []int, umbrellaID []int, label []string, needsTutors *bool, onlyFuture *bool, userMail []string) int + Events func(childComplexity int, id []int, umbrellaID []int, topic []string, typeArg []string, needsTutors *bool, onlyFuture *bool, userMail []string) int Forms func(childComplexity int, id []int) int Labels func(childComplexity int, name []string, kind []model.LabelKind, umbrellaID []int) int Rooms func(childComplexity int, number []string, buildingID int) int @@ -268,7 +268,7 @@ type MutationResolver interface { DeleteStudentApplicationForEvent(ctx context.Context, mail string, eventID int) (*models.User, error) } type QueryResolver interface { - Events(ctx context.Context, id []int, umbrellaID []int, label []string, needsTutors *bool, onlyFuture *bool, userMail []string) ([]*models.Event, error) + Events(ctx context.Context, id []int, umbrellaID []int, topic []string, typeArg []string, needsTutors *bool, onlyFuture *bool, userMail []string) ([]*models.Event, error) Umbrellas(ctx context.Context, id []int, onlyFuture *bool) ([]*models.Event, error) Buildings(ctx context.Context, id []int) ([]*models.Building, error) Rooms(ctx context.Context, number []string, buildingID int) ([]*models.Room, error) @@ -1056,7 +1056,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Events(childComplexity, args["id"].([]int), args["umbrellaID"].([]int), args["label"].([]string), args["needsTutors"].(*bool), args["onlyFuture"].(*bool), args["userMail"].([]string)), true + return e.complexity.Query.Events(childComplexity, args["id"].([]int), args["umbrellaID"].([]int), args["topic"].([]string), args["type"].([]string), args["needsTutors"].(*bool), args["onlyFuture"].(*bool), args["userMail"].([]string)), true case "Query.forms": if e.complexity.Query.Forms == nil { @@ -2064,41 +2064,50 @@ func (ec *executionContext) field_Query_events_args(ctx context.Context, rawArgs } args["umbrellaID"] = arg1 var arg2 []string - if tmp, ok := rawArgs["label"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("label")) + if tmp, ok := rawArgs["topic"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("topic")) arg2, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp) if err != nil { return nil, err } } - args["label"] = arg2 - var arg3 *bool + args["topic"] = arg2 + var arg3 []string + if tmp, ok := rawArgs["type"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("type")) + arg3, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp) + if err != nil { + return nil, err + } + } + args["type"] = arg3 + var arg4 *bool if tmp, ok := rawArgs["needsTutors"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("needsTutors")) - arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + arg4, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err } } - args["needsTutors"] = arg3 - var arg4 *bool + args["needsTutors"] = arg4 + var arg5 *bool if tmp, ok := rawArgs["onlyFuture"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyFuture")) - arg4, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + arg5, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err } } - args["onlyFuture"] = arg4 - var arg5 []string + args["onlyFuture"] = arg5 + var arg6 []string if tmp, ok := rawArgs["userMail"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userMail")) - arg5, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp) + arg6, err = ec.unmarshalOString2ᚕstringᚄ(ctx, tmp) if err != nil { return nil, err } } - args["userMail"] = arg5 + args["userMail"] = arg6 return args, nil } @@ -6529,7 +6538,7 @@ func (ec *executionContext) _Query_events(ctx context.Context, field graphql.Col }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Events(rctx, fc.Args["id"].([]int), fc.Args["umbrellaID"].([]int), fc.Args["label"].([]string), fc.Args["needsTutors"].(*bool), fc.Args["onlyFuture"].(*bool), fc.Args["userMail"].([]string)) + return ec.resolvers.Query().Events(rctx, fc.Args["id"].([]int), fc.Args["umbrellaID"].([]int), fc.Args["topic"].([]string), fc.Args["type"].([]string), fc.Args["needsTutors"].(*bool), fc.Args["onlyFuture"].(*bool), fc.Args["userMail"].([]string)) }) if err != nil { ec.Error(ctx, err) diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index b8a1994..90caa6b 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -127,7 +127,7 @@ type Application { } type Query { - events(id: [Int!], umbrellaID: [Int!], label: [String!], needsTutors: Boolean, onlyFuture: Boolean, userMail: [String!]): [Event!]! + events(id: [Int!], umbrellaID: [Int!], topic: [String!], type: [String!], needsTutors: Boolean, onlyFuture: Boolean, userMail: [String!]): [Event!]! umbrellas(id: [Int!], onlyFuture: Boolean): [Event!]! buildings(id: [Int!]): [Building!]! rooms(number: [String!], buildingID: Int!): [Room!]! diff --git a/server/graph/schema.resolvers.go b/server/graph/schema.resolvers.go index c602c6c..2fa1a9d 100644 --- a/server/graph/schema.resolvers.go +++ b/server/graph/schema.resolvers.go @@ -227,7 +227,7 @@ func (r *mutationResolver) UpdateEvent(ctx context.Context, id int, event models return nil, err } - updatedEvent, err := r.Query().Events(ctx, []int{id}, nil, nil, nil, nil, nil) + updatedEvent, err := r.Query().Events(ctx, []int{id}, nil, nil, nil, nil, nil, nil) if err != nil { return nil, err } @@ -560,7 +560,7 @@ func (r *mutationResolver) DeleteEventAssignmentForTutor(ctx context.Context, as return nil, err } - event, err := r.Query().Events(ctx, []int{int(assignment.EventID)}, nil, nil, nil, nil, nil) + event, err := r.Query().Events(ctx, []int{int(assignment.EventID)}, nil, nil, nil, nil, nil, nil) if err != nil { return nil, err } @@ -784,7 +784,7 @@ func (r *mutationResolver) DeleteStudentApplicationForEvent(ctx context.Context, } // Events is the resolver for the events field. -func (r *queryResolver) Events(ctx context.Context, id []int, umbrellaID []int, label []string, needsTutors *bool, onlyFuture *bool, userMail []string) ([]*models.Event, error) { +func (r *queryResolver) Events(ctx context.Context, id []int, umbrellaID []int, topic []string, typeArg []string, needsTutors *bool, onlyFuture *bool, userMail []string) ([]*models.Event, error) { var events []*models.Event query := r.DB.NewSelect(). @@ -802,10 +802,12 @@ func (r *queryResolver) Events(ctx context.Context, id []int, umbrellaID []int, query = query.Where(`"e"."umbrella_id" IN (?)`, bun.In(umbrellaID)) } - if label != nil { - query = query. - Where(`"e"."topic_name" IN (?)`, bun.In(label)). - WhereOr(`"e"."type_name" IN (?)`, bun.In(label)) + if typeArg != nil { + query = query.Where(`"e"."type_name" IN (?)`, bun.In(typeArg)) + } + + if topic != nil { + query = query.Where(`"e"."topic_name" IN (?)`, bun.In(topic)) } if needsTutors != nil { diff --git a/server/ical/handler.go b/server/ical/handler.go index d6fee1d..bf8ae4c 100644 --- a/server/ical/handler.go +++ b/server/ical/handler.go @@ -27,22 +27,28 @@ func createCalendar(events []*models.Event) string { func Handler(ctx context.Context, w http.ResponseWriter, r *http.Request, re *graph.Resolver) { var events []*models.Event - var labels []string + var topics []string + var types []string var umbrellaID int - u := r.URL.Query().Get("u") - umbrellaID, err := strconv.Atoi(u) - if u == "" || err != nil { + e := r.URL.Query().Get("e") + umbrellaID, err := strconv.Atoi(e) + if e == "" || err != nil { http.Error(w, "Calendar needs a valid umbrella id", http.StatusBadRequest) return } - l := r.URL.Query().Get("l") - if l != "" { - labels = strings.Split(l, ",") + to := r.URL.Query().Get("to") + if to != "" { + topics = strings.Split(to, ",") } - events, err = re.Query().Events(ctx, nil, []int{umbrellaID}, labels, nil, nil, nil) + ty := r.URL.Query().Get("ty") + if ty != "" { + types = strings.Split(ty, ",") + } + + events, err = re.Query().Events(ctx, nil, []int{umbrellaID}, topics, types, nil, nil, nil) if err != nil || len(events) == 0 { http.Error(w, "No events found", http.StatusBadRequest) return