Skip to content

Commit

Permalink
Feature: global settings (#364)
Browse files Browse the repository at this point in the history
  • Loading branch information
ludeknovy authored Oct 16, 2023
1 parent 97ec041 commit 9cb1f92
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/app/_interceptors/mock-interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export class HttpRequestInterceptorMock implements HttpInterceptor {
if (request.url && request.url.includes("projects/test-project/scenarios/test-scenario/processing-items")) {
return of(new HttpResponse({ status: 200 }));
}
if (request.url && request.url.includes("global-settings")) {
return of(new HttpResponse({ status: 200 }));
}

return next.handle(request);
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/_services/global-settings.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface GlobalSettings {
projectAutoProvisioning: boolean
}
28 changes: 28 additions & 0 deletions src/app/_services/global-settings.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { HttpClient } from "@angular/common/http";
import { BehaviorSubject, Observable } from "rxjs";
import { GlobalSettings } from "./global-settings.model";
import { Injectable } from "@angular/core";

@Injectable({
providedIn: "root"
})
export class GlobalSettingsService {

private notification = new BehaviorSubject<any>({});
public notification$ = this.notification.asObservable();

constructor(private http: HttpClient) {
}

getGlobalSettings(): Observable<GlobalSettings> {
return this.http.get<GlobalSettings>("global-settings");
}

updateGlobalSettings(payload: GlobalSettings) {
return this.http.put("global-settings", payload, { observe: "response" });
}

setNotificationMessage(response) {
this.notification.next(response);
}
}
1 change: 0 additions & 1 deletion src/app/administration/api-token/api-keys.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { DeleteTokenComponent } from "./delete-token/delete-token.component";
import { SharedModule } from "../../shared/shared.module";
import { AuthGuard } from "../../auth.guard";
import { ApiKeysComponent } from "./api-keys.component";
import { NavigationModule } from "../navigation/navigation.module";
import { ReactiveFormsModule } from "@angular/forms";


Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<div class="administration">
<div class="container-fluid">
<div class="row">
<div class="col">
<div class="card card-content card-shadow">
<h6 class="card-header bg-transparent">Settings <span class="inline-controller"></span></h6>

<div class="card-body">
<div class="card-body">
<form [formGroup]="globalSettingsForm" (ngSubmit)="onSubmit()" class="pl-3" *ngIf="globalSettingsForm">

<div class="form-sub">
<h6>Project auto-provisioning</h6>
<div class="text-secondary mb-2"><i class="fas fa-info-circle"> </i>
<small> When pushing a test report into a project that does not exist, the application will create
a project and a scenario on the fly.</small></div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="projectAutoProvisioning"
formControlName="projectAutoProvisioning">
<label class="custom-control-label" for="projectAutoProvisioning">Project auto-provisioning</label>
</div>
</div>
</div>

<div class="modal-footer">
<button type="submit" *userRole="'admin'" class="btn btn-primary">Submit</button>
</div>
</form>



</div>
</div>
</div>
</div>
</div>

</div>
</div>

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";

import { GlobalSettingsComponent } from "./global-settings.component";
import { RouterTestingModule } from "@angular/router/testing";
import { ReactiveFormsModule } from "@angular/forms";
import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http";
import { HttpRequestInterceptorMock } from "../../_interceptors/mock-interceptor";

describe("GlobalSettingsComponent", () => {
let component: GlobalSettingsComponent;
let fixture: ComponentFixture<GlobalSettingsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RouterTestingModule, ReactiveFormsModule, HttpClientModule],
declarations: [ GlobalSettingsComponent ],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: HttpRequestInterceptorMock,
multi: true
}]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(GlobalSettingsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it("should create", () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Component, OnInit } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { GlobalSettingsService } from "../../_services/global-settings.service";
import { GlobalSettings } from "../../_services/global-settings.model";
import { catchError } from "rxjs/operators";
import { of } from "rxjs";
import { NotificationMessage } from "../../notification/notification-messages";

@Component({
selector: "app-global-settings",
templateUrl: "./global-settings.component.html",
styleUrls: ["./global-settings.component.css", "../administration.css", "../../shared-styles.css"]
})
export class GlobalSettingsComponent implements OnInit {
globalSettingsForm: FormGroup;

formControls = {
projectAutoProvisioning: null
}

constructor(
private globalSettingsService: GlobalSettingsService,
private notification: NotificationMessage,
) {
}

ngOnInit(): void {
this.globalSettingsService.getGlobalSettings().subscribe((body) => {
this.createFormControls(body);
this.createForm();
})

}

onSubmit() {
console.log(this.globalSettingsForm.valid)
if (this.globalSettingsForm.valid) {
const { projectAutoProvisioning } = this.globalSettingsForm.value
this.globalSettingsService.updateGlobalSettings({ projectAutoProvisioning })
.pipe(catchError(r => of(r)))
.subscribe(_ => {
const message = this.notification.globalSettingsNotification(_);
this.globalSettingsService.setNotificationMessage(message)
})
}
}

private createFormControls(settings: GlobalSettings) {
this.formControls.projectAutoProvisioning = new FormControl(settings.projectAutoProvisioning, []);
}

private createForm() {
this.globalSettingsForm = new FormGroup({
projectAutoProvisioning: this.formControls.projectAutoProvisioning
})
}



}
25 changes: 25 additions & 0 deletions src/app/administration/global-settings/global-settings.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { SharedModule } from "../../shared/shared.module";
import { ReactiveFormsModule } from "@angular/forms";
import { GlobalSettingsComponent } from "./global-settings.component";
import { RouterModule, Routes } from "@angular/router";
import { AuthGuard } from "../../auth.guard";
import { AddUserModule } from "../users/add-user/add-user.module";
import { DeleteUserModule } from "../users/delete-user/delete-user.module";
import { RoleModule } from "../../_directives/role.module";


const routes: Routes = [
{ path: "administration/global-settings", component: GlobalSettingsComponent, canActivate: [AuthGuard] },
];

@NgModule({
declarations: [GlobalSettingsComponent],
imports: [
CommonModule, RouterModule.forRoot(routes), SharedModule, ReactiveFormsModule, AddUserModule, DeleteUserModule, RoleModule
],
exports: [GlobalSettingsComponent]
})
export class GlobalSettingsModule {
}
8 changes: 8 additions & 0 deletions src/app/administration/navigation/navigation.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@

</li>

<li ngbNavItem [ngbNavItem]="'global-settings'">
<a ngbNavLink class="jtl-nav-link"
[routerLinkActive]="['active-link']"
*userRole="'admin'">Settings</a>
<ng-template ngbNavContent><app-global-settings></app-global-settings></ng-template>

</li>

<li [ngbNavItem]="'apiKeys'">
<a ngbNavLink class="jtl-nav-link"
[routerLinkActive]="['active-link']"
Expand Down
3 changes: 2 additions & 1 deletion src/app/administration/navigation/navigation.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ProjectAdministrationModule } from "../projects/project-administration.
import { ApiKeysModule } from "../api-token/api-keys.module";
import { UsersModule } from "../users/users.module";
import { MyProfileModule } from "../my-profile/my-profile.module";
import { GlobalSettingsModule } from "../global-settings/global-settings.module";

const routes: Routes = [
{ path: "administration", component: NavigationComponent, canActivate: [AuthGuard] },
Expand All @@ -18,7 +19,7 @@ const routes: Routes = [
declarations: [NavigationComponent],
imports: [
CommonModule, RouterModule, RoleModule, NgbNavModule, RouterModule.forRoot(routes), ProjectAdministrationModule, ApiKeysModule,
UsersModule, MyProfileModule,
UsersModule, MyProfileModule, GlobalSettingsModule
],
exports: [NavigationComponent]
})
Expand Down
4 changes: 4 additions & 0 deletions src/app/notification/notification-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ export class NotificationMessage {
return this.statusCodeMessage(response, "Scenario trend settings updated");
}

globalSettingsNotification(response) {
return this.statusCodeMessage(response, "Settings updated");
}

appInitialization(response) {
return this.statusCodeMessage(response, "")
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/notification/notification.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ProjectApiService } from "../project-api.service";
import { ScenarioApiService } from "../scenario-api.service";
import { ToastrService } from "ngx-toastr";
import { NotificationService } from "../_services/notification.service";
import { GlobalSettingsService } from "../_services/global-settings.service";

@Component({
selector: "app-alert",
Expand All @@ -18,6 +19,7 @@ export class NotificationComponent implements OnInit {
private projectService: ProjectApiService,
private scenarioApiService: ScenarioApiService,
private notificationService: NotificationService,
private globalSettingsService: GlobalSettingsService,
private toastr: ToastrService
) { }

Expand All @@ -29,6 +31,7 @@ export class NotificationComponent implements OnInit {
this.projectService.response$.subscribe(_ => this.showNotification(_));
this.scenarioApiService.response$.subscribe(_ => this.showNotification(_));
this.notificationService.notificationMessage$.subscribe(_ => this.showNotification(_));
this.globalSettingsService.notification$.subscribe(_ => this.showNotification(_));


this._success.subscribe((message) => {
Expand Down

0 comments on commit 9cb1f92

Please sign in to comment.