Skip to content

Commit

Permalink
Merge branch 'master' into snyk-upgrade-8b240f0f993f32bbebfe1f7c445a1f36
Browse files Browse the repository at this point in the history
  • Loading branch information
ludeknovy authored Feb 18, 2024
2 parents eb658ff + 1f422a3 commit 07f1aac
Show file tree
Hide file tree
Showing 52 changed files with 838 additions and 116 deletions.
11 changes: 9 additions & 2 deletions .github/workflows/docker-hub-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,29 @@ jobs:
uses: actions/checkout@v2

- name: Log in to Docker Hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: novyl/jtl-reporter-fe

- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
labels: novyl/jtl-reporter-fe:latest
tags: novyl/jtl-reporter-fe:latest

11 changes: 9 additions & 2 deletions .github/workflows/docker-hub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,28 @@ jobs:
uses: actions/checkout@v2

- name: Log in to Docker Hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: novyl/jtl-reporter-fe

- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
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
12 changes: 12 additions & 0 deletions src/app/graphs/scenario-trends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ export const labelTrends: any = (text, title = "") => {
return timezoneOffset;
}
},
legend: {
align: "center",
itemMarginTop: 1,
useHTML: true,
maxHeight: 105,
},
exporting: {
buttons: {
contextButton: {
Expand Down Expand Up @@ -194,6 +200,12 @@ export const responseTimeDegradationCurveOption = () => {
},
},
},
legend: {
align: "center",
itemMarginTop: 1,
useHTML: true,
maxHeight: 105,
},
title: {
text: "",
},
Expand Down
2 changes: 1 addition & 1 deletion src/app/item-detail/item-detail.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class="fas fa-bars"></i></button>
<div class="dropdown-menu jtl-dropdown-control-menu" ngbDropdownMenu>
<app-edit-item *ngIf="itemData.environment"
[itemDetailData]="{note: itemData.note, resourcesLink: itemData.resourcesLink, environment: itemData.environment, hostname: itemData.hostname, isBase: itemData.isBase, params: itemParams, name: itemData.name}"
[itemDetailData]="{note: itemData.note, resourcesLink: itemData.resourcesLink, environment: itemData.environment, hostname: itemData.hostname, isBase: itemData.isBase, status: itemData.status, params: itemParams, name: itemData.name}"
(itemDetailChange)="itemDetailChanged($event)"></app-edit-item>
<app-share [params]=itemParams></app-share>
<app-delete-item *ngIf="itemData.reportStatus !== 'in_progress'" [itemData]="itemParams"></app-delete-item>
Expand Down
3 changes: 2 additions & 1 deletion src/app/item-detail/item-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
zeroErrorToleranceEnabled: null,
topMetricsSettings: null,
userSettings: null,
errorSummary: null
errorSummary: null,
status: null,
};
overallChartOptions;
scatterChartOptions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ <h6 class="card-header bg-transparent">Request Statistics <span class="compare">
<td *ngIf="displayColumn(itemData.userSettings?.requestStats?.max)"><span
[className]="comparedData ? _.maxResponseTime > 0 ? 'value-positive' : 'value-negative' : ''">{{_.maxResponseTime | number: '1.0-2'}}</span>
</td>
<td *ngIf="displayColumn(itemData.userSettings?.requestStats?.p90)"><span
<td *ngIf="displayColumn(itemData.userSettings?.requestStats?.p50, false)"><span
[className]="comparedData ? _.medianResponseTime > 0 ? 'value-positive' : 'value-negative' : ''">{{_.medianResponseTime | number: '1.0-2'}}</span>
</td>
<td *ngIf="displayColumn(itemData.userSettings?.requestStats?.p90)"><span
Expand Down
Loading

0 comments on commit 07f1aac

Please sign in to comment.