Skip to content

Commit

Permalink
Typed forms for settings (#167)
Browse files Browse the repository at this point in the history
* Add typed forms

* Get the form running

* Comments

* Spacing

* Formatting

* Current state: Multiple FormGroupTypes

* Add vertical tabs

* Add type float, general improvements

* support multiple categories

* Remove multiple categories again, introduce weight

* introduce representation

* Apply new structure

* Form validation

* Display detailed error messages

* Retreive settings

* Retreiving settings for given scope

* list scopes and fetch settings based on them

* Load single settings + motd for admin ui

* Better fetching of single settings

* Remove old code

* rename setting to motd-admin-ui

---------

Co-authored-by: Jan-Gerrit Göbel <jgoebel@uni-bremen.de>
  • Loading branch information
jggoebel and Jan-Gerrit Göbel authored Jun 20, 2023
1 parent 55e907f commit d246e7e
Show file tree
Hide file tree
Showing 23 changed files with 1,447 additions and 79 deletions.
5 changes: 5 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { StepComponent } from './step/step-component/step.component';
import { TerminalComponent } from './step/terminal/terminal.component';
import { RolesComponent } from './configuration/roles/roles/roles.component';
import { SessionStatisticsComponent } from './session-statistics/session-statistics.component';
import {SettingsComponent} from './configuration/settings/settings.component';

const routes: Routes = [
{path: '', redirectTo: '/home', pathMatch: 'full'},
Expand Down Expand Up @@ -79,6 +80,10 @@ const routes: Routes = [
AuthGuard
],
children: [
{
path: 'settings',
component: SettingsComponent
},
{
path: 'environments',
component: EnvironmentsComponent
Expand Down
13 changes: 11 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ import { FilterScenariosComponent } from './filter-scenarios/filter-scenarios.co
import { MDEditorComponent } from './scenario/md-editor/md-editor.component';
import { CodeWithSyntaxHighlightingComponent } from './configuration/code-with-syntax-highlighting/code-with-syntax-highlighting.component';
import { ResizableTextAreaDirective } from './directives/resizable-text-area.directive';

import { TypedFormComponent } from './typed-form/typed-form.component';
import { SettingsComponent } from './configuration/settings/settings.component';
import { TypedInputComponent } from './typed-form/typed-input.component';
import { TypedInputFieldComponent } from './typed-form/typed-input-field.component';
import { TypedSettingsService } from './data/typedSettings.service';

const appInitializerFn = (appConfig: AppConfigService) => {
return () => {
Expand Down Expand Up @@ -164,7 +168,11 @@ export function jwtOptionsFactory() {
VMTemplateServiceFormComponent,
FilterScenariosComponent,
CodeWithSyntaxHighlightingComponent,
ResizableTextAreaDirective
ResizableTextAreaDirective,
TypedFormComponent,
TypedInputComponent,
TypedInputFieldComponent,
SettingsComponent,
],
imports: [
BrowserModule,
Expand Down Expand Up @@ -209,6 +217,7 @@ export function jwtOptionsFactory() {
AppConfigService,
ProgressService,
PredefinedServiceService,
TypedSettingsService,
{
provide: APP_INITIALIZER,
useFactory: appInitializerFn,
Expand Down
4 changes: 3 additions & 1 deletion src/app/configuration/configuration.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<div class="content-container">
<nav class="sidenav">
<section class="sidenav-content">
<a href="javascript://" class="nav-link" [routerLink]="['settings']" [routerLinkActive]="'active'" *rbac="['environments.list']">
Settings</a>
<a href="javascript://" class="nav-link" [routerLink]="['environments']" [routerLinkActive]="'active'" *rbac="['environments.list']">
Environments</a>
<a href="javascript://" class="nav-link" [routerLink]="['vmtemplates']" [routerLinkActive]="'active'" *rbac="['virtualmachinetemplates.list']">
Expand All @@ -15,4 +17,4 @@
<router-outlet></router-outlet>
</div>
</div>
</div>
</div>
65 changes: 65 additions & 0 deletions src/app/configuration/settings/settings.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<div class="clr-row">
<div class="clr-col">
<h3>
Settings
<span class="scope">{{ this.selectedScope?.displayName ?? "scope" }}</span>
</h3>
</div>
</div>
<alert #alert></alert>
<ng-container *ngIf="scopesLoading">
<div>
<span class="spinner spinner-inline"> Please wait... </span>
<span> Scopes are being loaded... </span>
</div>
</ng-container>
<ng-container *ngIf="!scopesLoading">
<clr-dropdown>
<b><label>Scope</label></b>
<button
class="dropdown-toggle btn btn-link"
clrDropdownTrigger
[disabled]="scopes.length == 0"
>
<span *ngIf="!this.selectedScope">Select Scope</span>
<span *ngIf="this.selectedScope">{{
this.selectedScope.displayName
}}</span>
<clr-icon shape="caret down"></clr-icon>
</button>

<clr-dropdown-menu clrPosition="bottom-right" *clrIfOpen>
<clr-row
*ngFor="let sc of scopes"
clrDropdownItem
(click)="setScope(sc)"
[ngClass]="{ selected: this.selectedScope == sc }"
>
{{ sc.displayName }}
</clr-row>
</clr-dropdown-menu>
</clr-dropdown>
<button class="btn" (click)="onSubmit()" [disabled]="!hasChanges || !valid">
Save Changes
</button>
<ng-container *ngIf="loading">
<div>
<span class="spinner spinner-inline"> Please wait... </span>
<span> Settings are being loaded... </span>
</div>
</ng-container>
<ng-container *ngIf="!loading">
<app-typed-form
*ngIf="settings.length > 0"
[typedInputs]="settings"
(syncedInputs)="onFormChange($event)"
(inputsValid)="changeFormValidity($event)"
[groupType]="FormGroupType.TABS"
></app-typed-form>
<div *ngIf="settings.length == 0">
No settings available for scope
<code>{{ this.selectedScope.displayName }}</code
>.
</div>
</ng-container>
</ng-container>
6 changes: 6 additions & 0 deletions src/app/configuration/settings/settings.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.scope {
padding: 5px 10px 5px 10px;
color: white;
background-color: #3fc5f0;
border-radius: 20px;
}
91 changes: 91 additions & 0 deletions src/app/configuration/settings/settings.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Component, ViewChild } from '@angular/core';
import { TypedInput, FormGroupType } from '../../typed-form/TypedInput';
import {
PreparedScope,
TypedSettingsService,
} from 'src/app/data/typedSettings.service';
import { AlertComponent } from 'src/app/alert/alert.component';

@Component({
selector: 'app-settings',
templateUrl: './settings.component.html',
styleUrls: ['./settings.component.scss'],
})
export class SettingsComponent {
public settings: TypedInput[] = [];
public updatedSettings: TypedInput[] = [];
public hasChanges: boolean = false;
public valid: boolean = true;
public scopes: PreparedScope[] = [];
public selectedScope: PreparedScope;
public loading: boolean = true;
public scopesLoading: boolean = true;
readonly FormGroupType = FormGroupType; // Reference to TypedInputTypes enum for template use

@ViewChild('alert') alert: AlertComponent;

private alertTime = 2000;
private alertErrorTime = 10000;

constructor(public typedSettingsService: TypedSettingsService) {
this.getScopes();
}

onFormChange(data: TypedInput[]) {
this.updatedSettings = data;
this.hasChanges = true;
}

changeFormValidity(valid: boolean) {
this.valid = valid;
}

onSubmit() {
if (!this.updatedSettings) {
return;
}
console.log(this.updatedSettings);
this.typedSettingsService.updateCollection(this.updatedSettings).subscribe(
(resp) => {
console.log(resp);
this.hasChanges = false;
this.alert.success(
'Settings successfully saved',
false,
this.alertTime
);
},
(err) => {
this.alert.danger(err.error.message, true, this.alertErrorTime);
}
);
}

setScope(scope: PreparedScope) {
this.loading = true;
this.selectedScope = scope;
this.typedSettingsService.list(this.selectedScope.name).subscribe(
(typedSettings) => {
this.settings = typedSettings;
this.loading = false;
},
(err) => {
this.alert.danger(err.error.message, true, this.alertErrorTime);
}
);
}

getScopes() {
this.scopes = [];
this.typedSettingsService.listScopes().subscribe(
(scopes) => {
this.scopes = scopes;
this.scopesLoading = false;
this.setScope(this.scopes[0]);
},
(err) => {
this.alert.danger(err.error.message, true, this.alertErrorTime);
}
);
}
}
Loading

0 comments on commit d246e7e

Please sign in to comment.