Course Manager är en webbapplikation för att hantera kurser, kurssektioner, grupper och deltagare. Systemet låter dig organisera utbildningsinnehåll med stöd för filuppladdning och förhandsgranskning av dokument direkt i webbläsaren.
Funktioner: Skapa, redigera och ta bort kurser, kurssektioner, grupper och deltagare. Tilldela deltagare till kurser, kurssektioner och grupper via many-to-many-relationer. Ladda upp filer (bilder, PDF, text) kopplade till valfri entitet. Förhandsgranska textfiler, bilder, ljud och PDF direkt i webbläsaren. Redigera textfiler inline. Ladda ner alla filer för en entitet som ZIP. Sök bland kurser och deltagare. Mörkt och ljust läge med automatisk anpassning. Responsiv design anpassad för både desktop och mobil.
Struktur: Varje kurs innehåller kurssektioner. Varje kurssektion innehåller grupper. Deltagare kan kopplas till kurser, kurssektioner och grupper. Filer kan laddas upp på alla nivåer.
Teknik: Backend är byggd med ASP.NET Core, Entity Framework Core och Azure SQL Database. Filhantering sker via Azure Blob Storage eller lokal fillagring (i Utvecklingsmiljö). Applikationen körs i Azure App Service. Frontend är byggd med Angular (v21) och TypeScript med SCSS för styling.
Projektet består av två delar:
- CourseManager.Server: Webbservern som hanterar API, databas och filhantering
- CourseManager.Client: Frontend byggd med Angular
Systemet använder följande Azure-tjänster:
- Azure App Service → Hosting av backend API och frontend
- Azure SQL Database → Databas för kurser, sektioner, grupper, deltagare och filmetadata
- Azure Blob Storage → Lagring av uppladdade filer
- REST API för kurser, kurssektioner, grupper, deltagare och relationer
- Filhantering via Azure Blob Storage eller lokal fillagring (i Utvecklingsmiljö)
- Azure SQL Database via Entity Framework Core
- ZIP-nedladdning av alla filer för en entitet (inkl. nested)
- CORS-konfiguration för frontend
- Skrivet i Angular med TypeScript
- SCSS för styling
- Responsiv design med hamburgermeny för mobil
- Mörkt/ljust läge med
prefers-color-scheme-detektion - Inline textredigering
- Filförhandsgranskning (text, bild, ljud, PDF)
- Bekräftelsedialoger för destruktiva operationer
- Snackbar-meddelanden med auto-dismiss
- Metadata lagras i Azure SQL Database (eller LocalDB lokalt i utvecklingsläge)
- Filer lagras i Azure Blob Storage eller lokalt filsystem (
uploads/i utvecklingsläge) - Many-to-many-relationer mellan entiteter och filer via join-tabeller
- Skapa kurs med namn och beskrivning
- Visa alla kurser med sökfunktion
- Redigera kursinformation
- Ta bort kurs med bekräftelsedialog
- Visa kursdetaljer med kurssektioner och deltagare
- Skapa kurssektion kopplad till en kurs
- Visa kurssektion med dess grupper och deltagare
- Redigera och ta bort kurssektioner
- Skapa grupp kopplad till en kurssektion
- Visa gruppdetaljer med deltagare
- Redigera och ta bort grupp
- Skapa deltagare med fullständigt namn
- Lista alla deltagare med sökfunktion
- Visa deltagardetaljer med kopplade kurser, sektioner, grupper och filer
- Tilldela deltagare till kurser, kurssektioner och grupper
- Ta bort deltagare
- Ladda upp filer (PNG, JPG, PDF, TXT) till kurs, kurssektion, grupp eller deltagare
- Max filstorlek: 50 MB
- Förhandsgranska textfiler med inline-redigering
- Bildvisning för uppladdade bilder
- PDF-visning via webbläsaren
- Ladda ner enskild fil
- Ladda ner alla filer för en entitet som ZIP (inklusive nested filer)
- Content-modul med översiktsvy som grupperar filer efter källa
- Ta bort filer med bekräftelsedialog
- Top-nav med logotyp, navigationslänkar och tema-toggle
- Brödsmulestig (breadcrumb) för navigering
- Snackbar för framgångs- och felmeddelanden
- Bekräftelsedialoger (Yes/No) för destruktiva operationer
- Responsiv hamburgermeny för mobil
- Mörkt/ljust läge — toggle-knapp och auto-detection via
prefers-color-scheme - Footer med copyright
GET /api/course— Lista alla kurserGET /api/course/{courseId}— Hämta en kursPOST /api/course— Skapa kursPUT /api/course/{courseId}— Uppdatera kursDELETE /api/course/{courseId}— Ta bort kurs
GET /api/course-section— Lista alla kurssektionerGET /api/course-section/{sectionId}— Hämta en kurssektionPOST /api/course-section— Skapa kurssektionPUT /api/course-section/{sectionId}— Uppdatera kurssektionDELETE /api/course-section/{sectionId}— Ta bort kurssektion
GET /api/group— Lista alla grupperGET /api/group/{groupId}— Hämta en gruppPOST /api/group— Skapa gruppPUT /api/group/{groupId}— Uppdatera gruppDELETE /api/group/{groupId}— Ta bort grupp
GET /api/person— Lista alla deltagareGET /api/person/{personId}— Hämta en deltagarePOST /api/person— Skapa deltagarePUT /api/person/{personId}— Uppdatera deltagareDELETE /api/person/{personId}— Ta bort deltagare
POST /api/relations/course— Tilldela deltagare till kursDELETE /api/relations/course/{courseId}/{personId}— Ta bort deltagare från kursPOST /api/relations/course-section— Tilldela deltagare till kurssektionDELETE /api/relations/course-section/{sectionId}/{personId}— Ta bort deltagare från kurssektionPOST /api/relations/group— Tilldela deltagare till gruppDELETE /api/relations/group/{groupId}/{personId}— Ta bort deltagare från grupp
GET /api/files/{fileAssetId}— Hämta filmetadataPOST /api/files/upload/{entityType}/{entityId}— Ladda upp filDELETE /api/files/{fileAssetId}— Ta bort filGET /api/files/{fileAssetId}/content— Läs filinnehåll (text)PUT /api/files/{fileAssetId}/content— Uppdatera filinnehåll (text)GET /api/files/{fileAssetId}/download— Ladda ner filGET /api/files/{fileAssetId}/inline— Visa fil inlineGET /api/files/course/{courseId}— Lista filer för kursGET /api/files/course-section/{sectionId}— Lista filer för kurssektionGET /api/files/group/{groupId}— Lista filer för gruppGET /api/files/person/{personId}— Lista filer för deltagareGET /api/files/download/{entityType}/{entityId}— Ladda ner alla filer som ZIPDELETE /api/files/course/{courseId}/{fileAssetId}— Ta bort fil från kursDELETE /api/files/course-section/{sectionId}/{fileAssetId}— Ta bort fil från kurssektionDELETE /api/files/group/{groupId}/{fileAssetId}— Ta bort fil från gruppDELETE /api/files/person/{personId}/{fileAssetId}— Ta bort fil från deltagare
Course-Manager/
├─ .gitignore
├─ package.json
├─ package-lock.json
├─ README.md
├─ CourseManager.Client/
│ ├─ angular.json
│ ├─ package.json
│ ├─ tsconfig.json
│ ├─ tsconfig.app.json
│ ├─ tsconfig.spec.json
│ ├─ .editorconfig
│ ├─ .prettierrc
│ ├─ public/
│ └─ src/
│ ├─ index.html
│ ├─ main.ts
│ ├─ styles.scss
│ ├─ environments/
│ │ ├─ environment.ts
│ │ └─ environment.prod.ts
│ └─ app/
│ ├─ app.ts
│ ├─ app.html
│ ├─ app.routes.ts
│ ├─ app.config.ts
│ ├─ theme.service.ts
│ ├─ groups.service.ts
│ ├─ home/
│ ├─ layout/
│ ├─ all-courses/
│ ├─ course-view/
│ ├─ course-section-view/
│ ├─ group-view/
│ ├─ persons/
│ ├─ participant-detail/
│ ├─ create-course/
│ ├─ create-course-section/
│ ├─ create-group/
│ ├─ edit-group/
│ ├─ person-creator/
│ ├─ content-module/
│ │ └─ file-preview/
│ ├─ confirm-dialog/
│ ├─ modal-window/
│ ├─ shared/
│ │ └─ snackbar/
│ ├─ api-services/
│ └─ not-found/
└─ CourseManager.Server/
├─ Program.cs
├─ appsettings.json
├─ appsettings.Development.json
├─ CourseManager.Server.csproj
├─ Deploy.ps1
├─ Data/
│ └─ AppDbContext.cs
├─ DTOs/
├─ Endpoints/
│ ├─ CourseEndpoints.cs
│ ├─ CourseSectionEndpoints.cs
│ ├─ GroupEndpoints.cs
│ ├─ PersonEndpoints.cs
│ ├─ RelationsEndpoints.cs
│ └─ FileEndpoints.cs
├─ Migrations/
├─ Models/
├─ Repositories/
├─ Services/
│ └─ BlobService.cs
├─ Properties/
└─ wwwroot/
- .NET SDK 8
- Node.js och npm
- Angular CLI (installeras via npm)
- SQL Server LocalDB (eller Azure SQL)
Från rot-mappen, kör följande för att starta både backend och frontend samtidigt:
npm install
npm run devBackend startar på http://localhost:5053 (eller konfigurerad port).
Frontend startar på http://localhost:4200 och proxyar API-anrop till backend.
cd CourseManager.Server
dotnet runcd CourseManager.Client
npm install
npm startAutomatisk deploy till Azure med PowerShell:
.\CourseManager.Server\Deploy.ps1Servern använder appsettings.json för grundkonfiguration och appsettings.Development.json för lokal utveckling.
Connection strings konfigureras via miljövariabler eller appsettings.json:
ConnectionStrings:AzureSqlConnection— Azure SQL Database-anslutningAzureStorage:ConnectionString— Azure Blob Storage-anslutningAzureStorage:ContainerName— Blob container-namn
Lokalt används LocalDB automatiskt om ingen Azure-connection string finns. Filuppladdning sker till lokal uploads/-mapp om Azure Blob Storage inte är konfigurerat.
- CORS är konfigurerat för specifika origins (Azure-domän och localhost)
- Filuppladdning validerar filtyp (PNG, JPG, PDF, TXT) och filändelse
- Max filstorlek: 50 MB
- Skydd mot ogiltiga filnamn och path traversal
- Entity Framework migrationer körs automatiskt vid startup
Course Manager is a web application for managing courses, course sections, groups, and participants. It allows you to organize educational content with support for file uploads and document previews directly in the browser.
Courses contain course sections, which in turn contain groups. Participants can be assigned to courses, course sections, and groups through many-to-many relationships. Files can be uploaded at any level.
The backend is built with ASP.NET Core and Entity Framework Core, using Azure SQL Database for metadata and Azure Blob Storage for file storage. The frontend is built with Angular and TypeScript, featuring a responsive design with dark/light theme support.
- Alaa Alsous
- Johan Norgren
- Nils Öhrn Skäre
- Alexander Ljungqvist
- Sebastian Johansson
- Nour Amairy
- Alexander Lindgren



