Skip to content

Commit 8a4ca3b

Browse files
committed
Merge branch 'v4-feat/settings' into v4-dev
2 parents 75b7a70 + 22e58aa commit 8a4ca3b

30 files changed

Lines changed: 999 additions & 78 deletions

src/app/app-routing.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ActivityDescriptionPageComponent } from './pages/activity-description/a
99
import { UsageComponent } from './pages/usage/usage.component';
1010
import { TeamsComponent } from './pages/teams/teams.component';
1111
import { RoadmapComponent } from './pages/roadmap/roadmap.component';
12+
import { SettingsComponent } from './pages/settings/settings.component';
1213

1314
const routes: Routes = [
1415
{ path: '', component: CircularHeatmapComponent },
@@ -22,6 +23,7 @@ const routes: Routes = [
2223
{ path: 'about', component: AboutUsComponent },
2324
{ path: 'userday', component: UserdayComponent },
2425
{ path: 'roadmap', component: RoadmapComponent },
26+
{ path: 'settings', component: SettingsComponent },
2527
];
2628

2729
@NgModule({

src/app/app.module.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
22
import { BrowserModule } from '@angular/platform-browser';
3-
import { ReactiveFormsModule } from '@angular/forms';
3+
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
44

55
import { AppRoutingModule } from './app-routing.module';
66
import { AppComponent } from './app.component';
@@ -13,6 +13,7 @@ import { TeamsComponent } from './pages/teams/teams.component';
1313
import { UsageComponent } from './pages/usage/usage.component';
1414
import { UserdayComponent } from './pages/userday/userday.component';
1515
import { RoadmapComponent } from './pages/roadmap/roadmap.component';
16+
import { SettingsComponent } from './pages/settings/settings.component';
1617
import { AboutUsComponent } from './pages/about-us/about-us.component';
1718
import { LogoComponent } from './component/logo/logo.component';
1819
import { SidenavButtonsComponent } from './component/sidenav-buttons/sidenav-buttons.component';
@@ -52,6 +53,7 @@ import { TeamsGroupsEditorModule } from './component/teams-groups-editor/teams-g
5253
ModalMessageComponent,
5354
ProgressSliderComponent,
5455
KpiComponent,
56+
SettingsComponent,
5557
],
5658
imports: [
5759
BrowserModule,
@@ -60,6 +62,7 @@ import { TeamsGroupsEditorModule } from './component/teams-groups-editor/teams-g
6062
MaterialModule,
6163
MatDialogModule,
6264
ReactiveFormsModule,
65+
FormsModule,
6366
HttpClientModule,
6467
TeamsGroupsEditorModule,
6568
],

src/app/component/activity-description/activity-description.component.html

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ <h1>
2020

2121
<div class="activity-subheader">
2222
<span class="level">Level {{ currentActivity.level }}</span>
23-
<div class="uuid"><span class="uuid-label">id: </span><span class="uuid-value">{{ currentActivity.uuid }}</span></div>
23+
<div class="uuid">
24+
<span class="uuid-label">id: </span><span class="uuid-value">{{ currentActivity.uuid }}</span>
25+
</div>
2426
</div>
2527
<mat-accordion class="activity-details" multi="true">
2628
<mat-expansion-panel *ngIf="currentActivity.description?.hasContent()" [expanded]="true">
@@ -213,7 +215,8 @@ <h3><b>Usefulness</b></h3>
213215
*ngFor="let openCRE of currentActivity?.references?.openCRE"
214216
target="_blank"
215217
[href]="openCRE">
216-
View OpenCRE</a>
218+
View OpenCRE</a
219+
>
217220
</span>
218221
<ng-template #creEmpty>-</ng-template>
219222
</span>
@@ -336,9 +339,7 @@ <h4 class="tool-name" [innerHTML]="implement['name']"></h4>
336339
<mat-panel-title>
337340
<b>Implemented by</b>
338341
<div class="references-summary" [class.hidden]="implementedByPanel.expanded">
339-
<span
340-
class="ref-section"
341-
*ngFor="let progressTitle of progressTitlesWithTeams">
342+
<span class="ref-section" *ngFor="let progressTitle of progressTitlesWithTeams">
342343
<strong>{{ progressTitle }}:</strong>
343344
<span class="ref-values">
344345
<span
@@ -357,7 +358,9 @@ <h4 class="tool-name" [innerHTML]="implement['name']"></h4>
357358
<div class="reference-column" *ngFor="let progressTitle of progressTitlesWithTeams">
358359
<div class="reference-header">{{ progressTitle }}</div>
359360
<div class="reference-values">
360-
<span class="reference-value" *ngFor="let teamName of teamsByProgressTitle.get(progressTitle)">
361+
<span
362+
class="reference-value"
363+
*ngFor="let teamName of teamsByProgressTitle.get(progressTitle)">
361364
{{ teamName }}
362365
</span>
363366
</div>
@@ -369,7 +372,9 @@ <h4 class="tool-name" [innerHTML]="implement['name']"></h4>
369372
</mat-expansion-panel>
370373
</mat-accordion>
371374

372-
<div class="tags-section" *ngIf="currentActivity.tags?.length && currentActivity.tags?.[0] !== 'none'">
375+
<div
376+
class="tags-section"
377+
*ngIf="currentActivity.tags?.length && currentActivity.tags?.[0] !== 'none'">
373378
<div class="tags-container">
374379
<span class="tag-chip" *ngFor="let tag of currentActivity.tags">{{ tag }}</span>
375380
</div>

src/app/component/activity-description/activity-description.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export class ActivityDescriptionComponent implements OnInit, OnChanges {
7979
this.ResourceLabel = dataStore.getMetaString('labels', activity.difficultyOfImplementation.resources - 1);
8080
this.UsefulnessLabel = dataStore.getMetaString('labels', activity.usefulness - 1);
8181
/* eslint-enable */
82-
82+
8383
// Get teams that have implemented this activity
8484
this.updateTeamsImplemented();
8585
}
@@ -89,7 +89,7 @@ export class ActivityDescriptionComponent implements OnInit, OnChanges {
8989
this.teamsImplemented.clear();
9090
this.teamsByProgressTitle.clear();
9191
this.progressTitlesWithTeams = [];
92-
92+
9393
const dataStore = this.loader.datastore;
9494
if (!dataStore || !dataStore.progressStore || !dataStore.meta || !this.currentActivity.uuid) {
9595
return;
@@ -108,11 +108,11 @@ export class ActivityDescriptionComponent implements OnInit, OnChanges {
108108
for (const teamName of teams) {
109109
const progressTitle = progressStore.getTeamProgressTitle(activityUuid, teamName);
110110
const progressValue = progressStore.getTeamActivityProgressValue(activityUuid, teamName);
111-
111+
112112
// Only include teams that have made progress (value > 0)
113113
if (progressValue > 0) {
114114
this.teamsImplemented.set(teamName, progressTitle);
115-
115+
116116
// Group teams by progress title
117117
if (!this.teamsByProgressTitle.has(progressTitle)) {
118118
this.teamsByProgressTitle.set(progressTitle, []);

src/app/component/sidenav-buttons/sidenav-buttons.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export class SidenavButtonsComponent implements OnInit {
1212
'Matrix',
1313
'Mappings',
1414
'Teams',
15+
'Settings',
1516
'Usage',
1617
'Roadmap v4.0',
1718
'DSOMM User Day 2025',
@@ -22,6 +23,7 @@ export class SidenavButtonsComponent implements OnInit {
2223
'table_chart',
2324
'timeline',
2425
'people',
26+
'list',
2527
'description',
2628
'landscape',
2729
'school',
@@ -32,6 +34,7 @@ export class SidenavButtonsComponent implements OnInit {
3234
'/matrix',
3335
'/mapping',
3436
'/teams',
37+
'/settings',
3538
'/usage',
3639
'/roadmap',
3740
'/userday',

src/app/component/teams-groups-editor/selectable-list.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ <h2>{{ title }}</h2>
4545

4646
<span *ngIf="editMode">
4747
<button mat-icon-button (click)="startEditItem(name)" title="Rename {{ name }}">
48-
<mat-icon>edit</mat-icon>
48+
<mat-icon class="material-icons-outlined">edit</mat-icon>
4949
</button>
5050
<button mat-icon-button (click)="deleteListItem(name)" title="Delete {{ name }}">
51-
<mat-icon>delete</mat-icon>
51+
<mat-icon class="material-icons-outlined">delete</mat-icon>
5252
</button>
5353
</span>
5454
<span *ngIf="relationshipEditMode">

src/app/material/material.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { MatChipsModule } from '@angular/material/chips';
99
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
1010
import { MatAutocompleteModule } from '@angular/material/autocomplete';
1111
import { MatInputModule } from '@angular/material/input';
12+
import { MatSelectModule } from '@angular/material/select';
13+
import { MatFormFieldModule } from '@angular/material/form-field';
1214
import { MatExpansionModule } from '@angular/material/expansion';
1315
import { MatCardModule } from '@angular/material/card';
1416
import { MatCheckboxModule } from '@angular/material/checkbox';
@@ -29,6 +31,8 @@ const MaterialComponents = [
2931
MatProgressSpinnerModule,
3032
MatAutocompleteModule,
3133
MatInputModule,
34+
MatSelectModule,
35+
MatFormFieldModule,
3236
MatExpansionModule,
3337
MatCardModule,
3438
MatCheckboxModule,

src/app/model/activity-store.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ export class ActivityStore {
7575
return this._activityList;
7676
}
7777

78+
public getAllActivitiesUpToLevel(maxLevel: number | null): Activity[] {
79+
/* eslint-disable */
80+
if (maxLevel == null)
81+
return this._activityList;
82+
else
83+
return this._activityList.filter(a => a.level <= maxLevel);
84+
/* eslint-enable */
85+
}
86+
7887
public getAllCategoryNames(): string[] {
7988
return this._categoryNames;
8089
}

src/app/model/data-store.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,14 @@ export class DataStore {
6161
return this.activityStore?.getMaxLevel() || 0;
6262
}
6363

64-
public getLevels(): string[] {
65-
let maxLvl: number = this.getMaxLevel();
66-
return this.getMetaStrings()?.maturityLevels?.slice(0, maxLvl) || [];
64+
public getLevelTitles(maxLevel: number | null = null): string[] {
65+
if (maxLevel == null) maxLevel = this.getMaxLevel();
66+
let titles: string[] = this.getMetaStrings()?.maturityLevels?.slice(0, maxLevel) || [];
67+
if (titles.length < maxLevel) {
68+
for (let i = titles.length + 1; i <= maxLevel; i++) {
69+
titles.push(`Level ${i}`);
70+
}
71+
}
72+
return titles;
6773
}
6874
}

src/app/model/meta-store.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { YamlService } from '../service/yaml-loader/yaml-loader.service';
2-
import { ProgressDefinition, TeamNames, TeamGroups } from './types';
2+
import { ProgressDefinitions, TeamNames, TeamGroups } from './types';
33
import { perfNow } from 'src/app/util/util';
44

55
export interface MetaStrings {
@@ -16,16 +16,18 @@ const fallbackMetaStrings: MetaStrings = {
1616
};
1717

1818
const LOCALSTORAGE_KEY: string = 'meta';
19+
const PROGRESS_DEFINITIONS_KEY: string = 'progressDefinitions';
1920

2021
export class MetaStore {
2122
private yamlService: YamlService = new YamlService();
2223

2324
public hasLocalStorage: boolean = false;
25+
private defaultProgressDefinition: ProgressDefinitions = {};
2426

2527
checkForDsommUpdates: boolean = false;
2628
lang: string = 'en';
2729
strings: Record<string, MetaStrings> = { en: fallbackMetaStrings };
28-
progressDefinition: ProgressDefinition = {};
30+
progressDefinition: ProgressDefinitions = {};
2931
teamGroups: TeamGroups = {};
3032
teams: TeamNames = [];
3133
activityFiles: string[] = [];
@@ -52,7 +54,12 @@ export class MetaStore {
5254
metaData.checkForDsommUpdates || this.checkForDsommUpdates || false;
5355
this.lang = metaData.lang || this.lang || 'en';
5456
this.strings = metaData.strings || this.strings || fallbackMetaStrings;
55-
this.progressDefinition = metaData.progressDefinition || this.progressDefinition || {};
57+
// Store default progress definition
58+
if (metaData.progressDefinition) {
59+
this.defaultProgressDefinition = { ...metaData.progressDefinition };
60+
}
61+
// Load custom progress definition if exists, otherwise use default
62+
this.loadStoredProgressDefinition();
5663
this.teamGroups = metaData.teamGroups || this.teamGroups || {};
5764
this.teams = metaData.teams || this.teams || [];
5865
this.activityFiles = metaData.activityFiles || this.activityFiles || [];
@@ -62,6 +69,30 @@ export class MetaStore {
6269
}
6370
}
6471

72+
public saveProgressDefinition(definitions: ProgressDefinitions): void {
73+
this.progressDefinition = definitions;
74+
localStorage.setItem(PROGRESS_DEFINITIONS_KEY, JSON.stringify(definitions));
75+
}
76+
77+
public resetProgressDefinition(): void {
78+
this.progressDefinition = { ...this.defaultProgressDefinition };
79+
localStorage.removeItem(PROGRESS_DEFINITIONS_KEY);
80+
}
81+
82+
private loadStoredProgressDefinition(): void {
83+
const stored = localStorage.getItem(PROGRESS_DEFINITIONS_KEY);
84+
if (stored) {
85+
try {
86+
this.progressDefinition = JSON.parse(stored);
87+
} catch (error) {
88+
console.error('Failed to load stored progress definitions:', error);
89+
this.progressDefinition = { ...this.defaultProgressDefinition };
90+
}
91+
} else {
92+
this.progressDefinition = { ...this.defaultProgressDefinition };
93+
}
94+
}
95+
6596
public updateTeamsAndGroups(teams: TeamNames, teamGroups: TeamGroups): void {
6697
this.teams = teams;
6798
this.teamGroups = teamGroups;

0 commit comments

Comments
 (0)