diff --git a/.idea/swagger-settings.xml b/.idea/swagger-settings.xml new file mode 100644 index 0000000..01d844c --- /dev/null +++ b/.idea/swagger-settings.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/backend/migrations/1697532023_collections_snapshot.go b/backend/migrations/1697532023_collections_snapshot.go new file mode 100644 index 0000000..7edc1f3 --- /dev/null +++ b/backend/migrations/1697532023_collections_snapshot.go @@ -0,0 +1,384 @@ +package migrations + +import ( + "encoding/json" + + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/daos" + m "github.com/pocketbase/pocketbase/migrations" + "github.com/pocketbase/pocketbase/models" +) + +func init() { + m.Register(func(db dbx.Builder) error { + jsonData := `[ + { + "id": "cfq9mqlmd97v8z5", + "created": "2023-09-19 17:31:15.957Z", + "updated": "2023-09-19 17:31:15.957Z", + "name": "groups", + "type": "base", + "system": false, + "schema": [ + { + "system": false, + "id": "85msl21p", + "name": "university", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "2sii4dtp", + "name": "shortcut", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "uiwgo28f", + "name": "groupId", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "y0l1lrzs", + "name": "course", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "kr62mhbz", + "name": "faculty", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "ya6znpez", + "name": "facultyId", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + } + ], + "indexes": [ + "CREATE UNIQUE INDEX ` + "`" + `idx_rcaN2Oq` + "`" + ` ON ` + "`" + `groups` + "`" + ` (` + "`" + `course` + "`" + `)" + ], + "listRule": null, + "viewRule": null, + "createRule": null, + "updateRule": null, + "deleteRule": null, + "options": {} + }, + { + "id": "d65h4wh7zk13gxp", + "created": "2023-09-19 17:31:15.957Z", + "updated": "2023-10-17 08:37:17.943Z", + "name": "feeds", + "type": "base", + "system": false, + "schema": [ + { + "system": false, + "id": "cowxjfmc", + "name": "modules", + "type": "json", + "required": true, + "unique": false, + "options": {} + } + ], + "indexes": [], + "listRule": null, + "viewRule": "", + "createRule": null, + "updateRule": null, + "deleteRule": null, + "options": {} + }, + { + "id": "7her4515qsmrxe8", + "created": "2023-09-19 17:31:15.958Z", + "updated": "2023-09-19 17:31:15.958Z", + "name": "events", + "type": "base", + "system": false, + "schema": [ + { + "system": false, + "id": "m8ne8e3m", + "name": "Day", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "xnsxqp7j", + "name": "Week", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "7vsr9h6p", + "name": "Start", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "wwpokofe", + "name": "End", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "aeuskrjo", + "name": "Name", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "klrzqyw0", + "name": "EventType", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "5zltexoy", + "name": "Prof", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "gy3nvfmx", + "name": "Rooms", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "hn7b8dfy", + "name": "Notes", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "axskpwm8", + "name": "BookedAt", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "vyyefxp7", + "name": "course", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "vlbpm9fz", + "name": "semester", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + } + ], + "indexes": [ + "CREATE UNIQUE INDEX ` + "`" + `idx_orp1NWL` + "`" + ` ON ` + "`" + `events` + "`" + ` (\n ` + "`" + `Day` + "`" + `,\n ` + "`" + `Week` + "`" + `,\n ` + "`" + `Start` + "`" + `,\n ` + "`" + `End` + "`" + `,\n ` + "`" + `Name` + "`" + `,\n ` + "`" + `course` + "`" + `,\n ` + "`" + `Prof` + "`" + `,\n ` + "`" + `Rooms` + "`" + `,\n ` + "`" + `EventType` + "`" + `\n)" + ], + "listRule": null, + "viewRule": null, + "createRule": null, + "updateRule": null, + "deleteRule": null, + "options": {} + }, + { + "id": "_pb_users_auth_", + "created": "2023-10-08 16:32:34.131Z", + "updated": "2023-10-08 16:32:34.315Z", + "name": "users", + "type": "auth", + "system": false, + "schema": [ + { + "system": false, + "id": "users_name", + "name": "name", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + }, + { + "system": false, + "id": "users_avatar", + "name": "avatar", + "type": "file", + "required": false, + "unique": false, + "options": { + "maxSelect": 1, + "maxSize": 5242880, + "mimeTypes": [ + "image/jpeg", + "image/png", + "image/svg+xml", + "image/gif", + "image/webp" + ], + "thumbs": null, + "protected": false + } + } + ], + "indexes": [], + "listRule": "id = @request.auth.id", + "viewRule": "id = @request.auth.id", + "createRule": "", + "updateRule": "id = @request.auth.id", + "deleteRule": "id = @request.auth.id", + "options": { + "allowEmailAuth": true, + "allowOAuth2Auth": true, + "allowUsernameAuth": true, + "exceptEmailDomains": null, + "manageRule": null, + "minPasswordLength": 8, + "onlyEmailDomains": null, + "requireEmail": false + } + } + ]` + + collections := []*models.Collection{} + if err := json.Unmarshal([]byte(jsonData), &collections); err != nil { + return err + } + + return daos.New(db).ImportCollections(collections, true, nil) + }, func(db dbx.Builder) error { + return nil + }) +} diff --git a/backend/openapi.yml b/backend/openapi.yml index 1220dcd..d1aee05 100644 --- a/backend/openapi.yml +++ b/backend/openapi.yml @@ -1,7 +1,12 @@ openapi: 3.0.0 info: - title: Your API - version: 1.0.0 + title: HTWKalendar API + version: 1.0.1 +servers: + - url: https://cal.ekresse.de + description: Production server + - url: http://localhost:8090 + description: Local server paths: /api/fetchPlans: get: @@ -29,7 +34,20 @@ paths: description: Successful response /api/feed: get: - summary: Get iCal Feed + summary: Get iCal Feed for calendar + responses: + '200': + description: Successful response + /api/collections/feeds/records/{id}: + get: + summary: Get Modules selected for iCal feed + parameters: + - name: id + in: path + description: calendar token + required: true + schema: + type: string responses: '200': description: Successful response diff --git a/frontend/src/api/fetchModule.ts b/frontend/src/api/fetchModule.ts index 472046b..712dad1 100644 --- a/frontend/src/api/fetchModule.ts +++ b/frontend/src/api/fetchModule.ts @@ -1,4 +1,4 @@ -import { Module } from "../model/module.ts"; +import { Module } from "../model/module"; export async function fetchModule( name: string): Promise { const request = new Request("/api/module", { diff --git a/frontend/src/api/loadCalendar.ts b/frontend/src/api/loadCalendar.ts new file mode 100644 index 0000000..d780b12 --- /dev/null +++ b/frontend/src/api/loadCalendar.ts @@ -0,0 +1,16 @@ +import { Module } from "../model/module"; +import { Calendar } from "../model/calendar"; + +export async function getCalender( token: string): Promise { + const request = new Request("/api/collections/feeds/records/" + token, { + method: "GET", + }); + + return await fetch(request) + .then((response) => { + return response.json(); + }) + .then( + (calendarResponse: Calendar) => calendarResponse.modules + ); +} \ No newline at end of file diff --git a/frontend/src/components/MenuBar.vue b/frontend/src/components/MenuBar.vue index 17af22c..c8cf9e5 100644 --- a/frontend/src/components/MenuBar.vue +++ b/frontend/src/components/MenuBar.vue @@ -7,6 +7,11 @@ const items = ref([ icon: "pi pi-fw pi-plus", url: "/", }, + { + label: "Edit Calendar", + icon: "pi pi-fw pi-pencil", + url: "/edit", + }, { label: "FAQ", icon: "pi pi-fw pi-book", diff --git a/frontend/src/components/editCalendar/loadCalender.vue b/frontend/src/components/editCalendar/loadCalender.vue new file mode 100644 index 0000000..84a8508 --- /dev/null +++ b/frontend/src/components/editCalendar/loadCalender.vue @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/model/calendar.ts b/frontend/src/model/calendar.ts new file mode 100644 index 0000000..b73d3c7 --- /dev/null +++ b/frontend/src/model/calendar.ts @@ -0,0 +1,10 @@ +import { Module } from "./module"; + +export type Calendar = { + collectionId: string; + collectionName: string; + created: string; + id: string; + modules: Module[]; + updated: string; +} \ No newline at end of file diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 9a88635..ac75df0 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -6,6 +6,7 @@ import CalendarLink from "../components/CalendarLink.vue"; import Imprint from "../components/Imprint.vue"; import PrivacyPolicy from "../components/PrivacyPolicy.vue"; import RenameModules from "../components/RenameModules.vue"; +import EditCalendarView from "../view/editCalendarView.vue"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -30,6 +31,11 @@ const router = createRouter({ name: "calendar-link", component: CalendarLink, }, + { + path: "/edit", + name: "edit", + component: EditCalendarView, + }, { path: "/privacy-policy", name: "privacy-policy", diff --git a/frontend/src/store/moduleStore.ts b/frontend/src/store/moduleStore.ts index bf9d32b..ccb06e6 100644 --- a/frontend/src/store/moduleStore.ts +++ b/frontend/src/store/moduleStore.ts @@ -12,6 +12,9 @@ const moduleStore = defineStore("moduleStore", { removeModule(module: Module) { this.modules.splice(this.modules.indexOf(module), 1); }, + removeAllModules() { + this.modules = []; + } }, }); diff --git a/frontend/src/view/editCalendarView.vue b/frontend/src/view/editCalendarView.vue new file mode 100644 index 0000000..1d02d97 --- /dev/null +++ b/frontend/src/view/editCalendarView.vue @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file