diff --git a/src/app/appmarket/bulkDeployment/appdeployment.service.ts b/src/app/appmarket/bulkDeployment/appdeployment.service.ts index de9bdbfea154e0fdb81236cf766050a105247bfa..8ca97da1aaf043faf86a26b447f48823fb549763 100644 --- a/src/app/appmarket/bulkDeployment/appdeployment.service.ts +++ b/src/app/appmarket/bulkDeployment/appdeployment.service.ts @@ -1,6 +1,6 @@ import {Injectable} from '@angular/core'; import {ApplicationBase} from '../../model/application-base'; -import {HttpClient} from '@angular/common/http'; +import {HttpClient, HttpParams} from '@angular/common/http'; import {AppConfigService} from '../../service'; import {BulkResponse} from '../../model/bulk-response'; import {Observable} from 'rxjs'; @@ -89,5 +89,14 @@ export class AppdeploymentService { return this.http.get(this.getUrl() + `app/csv/${id}`, {responseType: 'blob'}) } + public refreshStatesInBulkDeployment(id: number) : Observable<BulkDeployment> { + return this.http.get<BulkDeployment>(this.getUrl() + `refresh/${id}`) + } + + public removeBulkDeployment(id: number, removeAll: boolean): Observable<void> { + let params = new HttpParams() + params = params.append('removeAll', removeAll) + return this.http.delete<void>(this.getUrl() + `${id}`, {params}) + } } diff --git a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html index e34eee5938d37ec4330b3cd1f1ebdc2d9659707f..6ca3b86ef56dbb270004f4df691a1a17d92c8c9a 100644 --- a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html +++ b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html @@ -1,2 +1,6 @@ -<app-bulk-list [header]="'BULK.APP.HEADER'" [bulks]="bulks" [mode]="mode"></app-bulk-list> +<app-bulk-list [header]="'BULK.APP.HEADER'" + [bulks]="bulks" + [mode]="mode" + (reloadBulks)="retrieveBulks()" +></app-bulk-list> diff --git a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts index 9256cfa4ea2a99172b68b96471a1312b92bb206d..7eaed23ae6fccaf2f641ca72cdd51d8ee205f5dd 100644 --- a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts +++ b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts @@ -20,6 +20,10 @@ export class BulkAppListComponent implements OnInit { } ngOnInit(): void { + this.retrieveBulks(); + } + + public retrieveBulks() { if (this.authService.getRoles().find(value => value === 'ROLE_VL_MANAGER') !== undefined) { this.deployService.getBulksAppDeploymentsOwner().subscribe(data => { data = data.sort((a, b) => new Date(b.creationDate).getTime() - new Date(a.creationDate).getTime()) diff --git a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html index c68bbe80370e26c7df8dfd879c91785745f46cb2..dad549b0d8a09af20bae1208a7176f18c99a6e0c 100644 --- a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html +++ b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html @@ -103,7 +103,7 @@ <a (click)="getAppBulkDetails(bulk?.id)"> {{"BULK.APP.DOWNLOAD_CSV" | translate}}</a> </li> <li *ngIf="mode === bulkTypeApp"> - <a (click)="modal.show()">{{ 'BULK.LIST.REMOVE' | translate }}</a> + <a (click)="modal.show(); setBulkToDelete(bulk)">{{ 'BULK.LIST.REMOVE' | translate }}</a> </li> </ul> </span> @@ -130,9 +130,12 @@ <p-checkbox [(ngModel)]="removeAll" binary="true"></p-checkbox> </div> </div> + <div *ngIf="errorMessage !== ''" style="margin-top: 2rem; display: flex; justify-content: start; color: indianred"> + <p>{{ 'BULK.REMOVE.ERROR' | translate}} {{errorMessage}}</p> + </div> </div> <div class="nmaas-modal-footer"> <button type="button" class="btn btn-secondary" (click)="modal.hide()">{{'APP_CHANGE_STATE_MODAL.CANCEL_BUTTON' | translate}}</button> - <button type="button" class="btn btn-primary" [disabled]="false">{{'BULK.REMOVE.REMOVE' | translate}}</button> + <button type="button" class="btn btn-primary" (click)="removeBulkDeployment()" [disabled]="false">{{'BULK.REMOVE.REMOVE' | translate}}</button> </div> </nmaas-modal> diff --git a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts index 8288379d544ee7f88744f62d8ee497a98c9d199c..642bcf677efea934828cac6db1d169ea51e72982 100644 --- a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts +++ b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, QueryList, ViewChild, ViewChildren} from '@angular/core'; +import {Component, EventEmitter, Input, Output, QueryList, ViewChild, ViewChildren} from '@angular/core'; import {BulkDeployment} from '../../../model/bulk-deployment'; import {BulkType} from '../../../model/bulk-response'; import {SortableHeaderDirective} from '../../../service/sort-domain.directive'; @@ -42,6 +42,12 @@ export class BulkListComponent { public searchValue = ''; public removeAll = false; + public bulkToDelete; + + public errorMessage = ''; + + @Output() + public reloadBulks = new EventEmitter<void>(); constructor(private appDeploy: AppdeploymentService, private sanitizer: DomSanitizer) { @@ -147,4 +153,25 @@ export class BulkListComponent { } return null } + + public removeBulkDeployment() { + this.appDeploy.removeBulkDeployment(this.bulkToDelete.id, this.removeAll) + .subscribe({ + next: (_) => { + this.reloadData() + this.modal.hide() + }, + error: err => { + this.errorMessage = err.error.message + } + }) + } + + public setBulkToDelete(bulk: BulkDeployment) { + this.bulkToDelete = bulk + } + + private reloadData() { + this.reloadBulks.emit() + } } diff --git a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html index 215014b66c57dfd28af43cf45473c215bd4ceca1..4fff4026057245bc910d12bd4e025985107390ac 100644 --- a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html +++ b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html @@ -197,6 +197,8 @@ </div> <div class="flex justify-content-end"> + <button class="btn btn-primary mr-2" (click)="refreshStates()">{{'BULK.APP.REFRESH' | translate}}</button> + <button class="btn btn-primary" (click)="getAppBulkDetails(this.bulkId)">{{'BULK.APP.DOWNLOAD_CSV' | translate}}</button> </div> </div> @@ -233,9 +235,9 @@ <li *ngIf="response.type === 'APPLICATION' && response?.details['appInstanceId'] !== undefined"> <a [routerLink]="['/instances/', response?.details['appInstanceId']]">{{ 'BULK.LIST.MOVE_APP' | translate }}</a> </li> - <li *ngIf="response.type === 'APPLICATION' && response.state !== 'COMPLETED'"> + <!-- <li *ngIf="response.type === 'APPLICATION' && response.state !== 'COMPLETED'"> <a>{{ 'BULK.APP.CHECK_STATE' | translate }}</a> - </li> + </li> --> </ul> </span> </td> diff --git a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts index a6775b4210ec0156cb5db31a91cf25f1a1172c21..5895c0b6ba5531de6c627b1026c321333073a0df 100644 --- a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts +++ b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts @@ -115,4 +115,11 @@ export class BulkViewComponent implements OnInit, OnDestroy { }) } + + public refreshStates() { + this.deployService.refreshStatesInBulkDeployment(this.bulkId).subscribe( deply => { + this.bulk = deply; + console.log("Updated states of bulks") + }) + } } diff --git a/src/app/shared/applications/applications.component.ts b/src/app/shared/applications/applications.component.ts index cc78bd5ac340e6aff6e2368fc027f94a5f63b0c9..03a1b40421b93fceead7206aefb4d2e6c9ffcace 100644 --- a/src/app/shared/applications/applications.component.ts +++ b/src/app/shared/applications/applications.component.ts @@ -24,6 +24,9 @@ function compareAppsPopularity(a: ApplicationBase, b: ApplicationBase, stats: an const bPop = stats[b.name] ? stats[b.name] : 0; return (aPop - bPop) * -1; // desc } +function compareAppsId(a: ApplicationBase, b: ApplicationBase): number { + return (a.id - b.id); +} @Component({ selector: 'nmaas-applications-view', @@ -53,8 +56,8 @@ export class ApplicationsViewComponent implements OnInit, OnChanges { public searchedAppName = ''; protected searchedTag = 'all'; - public sortModeList = ['NONE', 'NAME', 'RATING', 'POPULAR']; - public sortMode = 'NONE'; + public sortModeList = [ 'NAME', 'RATING', 'POPULAR', 'DATE']; + public sortMode = 'NAME'; private popStats: any = {}; @@ -73,6 +76,7 @@ export class ApplicationsViewComponent implements OnInit, OnChanges { this.popStats = data; } ) + } ngOnChanges(changes: SimpleChanges) { @@ -106,7 +110,7 @@ export class ApplicationsViewComponent implements OnInit, OnChanges { } this.applications = applications; - + this.doSearch() } protected updateSelected() { @@ -165,6 +169,8 @@ export class ApplicationsViewComponent implements OnInit, OnChanges { return [...apps].sort(compareAppsRating) case 'POPULAR': return [...apps].sort(popComp) + case 'DATE': + return [...apps].sort(compareAppsId) default: return apps } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index fb4946f331b4537b698bcadff73df57a83d04c90..cdc2db3120890f34fbebed676f7baf9d1e2bcf1b 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -51,16 +51,17 @@ import {DomainRolesDirective} from '../directive/domain-roles.directive'; import {SshKeysComponent} from './users/ssh-keys/ssh-keys.component'; import {NewSshKeyComponent} from './users/new-ssh-key/new-ssh-key.component'; import {ModalProvideSshKeyComponent} from './modal/modal-provide-ssh-key/modal-provide-ssh-key.component'; -import { ContactComponent } from './contact/contact.component'; +import {ContactComponent} from './contact/contact.component'; import {FormioModule} from '@formio/angular'; -import { PreferencesComponent } from './users/preferences/preferences.component'; +import {PreferencesComponent} from './users/preferences/preferences.component'; import {TooltipModule} from 'primeng/tooltip'; import {DropdownModule} from 'primeng/dropdown'; import {SortableHeaderDirective} from '../service/sort-domain.directive'; import {InputTextModule} from 'primeng/inputtext'; -import { DomainNamespaceAnnotationsComponent } from './domain-namespace-annotations/domain-namespace-annotations.component'; +import {DomainNamespaceAnnotationsComponent} from './domain-namespace-annotations/domain-namespace-annotations.component'; import { DEFAULT_PSM_OPTIONS } from 'angular-password-strength-meter/zxcvbn'; +import {AccessTokensComponent} from './users/access-tokens/access-tokens.component'; @NgModule({ imports: [ @@ -123,7 +124,8 @@ import { DEFAULT_PSM_OPTIONS } from 'angular-password-strength-meter/zxcvbn'; ContactComponent, PreferencesComponent, SortableHeaderDirective, - DomainNamespaceAnnotationsComponent + DomainNamespaceAnnotationsComponent, + AccessTokensComponent ], providers: [ PasswordValidator, @@ -174,7 +176,8 @@ import { DEFAULT_PSM_OPTIONS } from 'angular-password-strength-meter/zxcvbn'; ModalProvideSshKeyComponent, PreferencesComponent, SortableHeaderDirective, - DomainNamespaceAnnotationsComponent + DomainNamespaceAnnotationsComponent, + AccessTokensComponent ] }) export class SharedModule { diff --git a/src/app/shared/users/access-tokens/access-token.service.ts b/src/app/shared/users/access-tokens/access-token.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..50880d8ca75bd585e674529e0fd5e4aec469fe70 --- /dev/null +++ b/src/app/shared/users/access-tokens/access-token.service.ts @@ -0,0 +1,32 @@ +import {Observable} from 'rxjs'; +import {AccessToken} from './access-token'; +import {Injectable} from '@angular/core'; +import {GenericDataService} from '../../../service/genericdata.service'; +import {HttpClient} from '@angular/common/http'; +import {AppConfigService} from '../../../service'; + +@Injectable({ + providedIn: 'root' +}) +export class AccessTokenService extends GenericDataService { + + constructor(http: HttpClient, appConfig: AppConfigService) { + super(http, appConfig); + } + + public getAll(): Observable<AccessToken[]> { + return this.http.get<AccessToken[]>(this.getUrl()) + } + + public invalidate(id: number): Observable<void> { + return this.http.put<void>(`${this.getUrl()}/${id}`, '') + } + + public createToken(tokenName: string): Observable<AccessToken> { + return this.http.post<AccessToken>(this.getUrl(), tokenName) + } + + private getUrl(): string { + return this.appConfig.getApiUrl() + '/tokens'; + } +} diff --git a/src/app/shared/users/access-tokens/access-token.ts b/src/app/shared/users/access-tokens/access-token.ts new file mode 100644 index 0000000000000000000000000000000000000000..42239bc83516f6ca24d40b755fb6f828e054645b --- /dev/null +++ b/src/app/shared/users/access-tokens/access-token.ts @@ -0,0 +1,7 @@ +export class AccessToken { + public id: number + public name: string + public userId: number + public tokenValue: string + public valid: boolean +} diff --git a/src/app/shared/users/access-tokens/access-tokens.component.css b/src/app/shared/users/access-tokens/access-tokens.component.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/app/shared/users/access-tokens/access-tokens.component.html b/src/app/shared/users/access-tokens/access-tokens.component.html new file mode 100644 index 0000000000000000000000000000000000000000..73f8f698f8f7d66f93a926aa7305e748441c3d2a --- /dev/null +++ b/src/app/shared/users/access-tokens/access-tokens.component.html @@ -0,0 +1,60 @@ +<div style="margin-bottom: 15px;" class="panel panel-default"> + <div class="panel-heading">{{'TOKENS.HEADER' | translate}}</div> + <div class="panel-body"> + <table class="table table-hover" aria-describedby="User access tokens table"> + <thead> + <tr> + <th scope="col">{{'TOKENS.TABLE.ID' | translate}}</th> + <th scope="col">{{'TOKENS.TABLE.NAME' | translate}}</th> + <th scope="col">{{'TOKENS.TABLE.VALUE' | translate}}</th> + <th scope="col">{{'TOKENS.TABLE.VALID' | translate}}</th> + <th scope="col">{{'TOKENS.TABLE.ACTIONS' | translate}}</th> + </tr> + </thead> + <tbody> + <tr *ngFor="let token of tokensList"> + <td>{{token.id}}</td> + <td>{{token.name}}</td> + <td>{{token.tokenValue}}</td> + <td>{{token.valid}}</td> + <td> + <button type="button" class="btn btn-danger" + (click)="invalidate(token.id)">{{'TOKENS.BUTTON_INVALIDATE' | translate}}</button> + </td> + </tr> + <tr *ngIf="tokensList.length === 0"> + <td colspan="3" style="text-align: center">{{'TOKENS.NO_TOKENS' | translate}}</td> + </tr> + </tbody> + </table> + <div> + <button type="button" class="btn btn-success" + (click)="modal.show()">{{'TOKENS.NEW_TOKEN' | translate}}</button> + + </div> + </div> +</div> + +<nmaas-modal styleModal="info"> + <div class="nmaas-modal-header">{{'TOKENS.MODAL.HEADER' | translate}}</div> + <div class="nmaas-modal-body" style="height: 60%; max-height: 80vh;overflow-y: auto;"> + <form [formGroup]="requestForm" (ngSubmit)="createNewToken()"> + <div class="form-group"> + <label class="control-label" for="new-token-name"> + {{'TOKENS.MODAL.NAME' | translate}}: + </label> + <input id="new-token-name" type="text" class="form-control" formControlName="name"> + </div> + <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger"> + <div *ngIf="name.errors.required">{{'SSH_KEYS.MODAL.ERROR.NAME_REQUIRED' | translate}}</div> + <div *ngIf="name.errors.minlength">{{'SSH_KEYS.MODAL.ERROR.NAME_MINLENGTH' | translate}}</div> + <div *ngIf="name.errors.maxlength">{{'SSH_KEYS.MODAL.ERROR.NAME_MAXLENGTH' | translate}}</div> + </div> + <input type="submit" class="btn btn-success" value="{{'SSH_KEYS.MODAL.BUTTON_ADD' | translate}}" + [disabled]="!requestForm.valid"> + <button type="button" class="btn btn-primary pull-right" + (click)="modal.hide()">{{'SSH_KEYS.MODAL.BUTTON_CANCEL' | translate}}</button> + + </form> + </div> +</nmaas-modal> diff --git a/src/app/shared/users/access-tokens/access-tokens.component.spec.ts b/src/app/shared/users/access-tokens/access-tokens.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..410fd6ad82a9727a881b95b4e56c1f962a113eda --- /dev/null +++ b/src/app/shared/users/access-tokens/access-tokens.component.spec.ts @@ -0,0 +1,38 @@ +import {ComponentFixture, TestBed} from '@angular/core/testing'; + +import {AccessTokensComponent} from './access-tokens.component'; +import {HttpClientTestingModule} from '@angular/common/http/testing'; +import {TranslateFakeLoader, TranslateLoader, TranslateModule} from '@ngx-translate/core'; +import {ReactiveFormsModule} from '@angular/forms'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; + +describe('AccessTokensComponent', () => { + let component: AccessTokensComponent; + let fixture: ComponentFixture<AccessTokensComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AccessTokensComponent], + imports: [ + HttpClientTestingModule, + ReactiveFormsModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }), + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], + }) + .compileComponents(); + + fixture = TestBed.createComponent(AccessTokensComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/users/access-tokens/access-tokens.component.ts b/src/app/shared/users/access-tokens/access-tokens.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..8a076f18a3fd80a537e52d158de2d29dc1314957 --- /dev/null +++ b/src/app/shared/users/access-tokens/access-tokens.component.ts @@ -0,0 +1,67 @@ +import {Component, OnInit, ViewChild} from '@angular/core'; +import {Observable} from 'rxjs'; +import {AccessToken} from './access-token'; +import {AccessTokenService} from './access-token.service'; +import {ModalComponent} from '../../modal'; +import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms'; + +@Component({ + selector: 'app-access-tokens', + templateUrl: './access-tokens.component.html', + styleUrls: ['./access-tokens.component.css'] +}) +export class AccessTokensComponent implements OnInit { + + public tokens: Observable<AccessToken[]> = undefined; + public tokensList: AccessToken[] = []; + + public requestForm: UntypedFormGroup = undefined; + + public newTokenName = ''; + + @ViewChild(ModalComponent, {static: true}) + public readonly modal: ModalComponent; + + constructor(private tokenService: AccessTokenService, + private formBuilder: UntypedFormBuilder) { + } + + ngOnInit() { + this.requestForm = this.formBuilder.group({ + name: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(16)]], + }) + + this.tokens = this.tokenService.getAll(); + this.getData(); + } + + getData() { + this.tokensList = []; + this.tokens.subscribe( + data => this.tokensList.push(...data), + error => console.error(error) + ) + } + + invalidate(id: number) { + this.tokenService.invalidate(id).subscribe( + (_) => this.getData(), + error => console.error(error) + ); + } + + public createNewToken() { + this.tokenService.createToken(this.requestForm.value.name.trim()).subscribe({ + next: val => { + this.tokensList.push(val) + this.requestForm.reset(); + this.modal.hide(); + }, + error: err => console.warn(err) + }) + } + + get name() { + return this.requestForm.get('name'); + } +} diff --git a/src/app/shared/users/ssh-keys/ssh-keys.component.html b/src/app/shared/users/ssh-keys/ssh-keys.component.html index efb4cb027d9813f2b99c014a6a7894b6ea6e829d..fb8a78f932a3717b843e0dde2f803a767d88399e 100644 --- a/src/app/shared/users/ssh-keys/ssh-keys.component.html +++ b/src/app/shared/users/ssh-keys/ssh-keys.component.html @@ -1,4 +1,4 @@ -<div style="margin-bottom: 120px;" class="panel panel-default"> +<div style="margin-bottom: 15px;" class="panel panel-default"> <div class="panel-heading">{{'SSH_KEYS.HEADER' | translate}}</div> <div class="panel-body"> <div class="flex justify-content-end mb-4"> diff --git a/src/app/welcome/policy-subpage/policy-subpage.component.html b/src/app/welcome/policy-subpage/policy-subpage.component.html index 6678f7b23c2ececc3bce05cca3cc5fed9b029e48..85432326d3485692302bfcf2ed785189385cf7c3 100644 --- a/src/app/welcome/policy-subpage/policy-subpage.component.html +++ b/src/app/welcome/policy-subpage/policy-subpage.component.html @@ -1,7 +1,7 @@ <div id="welcome-container" class="container-fluid" style="margin-bottom: 20px;"> <div class="center-block center text-center"><a routerLink="/" data-toggle="tooltip" data-placement="right" - title="Network Management as a Service homepage"><img src="assets/images/logo.png" alt="logo" - style="margin: 5px" /></a> + title="Network Management as a Service homepage"><img src="assets/images/logo-small.png" alt="logo" width="280px" + style="margin-top: 30px" /></a> </div> <div class="card card-body col-lg-offset-2 col-md-offset-2 col-sm-offset-2 col-lg-8 col-md-8 col-sm-8 col-xs-12" style="margin-top: 15px; font-size: 14px;"> diff --git a/src/app/welcome/profile/profile.component.html b/src/app/welcome/profile/profile.component.html index f869b826e6e2744d74e6edf32beee6c2566419a6..f8c17f7e5690bf61858490dcb21e28b1035f820b 100644 --- a/src/app/welcome/profile/profile.component.html +++ b/src/app/welcome/profile/profile.component.html @@ -34,5 +34,6 @@ [allowedModes]="[ComponentMode.PROFILVIEW, ComponentMode.EDIT]"> </nmaas-userprivileges> <nmaas-ssh-keys></nmaas-ssh-keys> + <app-access-tokens></app-access-tokens> </div> </div> diff --git a/src/app/welcome/welcome.component.css b/src/app/welcome/welcome.component.css index ec3a5b4ffd080d0ed247a66375287187b41bac18..90dc85f0572a059f6b0e6d8f9ecb54ad749c4191 100644 --- a/src/app/welcome/welcome.component.css +++ b/src/app/welcome/welcome.component.css @@ -10,6 +10,14 @@ html, body { .flex-column{ flex-direction: column; } +.banner{ + background-color : #424242; + color: #E8E8E8; + padding: 12px; + justify-self: center; + display: grid; + width: 100%; +} .button{ text-decoration: none; font-weight: bold;