Skip to content

Commit

Permalink
#408 Added List View to Progress Dashboard (#231)
Browse files Browse the repository at this point in the history
* moved ProgressComponent into subfolder

renamed progressComponent into ProgressCardComponent

* generated progress-list component with angular cli

* added empty progress-list to sessions dashboard

added dummy table

* added table to end of the progress dashboard

* added progress colour to table

* ui changes to list-view

* Added action button

* progress info overlay enabled

* added filter function

* changed table structure

* added view to settings

* added clarity table, fixed colors, added service

* changed sort fields

* modifications for angular 17

---------

Co-authored-by: Tanja Ulmen <[email protected]>
  • Loading branch information
tanemlu and Tanja Ulmen authored Dec 10, 2024
1 parent 99d4202 commit 15d1ecc
Show file tree
Hide file tree
Showing 20 changed files with 491 additions and 81 deletions.
8 changes: 6 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ import { AlertComponent } from './alert/alert.component';
import { VmtemplatesComponent } from './configuration/vmtemplates/vmtemplates.component';
import { EditVmtemplateComponent } from './configuration/vmtemplates/edit-vmtemplate/edit-vmtemplate.component';
import { AppConfigService } from './app-config.service';
import { ProgressComponent } from './progress/progress.component';
import { ProgressCardComponent } from './progress/progress-card/progress-card.component';
import { ProgressListComponent } from './progress/progress-list/progress-list.component';
import { ProgressInfoComponent } from './progress/progress-info/progress-info.component';
import { EventUserListComponent } from './dashboards/progress-dashboard/event-user-list/event-user-list.component';
import { IntervalTimer } from './IntervalTimer/interval-timer.component';
Expand Down Expand Up @@ -169,6 +170,7 @@ import { TooltipDirective } from './directives/tooltip.directive';
import { TooltipComponent } from './tooltip/tooltip.component';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { AuthnService } from './data/authn.service';
import { SessionProgressService } from './progress/session-progress.service';

ClarityIcons.addIcons(
plusIcon,
Expand Down Expand Up @@ -268,7 +270,8 @@ export function jwtOptionsFactory(): JwtConfig {
VmtemplatesComponent,
EditVmtemplateComponent,
ProgressInfoComponent,
ProgressComponent,
ProgressCardComponent,
ProgressListComponent,
EventUserListComponent,
IntervalTimer,
ProgressDashboardComponent,
Expand Down Expand Up @@ -360,6 +363,7 @@ export function jwtOptionsFactory(): JwtConfig {
GargantuaClientFactory,
AppConfigService,
ProgressService,
SessionProgressService,
PredefinedServiceService,
ThemeService,
TypedSettingsService,
Expand Down
2 changes: 2 additions & 0 deletions src/app/configuration/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
DEFAULT_ALERT_ERROR_DURATION,
DEFAULT_ALERT_SUCCESS_DURATION,
} from 'src/app/alert/alert';
import { ProgressViewMode } from 'src/app/data/ProgressViewMode';

@Component({
selector: 'app-settings',
Expand All @@ -28,6 +29,7 @@ export class SettingsComponent implements OnInit {
scopesLoading = true;

readonly FormGroupType = FormGroupType; // Reference to TypedInputTypes enum for template use
public progress_view_mode: ProgressViewMode = "cardView"

@ViewChild('alert') alert: AlertComponent;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,37 @@
>Whether finished sessions should be included.
</clr-control-helper>
</clr-toggle-container>
<clr-radio-container id="selectViewToggle" clrInline>
<clr-radio-wrapper>
<input
checked
type="radio"
clrRadio
value="cardView"
[formControl]="progressViewModeControl"
/>
<label>Card View</label>
</clr-radio-wrapper>
<clr-radio-wrapper>
<input
type="radio"
clrRadio
value="listView"
[formControl]="progressViewModeControl"
/>
<label>List View</label>
</clr-radio-wrapper>
</clr-radio-container>
<clr-toggle-container id="hideUsernamesToggle">
<clr-toggle-wrapper>
<input
type="checkbox"
clrToggle
name="hideUsernames"
[(ngModel)]="hide_usernames_status"
(ngModelChange)="saveSettings($event)"
(ngModelChange)="
saveSettings({ hide_usernames_status: $event })
"
/>
<label>Hide Usernames</label>
</clr-toggle-wrapper>
Expand Down Expand Up @@ -109,24 +132,47 @@
<interval-timer (intervalElapsed)="refresh()"></interval-timer>
</div>
</div>
<div class="clr-row">
@if (currentProgress.length > 0) {
@for (p of filteredProgress; track p) {
<div class="clr-col-12 clr-col-sm-6 clr-col-md-4 clr-col-lg-3">
<progress-card
[progress]="p"
[pause]="pause"
[hideUsername]="hide_usernames_status"
(nameClickedEvent)="filterName($event)"
></progress-card>
@if (progressViewModeControl.value === "cardView") {
<div class="clr-row">
@if (currentProgress && currentProgress.length > 0) {
@for (p of filteredProgress; track p) {
<div class="clr-col-12 clr-col-sm-6 clr-col-md-4 clr-col-lg-3">
<progress-card
[progress]="p"
[pause]="pause"
[hideUsername]="hide_usernames_status"
(nameClickedEvent)="filterName($event)"
></progress-card>
</div>
}
} @else {
<div class="clr-col-12">
<p>No sessions found.</p>
</div>
}
} @else {
<div class="clr-col-12">
<p>No sessions found.</p>
</div>
}
</div>
</div>
}
@if (progressViewModeControl.value === "listView") {
<div class="clr-row">
<ng-container>
@if (currentProgress && currentProgress.length > 0) {
<div class="flex-container">
<progress-list
[progressList]="filteredProgress"
[pause]="pause"
[hideUsername]="hide_usernames_status"
(nameClickedEvent)="filterName($event)"
>
</progress-list>
</div>
} @else {
<div class="clr-col-12">
<p>No sessions found.</p>
</div>
}
</ng-container>
</div>
}
</div>

<event-user-list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,11 @@ svg circle {
stroke: red;
}
}

.flex-container {
display: flex;
width: 100%;
flex-direction: column;
margin-top: 20px;
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import { ScenarioService } from '../../data/scenario.service';
import { CourseService } from '../../data/course.service';
import { EventUserListComponent } from './event-user-list/event-user-list.component';
import { JwtHelperService } from '@auth0/angular-jwt';
import { combineLatest, Subject, takeUntil } from 'rxjs';
import { combineLatest, distinctUntilChanged, Subject, takeUntil } from 'rxjs';
import { User } from '../../data/user';
import { Settings, SettingsService } from 'src/app/data/settings.service';
import { FormGroup } from '@angular/forms';
import { FormControl, FormGroup } from '@angular/forms';

@Component({
selector: 'progress-dashboard',
templateUrl: './progress-dashboard.component.html',
styleUrls: ['./progress-dashboard.component.scss'],
})

export class ProgressDashboardComponent implements OnInit, OnDestroy, OnChanges {
@Input()
selectedEvent: ScheduledEventBase;
Expand All @@ -30,6 +31,7 @@ export class ProgressDashboardComponent implements OnInit, OnDestroy, OnChanges
public users: User[] = [];
public settingsForm: FormGroup;
public hide_usernames_status: boolean = false;
public progressViewModeControl = new FormControl<'cardView' | 'listView'>('cardView');
private settings_service$ = new Subject<Readonly<Settings>>();

public pauseCall: boolean = false; // Stop refreshing if we are looking at a progress
Expand All @@ -53,7 +55,7 @@ export class ProgressDashboardComponent implements OnInit, OnDestroy, OnChanges
public progressService: ProgressService,
public scheduledeventService: ScheduledeventService,
public helper: JwtHelperService,
public settingsService: SettingsService
public settingsService: SettingsService,
) {}

ngOnInit() {
Expand All @@ -63,13 +65,25 @@ export class ProgressDashboardComponent implements OnInit, OnDestroy, OnChanges
.subscribe(
({
hide_usernames_status = false,
progress_view_mode = 'cardView'
}) => {
this.settingsForm.patchValue({
hide_usernames_status
hide_usernames_status,
progress_view_mode
});
this.hide_usernames_status = this.settingsForm.get('hide_usernames_status')?.value
this.progressViewModeControl.setValue(this.settingsForm.get('progress_view_mode')?.value)
},
);
this.progressViewModeControl.valueChanges
.pipe(distinctUntilChanged())
.subscribe((value) => {
if (value === 'cardView') {
this.setCardView();
} else if (value === 'listView') {
this.setListView();
}
});
this.refresh();
}

Expand Down Expand Up @@ -121,6 +135,17 @@ export class ProgressDashboardComponent implements OnInit, OnDestroy, OnChanges
this.filter();
}

setCardView() {
//this.progressViewModeService.setCardView();
this.saveSettings({ progress_view_mode: 'cardView' })
}

setListView() {
//this.progressViewModeService.setListView();
this.saveSettings({ progress_view_mode: 'listView' })

}

openUserList() {
this.userList.openModal();
}
Expand Down Expand Up @@ -171,16 +196,15 @@ export class ProgressDashboardComponent implements OnInit, OnDestroy, OnChanges
});
}

saveSettings(newHideUsernamesStatus: boolean) {
saveSettings(update: Partial<Settings>) {
if (this.settingsForm.value) {
this.settingsService.update({hide_usernames_status: newHideUsernamesStatus}).subscribe({
this.settingsService.update(update).subscribe({
next: () => {
console.log('Saved Settings.');
},
error: (err) => {
console.error('Error while saving settings:', err);
}
})
},
});
}
}

Expand Down
1 change: 1 addition & 0 deletions src/app/data/ProgressViewMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ProgressViewMode = 'cardView' | 'listView';
18 changes: 11 additions & 7 deletions src/app/data/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
FormControl,
FormGroup,
} from '@angular/forms';
import { ProgressViewMode } from './ProgressViewMode';

export type ChartDetailsFormGroup = FormGroup<{
observationPeriod: FormControl<'daily' | 'weekly' | 'monthly'>;
Expand Down Expand Up @@ -71,6 +72,7 @@ export type SettingFormGroup = FormGroup<{
>;
hide_usernames_status: FormControl<boolean>;
theme: FormControl<'dark' | 'light' | 'system'>;
progress_view_mode: FormControl<ProgressViewMode>;
}>;

// This object type maps VMTemplate names to the number of requested VMs
Expand Down Expand Up @@ -188,10 +190,14 @@ export function isChartDetailsFormGroup(
return (
formGroup instanceof FormGroup &&
formGroup.controls.observationPeriod instanceof FormControl &&
['daily', 'weekly', 'monthly'].includes(formGroup.controls.observationPeriod.value) &&
['daily', 'weekly', 'monthly'].includes(
formGroup.controls.observationPeriod.value,
) &&
formGroup.controls.scenarios instanceof FormControl &&
Array.isArray(formGroup.controls.scenarios.value) &&
formGroup.controls.scenarios.value.every((item) => typeof item === 'string') &&
formGroup.controls.scenarios.value.every(
(item) => typeof item === 'string',
) &&
formGroup.controls.startDate instanceof FormControl &&
typeof formGroup.controls.startDate.value === 'string' &&
formGroup.controls.endDate instanceof FormControl &&
Expand All @@ -200,7 +206,7 @@ export function isChartDetailsFormGroup(
}

export function isGenericFormControl(
control: AbstractControl
control: AbstractControl,
): control is GenericFormControl {
return (
control instanceof FormControl &&
Expand All @@ -210,17 +216,15 @@ export function isGenericFormControl(
);
}

export function isGenericFormArray(
control: any
): control is GenericFormArray {
export function isGenericFormArray(control: any): control is GenericFormArray {
return (
control instanceof FormArray &&
control.controls.every(
(ctrl) =>
ctrl instanceof FormControl &&
(typeof ctrl.value === 'string' ||
typeof ctrl.value === 'number' ||
typeof ctrl.value === 'boolean')
typeof ctrl.value === 'boolean'),
)
);
}
14 changes: 12 additions & 2 deletions src/app/data/settings.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { HttpErrorResponse, HttpParams } from '@angular/common/http';
import { ProgressViewMode } from './ProgressViewMode';
import { Subject, concat, throwError } from 'rxjs';
import {
catchError,
Expand All @@ -21,6 +22,7 @@ export interface Settings {
terminal_theme: (typeof themes)[number]['id'];
hide_usernames_status: boolean;
theme: 'dark' | 'light' | 'system';
progress_view_mode: ProgressViewMode;
}

/**
Expand All @@ -40,8 +42,15 @@ export class SettingsService {
validators: [Validators.required],
nonNullable: true,
}),
hide_usernames_status: new FormControl<boolean>(false, {nonNullable: true}),
theme: new FormControl<'dark' | 'light' | 'system'>('system', {nonNullable: true}),
hide_usernames_status: new FormControl<boolean>(false, {
nonNullable: true,
}),
progress_view_mode: new FormControl<ProgressViewMode>('cardView', {
nonNullable: true,
}),
theme: new FormControl<'dark' | 'light' | 'system'>('system', {
nonNullable: true,
}),
});

fetch() {
Expand All @@ -54,6 +63,7 @@ export class SettingsService {
terminal_theme: themes[0].id,
hide_usernames_status: false,
theme: 'system',
progress_view_mode: 'cardView',
} as Settings),
),
tap((s: Settings) => {
Expand Down
Loading

0 comments on commit 15d1ecc

Please sign in to comment.