Skip to content

Commit

Permalink
Screen Apps (#778)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephGit authored Oct 15, 2024
1 parent 2273c3f commit ec655ac
Show file tree
Hide file tree
Showing 110 changed files with 1,615 additions and 1,236 deletions.
4 changes: 2 additions & 2 deletions AMW_angular/io/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
"error",
{
"type": "attribute",
"prefix": "amw",
"prefix": "app",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "amw",
"prefix": "app",
"style": "kebab-case"
}
]
Expand Down
5 changes: 2 additions & 3 deletions AMW_angular/io/coding-guidelines.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Coding Guidelines


## Inject() over Constructor-Injections

Use `inject()` instead of constuctor-injection to make the code more explicit and obvious.
Expand All @@ -16,6 +15,7 @@ constructor(
```

## RxJS

Leverage RxJS for API calls, web sockets, and complex data flows, especially when handling multiple asynchronous events. Combine with Signals to simplify component state management.

## Signals
Expand Down Expand Up @@ -56,7 +56,7 @@ readOnlyUsers = toSignal(this.users$, { initialValue: [] as User[]});

## Auth Service

The frontend provides a singelton auth-service which holds all restrictions for the current user.
The frontend provides a singelton auth-service which holds all restrictions for the current user.

After injecting the service in your component you can get Permissions/Actions depending on your needs:

Expand All @@ -72,5 +72,4 @@ this.canCreate.set(actions.some(isAllowed('CREATE')));

// or directly set signal based on a concret permission and action value
this.canViewSettings.set(this.authService.hasPermission('SETTINGS', 'READ'));

```
23 changes: 14 additions & 9 deletions AMW_angular/io/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ChangeDetectorRef } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { provideRouter, Router, withHashLocation } from '@angular/router';
import { of } from 'rxjs';
import { AppComponent } from './app.component';
import { NavigationComponent } from './navigation/navigation.component';
Expand All @@ -10,6 +9,7 @@ import { AppConfiguration } from './setting/app-configuration';
import { SettingService } from './setting/setting.service';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { routes } from './app.routes';

class RouterStub {
navigateByUrl(url: string) {
Expand All @@ -18,17 +18,23 @@ class RouterStub {
}

describe('App', () => {
let router: Router;
let app: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let settingService: SettingService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, NavigationComponent, AppComponent],
providers: [SettingService, ChangeDetectorRef, AppComponent, { provide: Router, useClass: RouterStub }, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
}).compileComponents();
router = TestBed.inject(Router);
imports: [NavigationComponent, AppComponent],
providers: [
SettingService,
ChangeDetectorRef,
AppComponent,
{ provide: Router, useClass: RouterStub },
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
provideRouter(routes, withHashLocation()),
],
}).compileComponents();
settingService = TestBed.inject(SettingService);

fixture = TestBed.createComponent(AppComponent);
Expand All @@ -54,7 +60,6 @@ describe('App', () => {

it('should set empty logoutUrl if config not found', () => {
// given
const expectedKey: string = 'logoutUrl';
const expectedValue: string = '';
const appConf: AppConfiguration = {
key: { value: 'test', env: 'TEST' },
Expand All @@ -63,6 +68,6 @@ describe('App', () => {

app.ngOnInit();

expect(app.logoutUrl).toEqual('');
expect(app.logoutUrl).toEqual(expectedValue);
});
});
4 changes: 1 addition & 3 deletions AMW_angular/io/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ import { ToastContainerComponent } from './shared/elements/toast/toast-container
export class AppComponent implements OnInit {
logoutUrl: string;

constructor(
private settingService: SettingService
) { }
constructor(private settingService: SettingService) {}

ngOnInit(): void {
this.settingService.getAllAppSettings().subscribe((r) => this.configureSettings(r));
Expand Down
2 changes: 2 additions & 0 deletions AMW_angular/io/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Routes } from '@angular/router';
import { DeploymentsComponent } from './deployments/deployments.component';
import { appsRoutes } from './apps/apps.routes';
import { auditviewRoutes } from './auditview/auditview.routes';
import { deploymentRoutes } from './deployment/deployment-routes';
import { settingsRoutes } from './settings/settings.routes';
Expand All @@ -9,6 +10,7 @@ export const routes: Routes = [
// default route only, the rest is done in module routing
{ path: '', component: DeploymentsComponent },

...appsRoutes,
...settingsRoutes,
...auditviewRoutes,
...deploymentRoutes,
Expand Down
55 changes: 55 additions & 0 deletions AMW_angular/io/src/app/apps/app-add/app-add.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<div class="modal-header">
<h5 class="modal-title" id="createApplicationTitle">Create application</h5>
<button type="button" class="btn btn-light close" aria-label="Close" (click)="cancel()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-horizontal mx-2">
<div class="mb-3">
<label for="name" class="form-label">Application</label>
<input type="text" class="form-control" id="name" [(ngModel)]="app.appName" />
</div>
<div class="mb-3">
<label class="form-label">Release</label>
<ng-select id="selectRelease" [(ngModel)]="app.appReleaseId" placeholder="Select release">
@for (release of releases(); track release.id) {
<ng-option [value]="release.id">{{ release.name }}</ng-option>
}
</ng-select>
</div>
<div class="mb-3">
<label class="form-label">Applicationserver</label>
<ng-select id="selectAppServer" [(ngModel)]="appServerGroup" placeholder="Select applicationserver">
@for (appServer of appServerGroups(); track appServer.id) {
<ng-option [value]="appServer">{{ appServer.name }}</ng-option>
}
</ng-select>
</div>
<div class="mb-3">
<label class="form-label">Applicationserver Release</label>
<ng-select
id="selectAppServerRelease"
[(ngModel)]="appServerRelease"
[disabled]="hasInvalidGroup()"
placeholder="Select AS release"
>
@if (appServerGroup && appServerGroup.releases) { @for (release of appServerGroup.releases; track release.id) {
<ng-option [value]="release">{{ release.release }}</ng-option>
} }
</ng-select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" (click)="cancel()" [attr.data-cy]="'button-cancel'">Cancel</button>
<button
type="button"
class="btn btn-primary"
[disabled]="hasInvalidFields()"
(click)="save()"
[attr.data-cy]="'button-save'"
>
Save
</button>
</div>
15 changes: 15 additions & 0 deletions AMW_angular/io/src/app/apps/app-add/app-add.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { AppAddComponent } from './app-add.component';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

describe('AppAddComponent', () => {
let component: AppAddComponent;
const activeModal = new NgbActiveModal();

beforeEach(async () => {
component = new AppAddComponent(activeModal);
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
61 changes: 61 additions & 0 deletions AMW_angular/io/src/app/apps/app-add/app-add.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Component, EventEmitter, Input, Output, Signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { Release } from '../../settings/releases/release';
import { Release as Rel } from '../../resource/release';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { Resource } from '../../resource/resource';
import { AppCreate } from '../app-create';

@Component({
selector: 'app-app-add',
standalone: true,
imports: [FormsModule, NgSelectModule],
templateUrl: './app-add.component.html',
})
export class AppAddComponent {
@Input() releases: Signal<Release[]>;
@Input() appServerGroups: Signal<Resource[]>;
@Output() saveApp: EventEmitter<AppCreate> = new EventEmitter<AppCreate>();

app: AppCreate = { appName: '', appReleaseId: null, appServerId: null, appServerReleaseId: null };
appServerGroup: Resource;
appServerRelease: Rel;

constructor(public activeModal: NgbActiveModal) {
this.activeModal = activeModal;
}

hasInvalidGroup(): boolean {
const isInvalid =
this.appServerGroup === undefined || this.appServerGroup === null || this.appServerGroup?.releases.length === 0;
if (isInvalid) {
this.appServerRelease = undefined;
}
return isInvalid;
}

// apps without appserver are valid too
hasInvalidFields(): boolean {
return (
this.app.appName === '' ||
this.app.appReleaseId === null ||
(!this.hasInvalidGroup() && (this.appServerRelease === undefined || this.appServerRelease === null))
);
}

cancel() {
this.activeModal.close();
}

save() {
const app: AppCreate = {
appName: this.app.appName,
appReleaseId: this.app.appReleaseId,
appServerId: this.appServerGroup?.id,
appServerReleaseId: this.appServerRelease?.id,
};
this.saveApp.emit(app);
this.activeModal.close();
}
}
6 changes: 6 additions & 0 deletions AMW_angular/io/src/app/apps/app-create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface AppCreate {
appName: string;
appReleaseId: number;
appServerId: number;
appServerReleaseId: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<div class="modal-header">
<h5 class="modal-title" id="createApplicationServer">Create application server</h5>
<button type="button" class="btn btn-light close" aria-label="Close" (click)="cancel()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-horizontal mx-2">
<div class="mb-3">
<label for="name" class="form-label">Applicationserver</label>
<input type="text" class="form-control" id="name" [(ngModel)]="appServer.name" />
</div>
<div class="mb-3">
<label class="form-label">Release</label>
<ng-select id="selectRelease" [(ngModel)]="appServer.release" placeholder="Select release">
@for (release of releases(); track release.id) {
<ng-option [value]="release">{{ release.name }}</ng-option>
}
</ng-select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" (click)="cancel()">Cancel</button>
<button type="button" class="btn btn-primary" [disabled]="hasInvalidFields()" (click)="save()">Save</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { AppServerAddComponent } from './app-server-add.component';

describe('AppServerAddComponent', () => {
let component: AppServerAddComponent;
const activeModal = new NgbActiveModal();

beforeEach(async () => {
component = new AppServerAddComponent(activeModal);
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Component, EventEmitter, Input, Output, Signal } from '@angular/core';
import { Release } from '../../settings/releases/release';
import { AppServer } from '../app-server';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { FormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';

@Component({
selector: 'app-server-add',
standalone: true,
imports: [FormsModule, NgSelectModule],
templateUrl: './app-server-add.component.html',
})
export class AppServerAddComponent {
@Input() releases: Signal<Release[]>;
@Output() saveAppServer: EventEmitter<AppServer> = new EventEmitter<AppServer>();

appServer: AppServer = { name: '', apps: [], deletable: false, id: null, runtimeName: '', release: null };

constructor(public activeModal: NgbActiveModal) {
this.activeModal = activeModal;
}

hasInvalidFields(): boolean {
return this.appServer.name === '' || this.appServer.release?.id === null || this.appServer.release?.name === '';
}

cancel() {
this.activeModal.close();
}

save() {
const appServer: AppServer = {
name: this.appServer.name,
release: this.appServer.release,
deletable: this.appServer.deletable,
id: this.appServer.id,
runtimeName: this.appServer.runtimeName,
apps: this.appServer.apps,
};
this.saveAppServer.emit(appServer);
this.activeModal.close();
}
}
11 changes: 11 additions & 0 deletions AMW_angular/io/src/app/apps/app-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Release } from '../settings/releases/release';
import { App } from './app';

export interface AppServer {
id: number;
name: string;
deletable: boolean;
runtimeName: string;
release: Release;
apps: App[];
}
7 changes: 7 additions & 0 deletions AMW_angular/io/src/app/apps/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Release } from '../settings/releases/release';

export interface App {
id: number;
name: string;
release: Release;
}
Loading

0 comments on commit ec655ac

Please sign in to comment.