mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender.git
synced 2025-08-07 04:09:15 +02:00
feat:#26 added semester to fetched groups
This commit is contained in:
461
backend/migrations/1706827339_collections_snapshot.go
Normal file
461
backend/migrations/1706827339_collections_snapshot.go
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
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": "2024-02-01 22:35:50.512Z",
|
||||||
|
"name": "groups",
|
||||||
|
"type": "base",
|
||||||
|
"system": false,
|
||||||
|
"schema": [
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "85msl21p",
|
||||||
|
"name": "university",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "2sii4dtp",
|
||||||
|
"name": "shortcut",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "uiwgo28f",
|
||||||
|
"name": "groupId",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "y0l1lrzs",
|
||||||
|
"name": "course",
|
||||||
|
"type": "text",
|
||||||
|
"required": true,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": 2,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "kr62mhbz",
|
||||||
|
"name": "faculty",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "ya6znpez",
|
||||||
|
"name": "facultyId",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "bdhcrksy",
|
||||||
|
"name": "semester",
|
||||||
|
"type": "text",
|
||||||
|
"required": true,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": 2,
|
||||||
|
"max": 2,
|
||||||
|
"pattern": "ws|ss"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": "2024-02-01 13:34:43.834Z",
|
||||||
|
"name": "feeds",
|
||||||
|
"type": "base",
|
||||||
|
"system": false,
|
||||||
|
"schema": [
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "cowxjfmc",
|
||||||
|
"name": "modules",
|
||||||
|
"type": "json",
|
||||||
|
"required": true,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"maxSize": 2000000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "wmmney8x",
|
||||||
|
"name": "retrieved",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [],
|
||||||
|
"listRule": null,
|
||||||
|
"viewRule": "",
|
||||||
|
"createRule": null,
|
||||||
|
"updateRule": "",
|
||||||
|
"deleteRule": null,
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7her4515qsmrxe8",
|
||||||
|
"created": "2023-09-19 17:31:15.958Z",
|
||||||
|
"updated": "2024-02-01 13:34:43.833Z",
|
||||||
|
"name": "events",
|
||||||
|
"type": "base",
|
||||||
|
"system": false,
|
||||||
|
"schema": [
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "m8ne8e3m",
|
||||||
|
"name": "Day",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "xnsxqp7j",
|
||||||
|
"name": "Week",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "aeuskrjo",
|
||||||
|
"name": "Name",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "klrzqyw0",
|
||||||
|
"name": "EventType",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "5zltexoy",
|
||||||
|
"name": "Prof",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "gy3nvfmx",
|
||||||
|
"name": "Rooms",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "hn7b8dfy",
|
||||||
|
"name": "Notes",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "axskpwm8",
|
||||||
|
"name": "BookedAt",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "vyyefxp7",
|
||||||
|
"name": "course",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "vlbpm9fz",
|
||||||
|
"name": "semester",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "0kahthzr",
|
||||||
|
"name": "uuid",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "6hkjwgb4",
|
||||||
|
"name": "start",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "szbefpjf",
|
||||||
|
"name": "end",
|
||||||
|
"type": "date",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": "",
|
||||||
|
"max": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "nlnnxu7x",
|
||||||
|
"name": "Compulsory",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
"CREATE INDEX ` + "`" + `idx_4vOTAiC` + "`" + ` ON ` + "`" + `events` + "`" + ` (\n ` + "`" + `Name` + "`" + `,\n ` + "`" + `course` + "`" + `,\n ` + "`" + `start` + "`" + `,\n ` + "`" + `end` + "`" + `,\n ` + "`" + `semester` + "`" + `,\n ` + "`" + `EventType` + "`" + `,\n ` + "`" + `Compulsory` + "`" + `\n)"
|
||||||
|
],
|
||||||
|
"listRule": null,
|
||||||
|
"viewRule": null,
|
||||||
|
"createRule": null,
|
||||||
|
"updateRule": null,
|
||||||
|
"deleteRule": null,
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "_pb_users_auth_",
|
||||||
|
"created": "2024-02-01 13:34:43.663Z",
|
||||||
|
"updated": "2024-02-01 13:34:43.833Z",
|
||||||
|
"name": "users",
|
||||||
|
"type": "auth",
|
||||||
|
"system": false,
|
||||||
|
"schema": [
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "users_name",
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "users_avatar",
|
||||||
|
"name": "avatar",
|
||||||
|
"type": "file",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"mimeTypes": [
|
||||||
|
"image/jpeg",
|
||||||
|
"image/png",
|
||||||
|
"image/svg+xml",
|
||||||
|
"image/gif",
|
||||||
|
"image/webp"
|
||||||
|
],
|
||||||
|
"thumbs": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"maxSize": 5242880,
|
||||||
|
"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,
|
||||||
|
"onlyVerified": false,
|
||||||
|
"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
|
||||||
|
})
|
||||||
|
}
|
39
backend/migrations/1706827586_updated_groups.go
Normal file
39
backend/migrations/1706827586_updated_groups.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
|
"github.com/pocketbase/pocketbase/daos"
|
||||||
|
m "github.com/pocketbase/pocketbase/migrations"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
m.Register(func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db)
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("cfq9mqlmd97v8z5")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[
|
||||||
|
"CREATE UNIQUE INDEX `+"`"+`idx_rcaN2Oq`+"`"+` ON `+"`"+`groups`+"`"+` (\n `+"`"+`course`+"`"+`,\n `+"`"+`semester`+"`"+`\n)"
|
||||||
|
]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
}, func(db dbx.Builder) error {
|
||||||
|
dao := daos.New(db)
|
||||||
|
|
||||||
|
collection, err := dao.FindCollectionByNameOrId("cfq9mqlmd97v8z5")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal([]byte(`[
|
||||||
|
"CREATE UNIQUE INDEX `+"`"+`idx_rcaN2Oq`+"`"+` ON `+"`"+`groups`+"`"+` (`+"`"+`course`+"`"+`)"
|
||||||
|
]`), &collection.Indexes)
|
||||||
|
|
||||||
|
return dao.SaveCollection(collection)
|
||||||
|
})
|
||||||
|
}
|
@@ -7,5 +7,6 @@ type SeminarGroup struct {
|
|||||||
Course string
|
Course string
|
||||||
Faculty string
|
Faculty string
|
||||||
FacultyId string
|
FacultyId string
|
||||||
|
Semester string
|
||||||
Events []Event
|
Events []Event
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Studium struct {
|
type Studium struct {
|
||||||
XMLName xml.Name `xml:"studium"`
|
XMLName xml.Name `xml:"studium"`
|
||||||
Fakultaet []Fakultaet `xml:"fakultaet"`
|
Faculty []Faculty `xml:"fakultaet"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fakultaet struct {
|
type Faculty struct {
|
||||||
XMLName xml.Name `xml:"fakultaet"`
|
XMLName xml.Name `xml:"fakultaet"`
|
||||||
Name string `xml:"name,attr"`
|
Name string `xml:"name,attr"`
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
|
@@ -307,6 +307,25 @@ func AddRoutes(app *pocketbase.PocketBase) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||||
|
_, err := e.Router.AddRoute(echo.Route{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/api/courses",
|
||||||
|
Handler: func(c echo.Context) error {
|
||||||
|
semester := c.QueryParam("semester")
|
||||||
|
courses := events.GetAllCoursesForSemester(app, semester)
|
||||||
|
return c.JSON(200, courses)
|
||||||
|
},
|
||||||
|
Middlewares: []echo.MiddlewareFunc{
|
||||||
|
apis.ActivityLogger(app),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||||
_, err := e.Router.AddRoute(echo.Route{
|
_, err := e.Router.AddRoute(echo.Route{
|
||||||
Method: http.MethodDelete,
|
Method: http.MethodDelete,
|
||||||
|
@@ -14,7 +14,7 @@ func SaveGroups(seminarGroup []model.SeminarGroup, collection *models.Collection
|
|||||||
var insertRecords []*models.Record
|
var insertRecords []*models.Record
|
||||||
|
|
||||||
for _, group := range seminarGroup {
|
for _, group := range seminarGroup {
|
||||||
dbGroup, err := FindGroupByCourse(group.Course, app)
|
dbGroup, err := FindGroupByCourseAndSemester(group.Course, group.Semester, app)
|
||||||
|
|
||||||
if dbGroup == nil && err.Error() == "sql: no rows in result set" {
|
if dbGroup == nil && err.Error() == "sql: no rows in result set" {
|
||||||
tobeSavedGroups = append(tobeSavedGroups, group)
|
tobeSavedGroups = append(tobeSavedGroups, group)
|
||||||
@@ -32,6 +32,7 @@ func SaveGroups(seminarGroup []model.SeminarGroup, collection *models.Collection
|
|||||||
record.Set("course", group.Course)
|
record.Set("course", group.Course)
|
||||||
record.Set("faculty", group.Faculty)
|
record.Set("faculty", group.Faculty)
|
||||||
record.Set("facultyId", group.FacultyId)
|
record.Set("facultyId", group.FacultyId)
|
||||||
|
record.Set("semester", group.Semester)
|
||||||
insertRecords = append(insertRecords, record)
|
insertRecords = append(insertRecords, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,13 +51,13 @@ func SaveGroups(seminarGroup []model.SeminarGroup, collection *models.Collection
|
|||||||
return savedRecords, nil
|
return savedRecords, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindGroupByCourse(course string, app *pocketbase.PocketBase) (*model.SeminarGroup, error) {
|
func FindGroupByCourseAndSemester(course string, semester string, app *pocketbase.PocketBase) (*model.SeminarGroup, error) {
|
||||||
var group model.SeminarGroup
|
var group model.SeminarGroup
|
||||||
err := app.Dao().DB().Select("*").From("groups").Where(dbx.NewExp("course = {:course}", dbx.Params{"course": course})).One(&group)
|
err := app.Dao().DB().Select("*").From("groups").Where(dbx.NewExp("course = {:course} AND semester = {:semester}", dbx.Params{"course": course, "semester": semester})).One(&group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &group, err
|
return &group, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllCourses(app *pocketbase.PocketBase) []string {
|
func GetAllCourses(app *pocketbase.PocketBase) []string {
|
||||||
@@ -80,3 +81,26 @@ func GetAllCourses(app *pocketbase.PocketBase) []string {
|
|||||||
|
|
||||||
return courseArray
|
return courseArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) interface{} {
|
||||||
|
|
||||||
|
var courses []struct {
|
||||||
|
CourseShortcut string `db:"course" json:"course"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all rooms from event records in the events collection
|
||||||
|
err := app.Dao().DB().Select("course").From("groups").Where(dbx.NewExp("semester = {:semester}", dbx.Params{"semester": semester})).All(&courses)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Error while getting groups from database: ", err)
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var courseArray []string
|
||||||
|
|
||||||
|
for _, course := range courses {
|
||||||
|
courseArray = append(courseArray, course.CourseShortcut)
|
||||||
|
}
|
||||||
|
|
||||||
|
return courseArray
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -8,3 +8,7 @@ import (
|
|||||||
func GetAllCourses(app *pocketbase.PocketBase) []string {
|
func GetAllCourses(app *pocketbase.PocketBase) []string {
|
||||||
return db.GetAllCourses(app)
|
return db.GetAllCourses(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) interface{} {
|
||||||
|
return db.GetAllCoursesForSemester(app, semester)
|
||||||
|
}
|
||||||
|
@@ -57,8 +57,8 @@ func FetchSeminarGroups(app *pocketbase.PocketBase) ([]*models.Record, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
groups = parseSeminarGroups(resultSummer)
|
groups = parseSeminarGroups(resultSummer, "ss")
|
||||||
groups = append(groups, parseSeminarGroups(resultWinter)...)
|
groups = append(groups, parseSeminarGroups(resultWinter, "ws")...)
|
||||||
|
|
||||||
// filter duplicates
|
// filter duplicates
|
||||||
groups = removeDuplicates(groups)
|
groups = removeDuplicates(groups)
|
||||||
@@ -91,14 +91,14 @@ func removeDuplicates(groups []model.SeminarGroup) []model.SeminarGroup {
|
|||||||
|
|
||||||
func contains(groups []model.SeminarGroup, group model.SeminarGroup) bool {
|
func contains(groups []model.SeminarGroup, group model.SeminarGroup) bool {
|
||||||
for _, a := range groups {
|
for _, a := range groups {
|
||||||
if a.Course == group.Course {
|
if (a.Course == group.Course) && (a.Semester == group.Semester) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSeminarGroups(result string) []model.SeminarGroup {
|
func parseSeminarGroups(result string, semester string) []model.SeminarGroup {
|
||||||
|
|
||||||
var studium model.Studium
|
var studium model.Studium
|
||||||
err := xml.Unmarshal([]byte(result), &studium)
|
err := xml.Unmarshal([]byte(result), &studium)
|
||||||
@@ -107,16 +107,17 @@ func parseSeminarGroups(result string) []model.SeminarGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var seminarGroups []model.SeminarGroup
|
var seminarGroups []model.SeminarGroup
|
||||||
for _, Fakultaet := range studium.Fakultaet {
|
for _, faculty := range studium.Faculty {
|
||||||
for _, Studiengang := range Fakultaet.Studiengang {
|
for _, Studiengang := range faculty.Studiengang {
|
||||||
for _, Studienrichtung := range Studiengang.Semgrp {
|
for _, Studienrichtung := range Studiengang.Semgrp {
|
||||||
seminarGroup := model.SeminarGroup{
|
seminarGroup := model.SeminarGroup{
|
||||||
University: "HTWK-Leipzig",
|
University: "HTWK-Leipzig",
|
||||||
GroupShortcut: Studiengang.Name,
|
GroupShortcut: Studiengang.Name,
|
||||||
GroupId: Studiengang.ID,
|
GroupId: Studiengang.ID,
|
||||||
Course: Studienrichtung.Name,
|
Course: Studienrichtung.Name,
|
||||||
Faculty: Fakultaet.Name,
|
Faculty: faculty.Name,
|
||||||
FacultyId: Fakultaet.ID,
|
FacultyId: faculty.ID,
|
||||||
|
Semester: semester,
|
||||||
}
|
}
|
||||||
seminarGroups = append(seminarGroups, seminarGroup)
|
seminarGroups = append(seminarGroups, seminarGroup)
|
||||||
}
|
}
|
||||||
|
75
backend/service/fetch/v1/fetchSeminarGroupService_test.go
Normal file
75
backend/service/fetch/v1/fetchSeminarGroupService_test.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"htwkalender/model"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_contains(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
groups []model.SeminarGroup
|
||||||
|
group model.SeminarGroup
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should return true if group is in groups",
|
||||||
|
args: args{
|
||||||
|
groups: []model.SeminarGroup{
|
||||||
|
{
|
||||||
|
Course: "test",
|
||||||
|
Semester: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
group: model.SeminarGroup{
|
||||||
|
Course: "test",
|
||||||
|
Semester: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should return false if group is not in groups",
|
||||||
|
args: args{
|
||||||
|
groups: []model.SeminarGroup{
|
||||||
|
{
|
||||||
|
Course: "test",
|
||||||
|
Semester: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
group: model.SeminarGroup{
|
||||||
|
Course: "test",
|
||||||
|
Semester: "test2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should return false if group is not in courses",
|
||||||
|
args: args{
|
||||||
|
groups: []model.SeminarGroup{
|
||||||
|
{
|
||||||
|
Course: "test3",
|
||||||
|
Semester: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
group: model.SeminarGroup{
|
||||||
|
Course: "test",
|
||||||
|
Semester: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := contains(tt.args.groups, tt.args.group); got != tt.want {
|
||||||
|
t.Errorf("contains() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
4677
frontend/package-lock.json
generated
Normal file
4677
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,24 @@ export async function fetchCourse(): Promise<string[]> {
|
|||||||
return courses;
|
return courses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchCourseBySemester(semester: string): Promise<string[]> {
|
||||||
|
const courses: string[] = [];
|
||||||
|
await fetch("/api/courses?semester=" + semester)
|
||||||
|
.then((response) => {
|
||||||
|
//check if response type is json
|
||||||
|
const contentType = response.headers.get("content-type");
|
||||||
|
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||||
|
return response.json();
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((coursesResponse) => {
|
||||||
|
coursesResponse.forEach((course: string) => courses.push(course));
|
||||||
|
});
|
||||||
|
return courses;
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchModulesByCourseAndSemester(
|
export async function fetchModulesByCourseAndSemester(
|
||||||
course: string,
|
course: string,
|
||||||
semester: string,
|
semester: string,
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ComputedRef, Ref, ref, watch } from "vue";
|
import { computed, ComputedRef, Ref, ref, watch } from "vue";
|
||||||
import {
|
import { fetchCourseBySemester,
|
||||||
fetchCourse,
|
fetchModulesByCourseAndSemester
|
||||||
fetchModulesByCourseAndSemester,
|
|
||||||
} from "../api/fetchCourse";
|
} from "../api/fetchCourse";
|
||||||
import DynamicPage from "./DynamicPage.vue";
|
import DynamicPage from "./DynamicPage.vue";
|
||||||
import ModuleSelection from "../components/ModuleSelection.vue";
|
import ModuleSelection from "../components/ModuleSelection.vue";
|
||||||
@@ -11,15 +10,28 @@ import { useI18n } from "vue-i18n";
|
|||||||
import moduleStore from "../store/moduleStore";
|
import moduleStore from "../store/moduleStore";
|
||||||
import router from "../router";
|
import router from "../router";
|
||||||
|
|
||||||
|
async function getModules() {
|
||||||
|
modules.value = await fetchModulesByCourseAndSemester(
|
||||||
|
selectedCourse.value.name,
|
||||||
|
selectedSemester.value.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCourses() {
|
||||||
|
courses.value = await fetchCourseBySemester(selectedSemester.value.value).then((data) => {
|
||||||
|
return data.map((course) => {
|
||||||
|
return { name: course };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const store = moduleStore();
|
const store = moduleStore();
|
||||||
const { t } = useI18n({ useScope: "global" });
|
const { t } = useI18n({ useScope: "global" });
|
||||||
|
|
||||||
const courses = async () => {
|
|
||||||
return await fetchCourse();
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectedCourse: Ref<{ name: string }> = ref({ name: "" });
|
const selectedCourse: Ref<{ name: string }> = ref({ name: "" });
|
||||||
const countries: Ref<{ name: string }[]> = ref([]);
|
const courses: Ref<{ name: string; }[]> = ref([]);
|
||||||
|
const modules: Ref<Module[]> = ref([]);
|
||||||
|
|
||||||
const semesters: ComputedRef<{ name: string; value: string }[]> = computed(
|
const semesters: ComputedRef<{ name: string; value: string }[]> = computed(
|
||||||
() => [
|
() => [
|
||||||
{ name: t("courseSelection.winterSemester"), value: "ws" },
|
{ name: t("courseSelection.winterSemester"), value: "ws" },
|
||||||
@@ -39,21 +51,10 @@ watch(
|
|||||||
newValue[selectedSemester.value.value === "ws" ? 0 : 1]),
|
newValue[selectedSemester.value.value === "ws" ? 0 : 1]),
|
||||||
);
|
);
|
||||||
|
|
||||||
courses().then(
|
// init the courses dropdown with the first semester that is default selected
|
||||||
(data) =>
|
getCourses();
|
||||||
(countries.value = data.map((course) => {
|
|
||||||
return { name: course };
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
const modules: Ref<Module[]> = ref([]);
|
|
||||||
|
|
||||||
async function getModules() {
|
|
||||||
modules.value = await fetchModulesByCourseAndSemester(
|
|
||||||
selectedCourse.value.name,
|
|
||||||
selectedSemester.value.value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -70,9 +71,17 @@ async function getModules() {
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #selection="{ flexSpecs }">
|
<template #selection="{ flexSpecs }">
|
||||||
|
<Dropdown
|
||||||
|
v-model="selectedSemester"
|
||||||
|
:options="semesters"
|
||||||
|
:class="flexSpecs"
|
||||||
|
option-label="name"
|
||||||
|
:placeholder="$t('courseSelection.semesterDropDown')"
|
||||||
|
@change="getCourses()"
|
||||||
|
></Dropdown>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
v-model="selectedCourse"
|
v-model="selectedCourse"
|
||||||
:options="countries"
|
:options="courses"
|
||||||
:class="flexSpecs"
|
:class="flexSpecs"
|
||||||
filter
|
filter
|
||||||
option-label="name"
|
option-label="name"
|
||||||
@@ -81,14 +90,6 @@ async function getModules() {
|
|||||||
:auto-filter-focus="true"
|
:auto-filter-focus="true"
|
||||||
@change="getModules()"
|
@change="getModules()"
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
<Dropdown
|
|
||||||
v-model="selectedSemester"
|
|
||||||
:options="semesters"
|
|
||||||
:class="flexSpecs"
|
|
||||||
option-label="name"
|
|
||||||
:placeholder="$t('courseSelection.semesterDropDown')"
|
|
||||||
@change="getModules()"
|
|
||||||
></Dropdown>
|
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<ModuleSelection
|
<ModuleSelection
|
||||||
|
Reference in New Issue
Block a user