This is an automated email from the ASF dual-hosted git repository. hshpak pushed a commit to branch epm-connected-platform in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 7a9c52b578145a58804b02af72cf7fdfcdff5928 Author: Hennadii_Shpak <borch...@gmail.com> AuthorDate: Wed Oct 19 19:32:00 2022 +0300 added connected platform component --- .../administration/management/management.model.ts | 12 ++- .../resources/webapp/src/app/app.routing.module.ts | 63 +++++------ .../configs/connected-platforms.model.ts} | 17 +-- .../configs/routing-list.config.ts} | 29 +++--- .../pipes/normalize-link/index.ts} | 12 +-- .../pipes/normalize-link/normalize-link.pipe.ts} | 14 +-- .../src/app/core/services/appRouting.service.ts | 3 +- .../services/applicationServiceFacade.service.ts | 30 +++++- .../services/connected-platform-api.service.ts | 54 ++++++++++ .../connected-platform-dialog.component.html | 80 ++++++++++++++ .../connected-platform-dialog.component.scss | 98 +++++++++++++++++ .../connected-platform-dialog.component.ts | 70 +++++++++++++ .../connected-platforms-routing.module.ts} | 21 ++-- .../connected-platforms.component.html | 96 +++++++++++++++++ .../connected-platforms.component.scss | 99 ++++++++++++++++++ .../connected-platforms.component.ts | 114 ++++++++++++++++++++ .../connected-platforms.config.ts} | 30 +++--- .../connected-platforms.models.ts} | 24 +++-- .../connected-platforms.module.ts | 53 ++++++++++ .../connected-platforms.service.ts | 61 +++++++++++ .../warning-dialog/warning-dialog.component.html} | 21 ++-- .../warning-dialog/warning-dialog.component.scss} | 26 +++-- .../warning-dialog/warning-dialog.component.ts | 49 +++++++++ .../access-denied/access-denied.component.ts | 10 +- .../not-found/not-found.component.html | 4 +- .../service-pages/not-found/not-found.component.ts | 5 +- .../src/app/service-pages/service-pages.module.ts | 5 +- .../modal-btn/modal-btn.component.html} | 27 ++--- .../modal-btn/modal-btn.component.scss} | 16 +-- .../modal-parts/modal-btn/modal-btn.component.ts} | 20 +++- .../modal-header/modal-header.component.html} | 20 ++-- .../modal-header/modal-header.component.scss} | 35 ++++--- .../modal-header/modal-header.component.ts} | 21 ++-- .../modal-parts/modal-parts.module.ts} | 24 +++-- .../src/app/shared/navbar/navbar.component.html | 116 ++++++++++++--------- .../src/app/shared/navbar/navbar.component.ts | 31 +++--- .../webapp/src/app/shared/navbar/navbar.config.ts | 22 ++-- 37 files changed, 1165 insertions(+), 267 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts index 56ce00ff7..14b5b15f2 100644 --- a/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts +++ b/services/self-service/src/main/resources/webapp/src/app/administration/management/management.model.ts @@ -85,8 +85,14 @@ export interface GeneralEnvironmentStatus { status: string; projectAssigned: boolean; bucketBrowser: object; + connectedPlatforms: ConnectedPlatformsStatus; } +export interface ConnectedPlatformsStatus { + add: boolean; + disconnect: boolean; + view: boolean; +} export class ManagementConfigModel { @@ -117,8 +123,8 @@ export class ManagementConfigModel { export interface ModalData { action: ActionsType; - resource_name?: any; - user?: any, + resource_name?: any; + user?: any, type: string; notebooks?: any } @@ -134,4 +140,4 @@ export enum ActionsType { start = 'start', run = 'run', recreate = 'recreate' -} \ No newline at end of file +} diff --git a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts index d166b7d40..3ff739602 100644 --- a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts @@ -37,12 +37,13 @@ import {ProjectAdminGuard} from './core/services/projectAdmin.guard'; import {ReportingComponent} from './reports/reporting/reporting.component'; import {OdahuComponent} from './administration/odahu/odahu.component'; import {AuditComponent} from './reports/audit/audit.component'; +import { RoutingListConfig } from './core/configs/routing-list.config'; const routes: Routes = [ { - path: 'login', + path: RoutingListConfig.login, component: LoginComponent - }, + }, { path: '', canActivate: [CheckParamsGuard], @@ -50,77 +51,81 @@ const routes: Routes = [ children: [ { path: '', - redirectTo: 'resources_list', + redirectTo: RoutingListConfig.instances, pathMatch: 'full' - }, + }, { - path: 'resources_list', + path: RoutingListConfig.instances, component: ResourcesComponent, canActivate: [AuthorizationGuard] - }, + }, { - path: 'billing_report', + path: RoutingListConfig.connectedPlatforms, + loadChildren: () => import('./resources/connected-platforms/connected-platforms.module').then(m => m.ConnectedPlatformsModule) + }, + { + path: RoutingListConfig.billing, component: ReportingComponent, canActivate: [AuthorizationGuard, CloudProviderGuard] - }, + }, { - path: 'projects', + path: RoutingListConfig.projects, component: ProjectComponent, canActivate: [AuthorizationGuard, AdminGuard], }, { - // path: 'odahu', - // component: OdahuComponent, - // canActivate: [AuthorizationGuard, AdminGuard], - // }, { - path: 'roles', + // path: 'odahu', + // component: OdahuComponent, + // canActivate: [AuthorizationGuard, AdminGuard], + // }, { + path: RoutingListConfig.users, component: RolesComponent, canActivate: [AuthorizationGuard, AdminGuard], - }, + }, { - path: 'environment_management', + path: RoutingListConfig.resources, component: ManagementComponent, canActivate: [AuthorizationGuard, AdminGuard] - }, + }, { - path: 'configuration', + path: RoutingListConfig.configuration, component: ConfigurationComponent, canActivate: [AuthorizationGuard, AdminGuard, ProjectAdminGuard] }, { - path: 'swagger', + path: RoutingListConfig.swagger, component: SwaggerComponent, canActivate: [AuthorizationGuard] - }, + }, { - path: 'help/publickeyguide', + path: RoutingListConfig.publickeyguide, component: PublicKeyGuideComponent, canActivate: [AuthorizationGuard] - }, + }, { - path: 'help/accessnotebookguide', + path: RoutingListConfig.accessnotebookguide, component: AccessNotebookGuideComponent, canActivate: [AuthorizationGuard] }, { - path: 'audit', + path: RoutingListConfig.audit, component: AuditComponent, canActivate: [AuthorizationGuard, AuditGuard], }, ] - }, + }, { path: 'terminal/:id/:endpoint', component: WebterminalComponent - }, + }, { path: '403', component: AccessDeniedComponent, canActivate: [AuthorizationGuard] - }, + }, { - path: '**', - component: NotFoundComponent + path: '**', + component: NotFoundComponent } ]; diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/core/configs/connected-platforms.model.ts similarity index 77% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/core/configs/connected-platforms.model.ts index 34f860f16..2344ed14a 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/configs/connected-platforms.model.ts @@ -17,11 +17,14 @@ * under the License. */ -import { Component } from '@angular/core'; +export enum ModalTitle { + share = 'Share image', + terminate = 'Terminate image', + unShare = '! Warning', + addPlatform = 'Add platform' +} -@Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] -}) -export class NotFoundComponent { } +export enum URL_Chunk { + sharingInfo = 'sharing_info', + autocomplete = 'share_autocomplete' +} diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts b/services/self-service/src/main/resources/webapp/src/app/core/configs/routing-list.config.ts similarity index 66% copy from services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts copy to services/self-service/src/main/resources/webapp/src/app/core/configs/routing-list.config.ts index 38df6d2c5..171f80c4e 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/configs/routing-list.config.ts @@ -17,19 +17,18 @@ * under the License. */ -export const sideBarNamesConfig: Record<string, string> = { - resourses: 'Resources', - reports: 'Reports', - audit: 'Audit', - billing: 'Billing', - administration: 'Administration', - users: 'Users', - projects: 'Projects', - resources: 'Resources', - configuration: 'Configuration' -} - -export interface UserInfo { - email: string; - name: string; +export enum RoutingListConfig { + instances = 'instances', + images = 'images', + connectedPlatforms = 'connected-platforms', + login = 'login', + billing = 'billing', + projects = 'projects', + users = 'users', + resources = 'resources', + audit = 'audit', + configuration = 'configuration', + swagger = 'swagger', + publickeyguide = 'help/publickeyguide', + accessnotebookguide = 'help/accessnotebookguide', } diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts b/services/self-service/src/main/resources/webapp/src/app/core/pipes/normalize-link/index.ts similarity index 73% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts copy to services/self-service/src/main/resources/webapp/src/app/core/pipes/normalize-link/index.ts index f3da2fe6f..18c71d973 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/pipes/normalize-link/index.ts @@ -19,12 +19,12 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { NotFoundComponent } from './not-found/not-found.component'; -import { AccessDeniedComponent } from './access-denied/access-denied.component'; +import { NormalizeLinkPipe } from './normalize-link.pipe'; @NgModule({ - imports: [CommonModule], - declarations: [NotFoundComponent, AccessDeniedComponent], - exports: [NotFoundComponent, AccessDeniedComponent] + imports: [ CommonModule ], + declarations: [ NormalizeLinkPipe ], + exports: [ NormalizeLinkPipe ] }) -export class ServicePagesModule { } \ No newline at end of file + +export class NormalizeLinkPipeModule { } diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/core/pipes/normalize-link/normalize-link.pipe.ts similarity index 76% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/core/pipes/normalize-link/normalize-link.pipe.ts index 34f860f16..ecbd3efcf 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/pipes/normalize-link/normalize-link.pipe.ts @@ -17,11 +17,13 @@ * under the License. */ -import { Component } from '@angular/core'; +import { Pipe, PipeTransform } from '@angular/core'; -@Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] +@Pipe({ + name: 'normalizeLink' }) -export class NotFoundComponent { } +export class NormalizeLinkPipe implements PipeTransform { + transform(value: string): string { + return value.includes('http') ? value : `//${value}`; + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/appRouting.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/appRouting.service.ts index 1a8075973..4eac9090f 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/services/appRouting.service.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/appRouting.service.ts @@ -19,6 +19,7 @@ import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; +import { RoutingListConfig } from '../configs/routing-list.config'; @Injectable() export class AppRoutingService { @@ -34,7 +35,7 @@ export class AppRoutingService { } redirectToHomePage(): void { - this.router.navigate(['/resources_list']); + this.router.navigate(['/', RoutingListConfig.instances]); } redirectToHealthStatusPage(): void { diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts index 3bb326d3e..e7218bc45 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts @@ -24,6 +24,7 @@ import { HttpClient } from '@angular/common/http'; import { Dictionary } from '../collections'; import { environment } from '../../../environments/environment'; import { HTTPMethod } from '../util'; +import { AddPlatformFromValue } from '../../resources/connected-platforms/connected-platforms.models'; // we can now access environment.apiUrl const API_URL = environment.apiUrl; @@ -81,6 +82,7 @@ export class ApplicationServiceFacade { private static readonly AUDIT = 'audit'; private static readonly CONFIG = 'config'; private static readonly QUOTA = 'quota'; + private static readonly CONNECTED_PLATFORMS = 'connected_platforms'; private requestRegistry: Dictionary<string>; @@ -180,6 +182,28 @@ export class ApplicationServiceFacade { null); } + buildGetConnectedPlatformsPage(): Observable<any> { + console.log(`${this.requestRegistry.Item(ApplicationServiceFacade.CONNECTED_PLATFORMS)}/user`); + return this.buildRequest(HTTPMethod.GET, + `${this.requestRegistry.Item(ApplicationServiceFacade.CONNECTED_PLATFORMS)}/user`, + null + ); + } + + buildAddPlatform(platformParams: AddPlatformFromValue): Observable<any> { + return this.buildRequest(HTTPMethod.POST, + this.requestRegistry.Item(ApplicationServiceFacade.CONNECTED_PLATFORMS), + platformParams + ); + } + + buildDisconnectPlatform(platformName: string): Observable<any> { + return this.buildRequest(HTTPMethod.DELETE, + `${this.requestRegistry.Item(ApplicationServiceFacade.CONNECTED_PLATFORMS)}/${platformName}`, + null + ); + } + public buildGetTemplatesRequest(params): Observable<any> { return this.buildRequest(HTTPMethod.GET, this.requestRegistry.Item(ApplicationServiceFacade.TEMPLATES) + params, @@ -725,6 +749,10 @@ export class ApplicationServiceFacade { this.requestRegistry.Add(ApplicationServiceFacade.SCHEDULER, '/api/infrastructure_provision/exploratory_environment/scheduler'); + // Connected Platforms + this.requestRegistry.Add(ApplicationServiceFacade.CONNECTED_PLATFORMS, + '/api/connected_platforms'); + // Computational Resources this.requestRegistry.Add(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES, '/infrastructure_provision/computational_resources'); @@ -805,4 +833,4 @@ export class ApplicationServiceFacade { return this.http.get(body ? (url + body) : url, opt); } } -} \ No newline at end of file +} diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/connected-platform-api.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/connected-platform-api.service.ts new file mode 100644 index 000000000..bd7153080 --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/connected-platform-api.service.ts @@ -0,0 +1,54 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Injectable } from '@angular/core'; +import { ApplicationServiceFacade } from './applicationServiceFacade.service'; +import { catchError } from 'rxjs/operators'; +import { ErrorUtils } from '../util'; +import { Observable } from 'rxjs'; +import { AddPlatformFromValue, ConnectedPlatformsInfo } from '../../resources/connected-platforms/connected-platforms.models'; + +@Injectable({ + providedIn: 'root' +}) +export class ConnectedPlatformApiService { + + constructor( + private applicationServiceFacade: ApplicationServiceFacade + ) { } + + getConnectedPlatformsPage(): Observable<ConnectedPlatformsInfo> { + return this.applicationServiceFacade.buildGetConnectedPlatformsPage() + .pipe( + catchError(ErrorUtils.handleServiceError) + ); + } + + addPlatform(platformParams: AddPlatformFromValue) { + return this.applicationServiceFacade.buildAddPlatform(platformParams).pipe( + catchError(ErrorUtils.handleServiceError) + ); + } + + disconnectPlatform(platformName: string) { + return this.applicationServiceFacade.buildDisconnectPlatform(platformName).pipe( + catchError(ErrorUtils.handleServiceError) + ); + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.html new file mode 100644 index 000000000..9540c721f --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.html @@ -0,0 +1,80 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> + + <div id="dialog-box" class="dialog__wrapper"> + <header class="dialog-header"> + <h4 class="modal-title"> + {{modalTitle.addPlatform}} + </h4> + <button type="button" class="close" (click)="dialogRef.close()">×</button> + </header> + <div class="dialog-content"> + <form [formGroup]="connectedPlatformForm"> + <div class="control__wrapper"> + <label>Select platform</label> + <mat-form-field class="select__wrapper" appearance="fill"> + <mat-select placeholder="Select platform" name="platformType" formControlName="type"> + <mat-option *ngIf="!data.types.length" disabled="true"> + No platforms to add + </mat-option><mat-option *ngFor="let type of data.types" [value]="type"> + {{type}} + </mat-option> + </mat-select> + <button class="caret"> + <i class="material-icons">keyboard_arrow_down</i> + </button> + </mat-form-field> + </div> + + <div class="control__wrapper"> + <label>Platform url</label> + <div class="input__wrapper"> + <input placeholder="Platform url" type="text" formControlName="url"> + <span + class="error" + *ngIf="!connectedPlatformForm?.controls.url.valid + && connectedPlatformForm.controls.url.touched" + > + Please provide a valid platform url. + </span> + </div> + </div> + + <div class="control__wrapper"> + <label>Name</label> + <div class="input__wrapper"> + <input placeholder="Enter name" type="text" formControlName="name"> + <span + class="error" + *ngIf="!connectedPlatformForm?.controls.name.valid && connectedPlatformForm.controls.name.touched" + > + Platform name cannot be longer than 6 characters. + </span> + </div> + </div> + <div class="button__wrapper"> + <datalab-modal-btn + [isConfirmBtnDisabled]="!isFormValid" + [confirmBtnName]="confirmButtonName.add" + (closeEvent)="onBtnClick($event)" + ></datalab-modal-btn> + </div> + </form> + </div> + </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.scss new file mode 100644 index 000000000..0becd0d19 --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.scss @@ -0,0 +1,98 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.dialog-content { + padding: 25px 30px; +} + +.control__wrapper { + display: flex; + justify-content: space-between; + align-items: baseline; + height: 56px; +} + +.select__wrapper { + position: relative; + width: 320px; + height: 36px; + + & ::ng-deep .mat-form-field-wrapper { + padding: 0; + } + + &.mat-form-field .mat-form-field-flex { + background-color: red !important; + } + + & ::ng-deep .mat-form-field-appearance-fill .mat-form-field-flex { + padding: 0; + } + + & ::ng-deep .mat-form-field-infix { + border-top: none; + } + + & ::ng-deep .mat-form-field-underline::before { + height: 0; + } + + & ::ng-deep .mat-form-field-ripple { + display: none; + } + + & ::ng-deep .mat-select-arrow { + border: none; + + } + + ::ng-deep .mat-select-placeholder { + font-size: 15px; + } +} + +.caret { + position: absolute; + top: -9px; + right: -11px; + width: 40px; + height: 40px; + color: #35afd5; + background-color: transparent; + border: none; + border-left: 1px solid #ececec; + outline: none; + cursor: pointer; +} + +::ng-deep { + .mat-form-field .mat-form-field-flex{ + background-color: white; + box-shadow: 0px 3px 1px -2px rgb(0 0 0 / 20%), 0px 2px 2px 0px rgb(0 0 0 / 14%), 0px 1px 5px 0px rgb(0 0 0 / 12%); + } +} + +.input__wrapper { + width: 320px; + height: 56px; +} + +.button__wrapper { + padding-top: 20px; +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.ts new file mode 100644 index 000000000..bf9f96e2e --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platform-dialog/connected-platform-dialog.component.ts @@ -0,0 +1,70 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Component, Inject, OnInit } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AddModalData, AddPlatformFromValue } from '../connected-platforms.models'; +import { ConfirmButtonNames } from '../connected-platforms.config'; +import { PATTERNS } from '../../../core/util'; +import { ModalTitle } from '../../../core/configs/connected-platforms.model'; + +const URL_REGEXP_VALIDATION_STRING = '^(http(s)?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]'; + +@Component({ + selector: 'datalab-connected-platform-dialog', + templateUrl: './connected-platform-dialog.component.html', + styleUrls: ['./connected-platform-dialog.component.scss'] +}) +export class ConnectedPlatformDialogComponent implements OnInit { + readonly modalTitle: typeof ModalTitle = ModalTitle; + readonly confirmButtonName: typeof ConfirmButtonNames = ConfirmButtonNames; + + connectedPlatformForm!: FormGroup; + + constructor( + public dialogRef: MatDialogRef<ConnectedPlatformDialogComponent>, + private fb: FormBuilder, + @Inject(MAT_DIALOG_DATA) public data: AddModalData + ) { } + + ngOnInit(): void { + this.initForm(); + } + + onBtnClick(flag: boolean): void { + let responseObj: AddPlatformFromValue; + if (flag) { + responseObj = this.connectedPlatformForm.value; + } + this.dialogRef.close(responseObj); + } + + private initForm(): void { + this.connectedPlatformForm = this.fb.group({ + type: ['', Validators.required], + url: ['', [ Validators.required, Validators.pattern(URL_REGEXP_VALIDATION_STRING)]], + name: ['', [ Validators.required, Validators.pattern(PATTERNS.projectName), Validators.minLength(2)]] + }); + } + + get isFormValid(): boolean { + return this.connectedPlatformForm.valid; + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms-routing.module.ts similarity index 69% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts copy to services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms-routing.module.ts index f3da2fe6f..61d93807f 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms-routing.module.ts @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,13 +18,18 @@ */ import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { NotFoundComponent } from './not-found/not-found.component'; -import { AccessDeniedComponent } from './access-denied/access-denied.component'; +import { RouterModule, Routes } from '@angular/router'; +import { ConnectedPlatformsComponent } from './connected-platforms.component'; + +const routes: Routes = [ + { + path: '', + component: ConnectedPlatformsComponent + } +]; @NgModule({ - imports: [CommonModule], - declarations: [NotFoundComponent, AccessDeniedComponent], - exports: [NotFoundComponent, AccessDeniedComponent] + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] }) -export class ServicePagesModule { } \ No newline at end of file +export class ConnectedPlatformsRoutingModule { } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.html new file mode 100644 index 000000000..08acd3619 --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.html @@ -0,0 +1,96 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> + +<section class="connected-platforms__wrapper base-retreat"> + <nav class="sub-nav"> + <button + *ngIf="(connectedPlatformsStatus$ | async)?.add" + (click)="onAddNew()" + mat-raised-button + class="butt butt-create" + > + <i class="material-icons">add</i>Add new + </button> + </nav> + + <mat-divider></mat-divider> + + <table mat-table [dataSource]="(platformPageData$ | async).userPlatforms" class="mat-elevation-z8 table"> + + <ng-container matColumnDef="platformName"> + <th mat-header-cell *matHeaderCellDef>{{tableHeaderCellTitles.platformName}}</th> + <td mat-cell class="column" *matCellDef="let element"> {{element.name}} </td> + </ng-container> + + <ng-container matColumnDef="linkToPlatform"> + <th mat-header-cell *matHeaderCellDef>{{tableHeaderCellTitles.linkToPlatform}}</th> + <td class="column" mat-cell *matCellDef="let element"> + <a + class="link" + [href]="element.url | normalizeLink" + target="_blank" + [matTooltip]="element.url" + matTooltipPosition="above" + [matTooltipDisabled]="element.url.length < maxUrlLength" + > + {{element.url | truncateTextPipe : maxUrlLength}} + </a> + </td> + </ng-container> + + <ng-container matColumnDef="actions"> + <th + mat-header-cell + [ngClass]="{'hided-table-title': !(connectedPlatformsStatus$ | async)?.disconnect}" + *matHeaderCellDef + > + {{tableHeaderCellTitles.actions}} + </th> + <td mat-cell class="action-cell" *matCellDef="let element"> + <span class="actions-menu" + #settings + (click)="actions.toggle($event, settings)"> + <img + *ngIf="(connectedPlatformsStatus$ | async)?.disconnect" + class="action-icon" + [src]="'assets/svg/settings_icon.svg'" + alt="setting-icon" + > + </span> + <bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left"> + <ul class="list-unstyled"> + <li> + <button + class="action-button__disconnect" + (click)="onPlatformDisconnect(element)" + > + <i class="material-icons icon">cast</i> + <span>Disconnect</span> + </button> + </li> + </ul> + </bubble-up> + </td> + </ng-container> + + <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> + <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> + </table> + +</section> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.scss new file mode 100644 index 000000000..7dd04357d --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.scss @@ -0,0 +1,99 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.table { + width: 100%; +} + +.column { + width: 20%; +} + +.action-icon, +.link { + cursor: pointer; +} + +.link { + text-decoration: underline; +} + +.hided-table-title { + color: transparent; +} + +.table-cell { + position: relative; +} + +.list-menu { + left: auto; + top: 30px !important; + width: 190px; + max-height: calc(100vh / 2 - 70px); + margin-left: 0; + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12); + border: none; +} + +.actions-menu { + position: relative; + width: 190px; +} + +.action-button__disconnect { + display: flex; + align-items: center; + width: 100%; + padding: 10px 15px; + background-color: transparent; + color: rgb(87, 114, 137); + border: none; + outline: none; + + &:hover { + color: #35afd5; + cursor: pointer; + + & ::before { + background-color: #35afd5; + } + } +} + +.action-cell { + position: relative; +} + +.icon { + position: relative; + margin-right: 10px; + + &::before { + position: absolute; + top: 11px; + left: -4px; + width: 32px; + height: 1px; + rotate: 40deg; + content: ''; + background-color: #577289; + transform: rotateX(1deg); + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.ts new file mode 100644 index 000000000..b49dbc545 --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.component.ts @@ -0,0 +1,114 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Component, OnInit } from '@angular/core'; +import { BehaviorSubject, EMPTY, Observable, pipe } from 'rxjs'; +import { switchMap, take, tap } from 'rxjs/operators'; +import { MatDialog } from '@angular/material/dialog'; +import { ToastrService } from 'ngx-toastr'; + +import { ConnectedPlatformsStatus, GeneralEnvironmentStatus } from '../../administration/management/management.model'; +import { HealthStatusService } from '../../core/services'; +import { ConnectedPlatformsTableTitles, ConnectedPlatformDisplayedColumns } from './connected-platforms.config'; +import { ConnectedPlatformDialogComponent } from './connected-platform-dialog/connected-platform-dialog.component'; +import { ConnectedPlatformsInfo, Platform } from './connected-platforms.models'; +import { ConnectedPlatformsService } from './connected-platforms.service'; +import { WarningDialogComponent } from './warning-dialog/warning-dialog.component'; + +@Component({ + selector: 'datalab-connected-platforms', + templateUrl: './connected-platforms.component.html', + styleUrls: ['./connected-platforms.component.scss'] +}) +export class ConnectedPlatformsComponent implements OnInit { + readonly tableHeaderCellTitles: typeof ConnectedPlatformsTableTitles = ConnectedPlatformsTableTitles; + readonly maxUrlLength: number = 30; + + // tslint:disable-next-line:max-line-length + private readonly connectedPlatformsStatus$$: BehaviorSubject<ConnectedPlatformsStatus> = new BehaviorSubject<ConnectedPlatformsStatus>({} as ConnectedPlatformsStatus); + readonly connectedPlatformsStatus$: Observable<ConnectedPlatformsStatus> = this.connectedPlatformsStatus$$.asObservable(); + + platformPageData$: Observable<ConnectedPlatformsInfo>; + + displayedColumns: typeof ConnectedPlatformDisplayedColumns = ConnectedPlatformDisplayedColumns; + + constructor( + private healthStatusService: HealthStatusService, + public toastr: ToastrService, + private dialog: MatDialog, + private connectedPlatformsService: ConnectedPlatformsService + ) { } + + ngOnInit(): void { + this.getEnvironmentHealthStatus(); + this.getConnectedPlatformPageInfo(); + this.initPageData(); + } + + onAddNew(): void { + this.dialog.open(ConnectedPlatformDialogComponent, { + data: this.connectedPlatformsService.addModalData, + panelClass: 'modal-lg' + }) + .afterClosed() + .pipe( + this.getModalAction(this.connectedPlatformsService.addPlatform), + ).subscribe(); + } + + onPlatformDisconnect({name}: Platform): void { + this.dialog.open(WarningDialogComponent, + { + data: name, + panelClass: 'modal-sm' + }) + .afterClosed() + .pipe( + this.getModalAction(this.connectedPlatformsService.disconnectPlatform) + ).subscribe(); + } + + private getModalAction(callback: Function) { + callback = callback.bind(this.connectedPlatformsService); + return pipe( + switchMap((arg) => { + if (arg) { + return callback(arg); + } + return EMPTY; + }), + switchMap(() => this.connectedPlatformsService.getConnectedPlatformPageInfo()) + ); + } + + private getEnvironmentHealthStatus(): void { + this.healthStatusService.getEnvironmentHealthStatus().pipe( + tap((response: GeneralEnvironmentStatus) => this.connectedPlatformsStatus$$.next(response.connectedPlatforms)), + take(1) + ).subscribe(); + } + + private getConnectedPlatformPageInfo(): void { + this.connectedPlatformsService.getConnectedPlatformPageInfo().subscribe(); + } + + private initPageData(): void { + this.platformPageData$ = this.connectedPlatformsService.platformPageData$; + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.config.ts similarity index 68% copy from services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts copy to services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.config.ts index 38df6d2c5..708ff528e 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.config.ts @@ -17,19 +17,23 @@ * under the License. */ -export const sideBarNamesConfig: Record<string, string> = { - resourses: 'Resources', - reports: 'Reports', - audit: 'Audit', - billing: 'Billing', - administration: 'Administration', - users: 'Users', - projects: 'Projects', - resources: 'Resources', - configuration: 'Configuration' +export enum ConnectedPlatformsTableTitles { + platformName = 'Platform name', + linkToPlatform = 'Link to platform', + actions = 'Actions' } -export interface UserInfo { - email: string; - name: string; +export const ConnectedPlatformDisplayedColumns = [ + 'platformName', + 'linkToPlatform', + 'actions', +]; + +export enum ModalTitles { + disconnect= 'Disconnect platform' +} + +export enum ConfirmButtonNames { + yes = 'Yes', + add = 'Add' } diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.models.ts similarity index 69% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.models.ts index 34f860f16..d51487953 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.models.ts @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,11 +17,19 @@ * under the License. */ -import { Component } from '@angular/core'; +export interface ConnectedPlatformsInfo { + userPlatforms: Platform[]; + types: string[]; + platformNames: string[]; +} -@Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] -}) -export class NotFoundComponent { } +export interface Platform { + name: string; + type: string; + user: string; + url: string; +} + +export type AddModalData = Omit<ConnectedPlatformsInfo, 'userPlatforms'>; + +export type AddPlatformFromValue = Omit<Platform, 'user'>; diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.module.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.module.ts new file mode 100644 index 000000000..1a653e50b --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.module.ts @@ -0,0 +1,53 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { ConnectedPlatformsRoutingModule } from './connected-platforms-routing.module'; +import { ConnectedPlatformsComponent } from './connected-platforms.component'; +import { MaterialModule } from '../../shared/material.module'; +import { BubbleModule } from '../../shared'; +import { ReactiveFormsModule } from '@angular/forms'; +import { TruncateTextPipeModule } from '../../core/pipes/truncate-text-pipe'; +import { ModalPartsModule } from '../../shared/modal-parts/modal-parts.module'; +import { WarningDialogComponent } from './warning-dialog/warning-dialog.component'; +import { ConnectedPlatformDialogComponent } from './connected-platform-dialog/connected-platform-dialog.component'; +import { NormalizeLinkPipeModule } from '../../core/pipes/normalize-link'; + + +@NgModule({ + declarations: [ + ConnectedPlatformsComponent, + WarningDialogComponent, + ConnectedPlatformDialogComponent + ], + imports: [ + CommonModule, + MaterialModule, + NormalizeLinkPipeModule, + ConnectedPlatformsRoutingModule, + BubbleModule, + ModalPartsModule, + ReactiveFormsModule, + TruncateTextPipeModule + ], + entryComponents: [ ConnectedPlatformDialogComponent, WarningDialogComponent ] +}) +export class ConnectedPlatformsModule { } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.service.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.service.ts new file mode 100644 index 000000000..14eea05b6 --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/connected-platforms.service.ts @@ -0,0 +1,61 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Injectable } from '@angular/core'; +import { ConnectedPlatformApiService } from '../../core/services/connected-platform-api.service'; +import { tap } from 'rxjs/operators'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { AddModalData, AddPlatformFromValue, ConnectedPlatformsInfo } from './connected-platforms.models'; + +@Injectable({ + providedIn: 'root' +}) +export class ConnectedPlatformsService { + // tslint:disable-next-line:max-line-length + private platformPageData$$: BehaviorSubject<ConnectedPlatformsInfo> = new BehaviorSubject<ConnectedPlatformsInfo>({} as ConnectedPlatformsInfo); + platformPageData$: Observable<ConnectedPlatformsInfo> = this.platformPageData$$.asObservable(); + addModalData: AddModalData; + + constructor( + private connectedPlatformPageService: ConnectedPlatformApiService + ) { } + + getConnectedPlatformPageInfo(): Observable<ConnectedPlatformsInfo> { + console.log(1); + return this.connectedPlatformPageService.getConnectedPlatformsPage() + .pipe( + tap(res => console.log(res)), + tap( result => this.platformPageData$$.next(result)), + tap( result => this.getAddModalData(result)), + ); + } + + addPlatform(platformParams: AddPlatformFromValue): Observable<any> { + return this.connectedPlatformPageService.addPlatform(platformParams); + } + + disconnectPlatform(platformName: string): Observable<any> { + return this.connectedPlatformPageService.disconnectPlatform(platformName); + } + + private getAddModalData(info: ConnectedPlatformsInfo): void { + const { platformNames, types } = info; + this.addModalData = { platformNames, types }; + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.html similarity index 67% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html copy to services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.html index 2eb5e74b3..32d382c05 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.html @@ -17,17 +17,12 @@ ~ under the License. --> -<div class="not-found-page"> - <div class="content"> - <a class="logo" href="#/resources_list"> - <img src="assets/svg/not_found_page.svg" alt=""> - </a> - - <div class="message-block"> - <h3>Whooops... Page Not Found!</h3> - <p>We couldn't seem to found the page you are looking for. - <a href="#/resources_list">Go to the Homepage?</a> - </p> - </div> - </div> +<datalab-modal-header (close)="onClose()" [modalTitle]="title.disconnect"></datalab-modal-header> +<div class="dialog-content"> + <p class="content red">The <span class="platform-name">{{data}}</span> will be disconnected from this account.</p> + <datalab-modal-btn + [needAdditionalQuestion]="true" + (closeEvent)="onBtnClick($event)" + [confirmBtnName]="confirmButtonName.yes" + ></datalab-modal-btn> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.scss similarity index 79% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.scss index 34f860f16..310d4b09f 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.scss @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,11 +17,21 @@ * under the License. */ -import { Component } from '@angular/core'; +.dialog-content { + padding: 25px 30px; +} -@Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] -}) -export class NotFoundComponent { } +.red { + color: red; +} + +.content { + margin-bottom: 50px; + padding-top: 20px; + text-align: center; + font-weight: 400; +} + +.platform-name { + font-weight: 700; +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.ts new file mode 100644 index 000000000..f30f0d3be --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/connected-platforms/warning-dialog/warning-dialog.component.ts @@ -0,0 +1,49 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { ConfirmButtonNames, ModalTitles } from '../connected-platforms.config'; + +@Component({ + selector: 'datalab-warning-dialog', + templateUrl: './warning-dialog.component.html', + styleUrls: ['./warning-dialog.component.scss'] +}) +export class WarningDialogComponent { + readonly title: typeof ModalTitles = ModalTitles; + readonly confirmButtonName: typeof ConfirmButtonNames = ConfirmButtonNames; + + constructor( + public dialogRef: MatDialogRef<WarningDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: string + ) { } + + onClose(): void { + this.dialogRef.close(); + } + + onBtnClick(isConfirm: boolean): void { + let platformName; + if (isConfirm) { + platformName = this.data; + } + this.dialogRef.close(platformName); + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/access-denied/access-denied.component.ts b/services/self-service/src/main/resources/webapp/src/app/service-pages/access-denied/access-denied.component.ts index cb290ec3c..b0075cac8 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/access-denied/access-denied.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/service-pages/access-denied/access-denied.component.ts @@ -17,20 +17,21 @@ * under the License. */ import { Component, OnInit } from '@angular/core'; +import { RoutingListConfig } from '../../core/configs/routing-list.config'; @Component({ selector: 'datalab-access-denied', template: ` <div class="no-access-page"> <div class="content"> - <a class="logo" href="#/resources_list"> + <a class="logo" [routerLink]="['/', routerList.instances]"> <img src="assets/img/security-screen.png" alt=""> </a> <div class="message-block"> <h3>Access Denied!</h3> <p>The page you were trying to reach has restricted access. - <a href="#/resources_list">Go to the Homepage?</a> + <a [routerLink]="['/', routerList.instances]">Go to the Homepage?</a> </p> </div> </div> @@ -38,7 +39,6 @@ import { Component, OnInit } from '@angular/core'; `, styleUrls: ['./access-denied.component.scss'] }) -export class AccessDeniedComponent implements OnInit { - constructor() { } - ngOnInit() { } +export class AccessDeniedComponent { + readonly routerList: typeof RoutingListConfig = RoutingListConfig; } diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html b/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html index 2eb5e74b3..8dada3ee9 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html @@ -19,14 +19,14 @@ <div class="not-found-page"> <div class="content"> - <a class="logo" href="#/resources_list"> + <a class="logo" [routerLink]="['/', routerList.instances]"> <img src="assets/svg/not_found_page.svg" alt=""> </a> <div class="message-block"> <h3>Whooops... Page Not Found!</h3> <p>We couldn't seem to found the page you are looking for. - <a href="#/resources_list">Go to the Homepage?</a> + <a [routerLink]="['/', routerList.instances]">Go to the Homepage?</a> </p> </div> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts index 34f860f16..08b17cd32 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts @@ -18,10 +18,13 @@ */ import { Component } from '@angular/core'; +import { RoutingListConfig } from '../../core/configs/routing-list.config'; @Component({ selector: 'not-found', templateUrl: 'not-found.component.html', styleUrls: ['not-found.component.scss'] }) -export class NotFoundComponent { } +export class NotFoundComponent { + readonly routerList: typeof RoutingListConfig = RoutingListConfig; +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts b/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts index f3da2fe6f..268bf75e4 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts @@ -21,10 +21,11 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NotFoundComponent } from './not-found/not-found.component'; import { AccessDeniedComponent } from './access-denied/access-denied.component'; +import { RouterModule } from '@angular/router'; @NgModule({ - imports: [CommonModule], + imports: [CommonModule, RouterModule], declarations: [NotFoundComponent, AccessDeniedComponent], exports: [NotFoundComponent, AccessDeniedComponent] }) -export class ServicePagesModule { } \ No newline at end of file +export class ServicePagesModule { } diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.html similarity index 66% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.html index 2eb5e74b3..0a5089c4b 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.html @@ -16,18 +16,19 @@ ~ specific language governing permissions and limitations ~ under the License. --> - -<div class="not-found-page"> - <div class="content"> - <a class="logo" href="#/resources_list"> - <img src="assets/svg/not_found_page.svg" alt=""> - </a> - - <div class="message-block"> - <h3>Whooops... Page Not Found!</h3> - <p>We couldn't seem to found the page you are looking for. - <a href="#/resources_list">Go to the Homepage?</a> - </p> - </div> +<div class="component__wrapper"> + <p *ngIf="needAdditionalQuestion" class="question center"> + Do you want proceed? + </p> + <div class="button__wrapper"> + <button type="button" class="butt mat-raised-button" (click)="close()">No</button> + <button + [disabled]="isConfirmBtnDisabled" + type="button" + class="butt butt-success mat-raised-button" + (click)="close(true)"> + {{confirmBtnName}} + </button> </div> </div> + diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.scss similarity index 79% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.scss index 34f860f16..d46002dc1 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.scss @@ -17,11 +17,13 @@ * under the License. */ -import { Component } from '@angular/core'; +.button__wrapper { + text-align: center; +} -@Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] -}) -export class NotFoundComponent { } +.question { + margin-bottom: 20px; + text-align: center; + color: #718ba6; + font-weight: bold; +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.ts similarity index 61% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.ts index 34f860f16..4aa51fb0c 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-btn/modal-btn.component.ts @@ -17,11 +17,21 @@ * under the License. */ -import { Component } from '@angular/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] + selector: 'datalab-modal-btn', + templateUrl: './modal-btn.component.html', + styleUrls: ['./modal-btn.component.scss'] }) -export class NotFoundComponent { } +export class ModalBtnComponent { + @Input() isConfirmBtnDisabled: boolean; + @Input() confirmBtnName: string; + @Input() needAdditionalQuestion: boolean = false; + + @Output() closeEvent: EventEmitter<boolean> = new EventEmitter<boolean>(); + + close(flag: boolean = false): void { + this.closeEvent.emit(flag); + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.html similarity index 68% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.html index 2eb5e74b3..83650e21b 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.html @@ -17,17 +17,11 @@ ~ under the License. --> -<div class="not-found-page"> - <div class="content"> - <a class="logo" href="#/resources_list"> - <img src="assets/svg/not_found_page.svg" alt=""> - </a> - - <div class="message-block"> - <h3>Whooops... Page Not Found!</h3> - <p>We couldn't seem to found the page you are looking for. - <a href="#/resources_list">Go to the Homepage?</a> - </p> - </div> - </div> +<div> + <header class="dialog-header"> + <h4 class="modal-title"> + {{modalTitle}} + </h4> + <button type="button" class="close" (click)="onClose()">×</button> + </header> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.scss similarity index 68% copy from services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.scss index 38df6d2c5..ece700481 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.scss @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,19 +17,26 @@ * under the License. */ -export const sideBarNamesConfig: Record<string, string> = { - resourses: 'Resources', - reports: 'Reports', - audit: 'Audit', - billing: 'Billing', - administration: 'Administration', - users: 'Users', - projects: 'Projects', - resources: 'Resources', - configuration: 'Configuration' +.dialog-header { + position: relative; + padding-left: 30px; + height: 50px; + background: #f6fafe; + line-height: 50px; } -export interface UserInfo { - email: string; - name: string; +.close { + position: absolute; + top: 0; + right: 0; + height: 50px; + width: 50px; + font-size: 24px; + font-weight: 300; + border: 0; + background: none; + color: #577289; + outline: none; + cursor: pointer; + transition: all 0.5s ease-in-out; } diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.ts similarity index 67% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.ts index 34f860f16..7ef9b6d62 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/not-found/not-found.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-header/modal-header.component.ts @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,11 +17,20 @@ * under the License. */ -import { Component } from '@angular/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ - selector: 'not-found', - templateUrl: 'not-found.component.html', - styleUrls: ['not-found.component.scss'] + selector: 'datalab-modal-header', + templateUrl: './modal-header.component.html', + styleUrls: ['./modal-header.component.scss'] }) -export class NotFoundComponent { } +export class ModalHeaderComponent { + @Input() modalTitle: string; + + @Output() close: EventEmitter<any> = new EventEmitter<any>(); + + onClose(): void { + this.close.emit(); + } + +} diff --git a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-parts.module.ts similarity index 72% copy from services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts copy to services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-parts.module.ts index f3da2fe6f..3559594eb 100644 --- a/services/self-service/src/main/resources/webapp/src/app/service-pages/service-pages.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/modal-parts/modal-parts.module.ts @@ -1,4 +1,4 @@ -/* +/*! * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -19,12 +19,22 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { NotFoundComponent } from './not-found/not-found.component'; -import { AccessDeniedComponent } from './access-denied/access-denied.component'; +import { ModalHeaderComponent } from './modal-header/modal-header.component'; +import { ModalBtnComponent } from './modal-btn/modal-btn.component'; + + @NgModule({ - imports: [CommonModule], - declarations: [NotFoundComponent, AccessDeniedComponent], - exports: [NotFoundComponent, AccessDeniedComponent] + declarations: [ + ModalHeaderComponent, + ModalBtnComponent + ], + imports: [ + CommonModule + ], + exports: [ + ModalBtnComponent, + ModalHeaderComponent + ] }) -export class ServicePagesModule { } \ No newline at end of file +export class ModalPartsModule { } diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html index 8c52c46f9..9ff4b3754 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.html @@ -28,7 +28,7 @@ <span class="line"></span> </button> - <a [routerLink]="['/resources_list']" class="navbar-logo"> + <a [routerLink]="[routerList.instances]" class="navbar-logo"> <img src="assets/svg/logo.svg" alt=""> </a> </div> @@ -37,11 +37,11 @@ <!-- <a *ngIf="healthStatus.status" [routerLink]="['/environment_management']" class="statusbar"> <span class="material-icons" ngClass="{{healthStatus.status || ''}}">radio_button_checked</span> </a> --> - - <a - *ngIf="metadata" - class="statusbar about-btn--wrapper" - #info + + <a + *ngIf="metadata" + class="statusbar about-btn--wrapper" + #info (click)="actions.toggle($event, info)"> <span class="about-btn">About</span> </a> @@ -72,7 +72,7 @@ <a class="help-link" href="https://github.com/apache/incubator-datalab/blob/master/USER_GUIDE.md" target="_blank">Help</a> </span> - <span + <span class="material-icons account-icon--nav-bar account-icon" #login (click)="loginInfo.toggle($event, login)"> account_circle </span> @@ -85,53 +85,71 @@ <span class="user-mail">{{userData.email}}</span> <button type="button" class="logout-btn" (click)="logout_btnClick()"> Log out from account - </button> + </button> </div> </bubble-up> </div> </div> <mat-sidenav-container class="example-container" autosize > - <mat-sidenav - #drawer - mode="side" - opened - role="navigation" - [style.width]="isExpanded ? '220px' : '60px'" - disableClose + <mat-sidenav + #drawer + mode="side" + opened + role="navigation" + [style.width]="isExpanded ? '220px' : '60px'" + disableClose *ngIf="healthStatus" > <mat-nav-list > <nav> <div> - <a - class="nav-item" - [routerLink]="['/resources_list']" - [routerLinkActive]="['active']" - [routerLinkActiveOptions]="{exact:true}" - > - <span *ngIf="isExpanded; else resources">{{sideBarNames.resourses}}</span> - <ng-template #resources><i class="material-icons">dashboard</i></ng-template> + <a class="nav-item has-children"> + <span *ngIf="isExpanded">{{sideBarNames.resources}}</span> + <a + class="sub-nav-item" + [style.margin-left.px]="isExpanded ? '30' : '0'" + [routerLink]="[routerList.instances]" + [routerLinkActive]="['active']" + [routerLinkActiveOptions]="{exact:true}" + > + <span *ngIf="isExpanded; else instances">{{sideBarNames.instances}}</span> + <ng-template #instances><i class="material-icons">laptop</i></ng-template> + </a> + + <a + *ngIf="healthStatus.connectedPlatforms?.view" + class="sub-nav-item" + [style.margin-left.px]="isExpanded ? '30' : '0'" + [routerLink]="[routerList.connectedPlatforms]" + [routerLinkActive]="['active']" + [routerLinkActiveOptions]="{exact:true}" + > + <span *ngIf="isExpanded; else connectedPlatforms">{{sideBarNames.connectedPlatforms}}</span> + <ng-template #connectedPlatforms><i class="material-icons">cast</i></ng-template> + </a> + </a> + <a class="nav-item has-children" *ngIf="healthStatus?.billingEnabled || healthStatus?.auditEnabled"> <span *ngIf="isExpanded">{{sideBarNames.reports}}</span> - <a - *ngIf="healthStatus?.auditEnabled" - class="sub-nav-item" - [routerLink]="['/audit']" + <a + *ngIf="healthStatus?.auditEnabled" + class="sub-nav-item" + [routerLink]="['/audit']" [style.margin-left.px]="isExpanded ? '30' : '0'" - [routerLinkActive]="['active']" + [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" > <span *ngIf="isExpanded; else audit">{{sideBarNames.audit}}</span> <ng-template #audit><i class="material-icons">library_books</i></ng-template> </a> - <a - *ngIf="healthStatus?.billingEnabled" - class="sub-nav-item" + <a + *ngIf="healthStatus?.billingEnabled" + class="sub-nav-item" [routerLink]="['/billing_report']" - [routerLinkActive]="['active']" - [routerLinkActiveOptions]="{exact:true}" + [routerLinkActive]="['active']" + [routerLinkActiveOptions]="{exact:true}" [style.margin-left.px]="isExpanded ? '30' : '0'" > <span *ngIf="isExpanded; else billing">{{sideBarNames.billing}}</span> @@ -141,21 +159,21 @@ <a class="nav-item has-children" *ngIf="healthStatus?.admin || healthStatus?.projectAdmin"> <span *ngIf="isExpanded">{{sideBarNames.administration}}</span> - <a - class="sub-nav-item" - [style.margin-left.px]="isExpanded ? '30' : '0'" + <a + class="sub-nav-item" + [style.margin-left.px]="isExpanded ? '30' : '0'" [routerLink]="['/roles']" - [routerLinkActive]="['active']" + [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" > <span *ngIf="isExpanded; else roles">{{sideBarNames.users}}</span> <ng-template #roles><i class="material-icons">account_box</i></ng-template> </a> - <a - class="sub-nav-item" - [style.margin-left.px]="isExpanded ? '30' : '0'" + <a + class="sub-nav-item" + [style.margin-left.px]="isExpanded ? '30' : '0'" [routerLink]="['/projects']" - [routerLinkActive]="['active']" + [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" > <span *ngIf="isExpanded; else projects">{{sideBarNames.projects}}</span> @@ -166,21 +184,21 @@ <!-- <span *ngIf="isExpanded; else odahu">Odahu deployment</span>--> <!-- <ng-template #odahu><i class="material-icons">get_app</i></ng-template>--> <!-- </a>--> - <a - class="sub-nav-item" + <a + class="sub-nav-item" [style.margin-left.px]="isExpanded ? '30' : '0'" - [routerLink]="['/environment_management']" + [routerLink]="['/environment_management']" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" > <span *ngIf="isExpanded; else env">{{sideBarNames.resources}}</span> <ng-template #env><i class="material-icons">settings</i></ng-template> </a> - <a - *ngIf="healthStatus?.admin" - class="sub-nav-item" + <a + *ngIf="healthStatus?.admin" + class="sub-nav-item" [style.margin-left.px]="isExpanded ? '30' : '0'" - [routerLink]="['/configuration']" + [routerLink]="['/configuration']" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}" > @@ -188,7 +206,7 @@ <ng-template #env><i class="material-icons">build_circle</i></ng-template> </a> </a> - + </div> <!-- <div>--> <!-- <a class="nav-item" [routerLink]="['/swagger']" [routerLinkActive]="['active']"--> diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts index b01184dc8..862f9feb5 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts @@ -23,12 +23,12 @@ import { Subscription, timer } from 'rxjs'; import { ToastrService } from 'ngx-toastr'; import { RouterOutlet } from '@angular/router'; -import { - ApplicationSecurityService, - HealthStatusService, - AppRoutingService, - SchedulerService, - StorageService +import { + ApplicationSecurityService, + HealthStatusService, + AppRoutingService, + SchedulerService, + StorageService } from '../../core/services'; import { GeneralEnvironmentStatus } from '../../administration/management/management.model'; import { NotificationDialogComponent } from '../modal-dialog/notification-dialog'; @@ -37,12 +37,13 @@ import { animate, transition, style, - query, + query, group, } from '@angular/animations'; import {skip, take} from 'rxjs/operators'; import {ProgressBarService} from '../../core/services/progress-bar.service'; -import{ sideBarNamesConfig, UserInfo } from './navbar.config' +import { Sidebar_Names_Config, UserInfo } from './navbar.config'; +import { RoutingListConfig } from '../../core/configs/routing-list.config'; interface Quota { projectQuotas: {}; @@ -85,6 +86,8 @@ export class NavbarComponent implements OnInit, OnDestroy { private readonly CHECK_ACTIVE_SCHEDULE_TIMEOUT: number = 300000; private readonly CHECK_ACTIVE_SCHEDULE_PERIOD: number = 15; + readonly routerList: typeof RoutingListConfig = RoutingListConfig; + readonly sideBarNames: typeof Sidebar_Names_Config = Sidebar_Names_Config; currentUserName: string; quotesLimit: number = 70; @@ -93,7 +96,6 @@ export class NavbarComponent implements OnInit, OnDestroy { isExpanded: boolean = true; healthStatus: GeneralEnvironmentStatus; subscriptions: Subscription = new Subscription(); - sideBarNames!: Record<string, string>; userData!: UserInfo; commitMaxLength: number = 22; @@ -109,7 +111,6 @@ export class NavbarComponent implements OnInit, OnDestroy { ) { } ngOnInit() { - this.sideBarNames = sideBarNamesConfig; this.applicationSecurityService.loggedInStatus.subscribe(response => { this.subscriptions.unsubscribe(); this.subscriptions.closed = false; @@ -197,22 +198,22 @@ export class NavbarComponent implements OnInit, OnDestroy { } else { this.storage.setBillingQuoteUsed(''); } - + if (this.dialog.openDialogs.length > 0 || this.dialog.openDialogs.length > 0) return; checkQuotaAlert && this.emitQuotes(checkQuotaAlert, params.totalQuotaUsed, exceedProjects, informProjects); }); } } - + private getUserData(): UserInfo { - const token = localStorage.getItem('JWT_TOKEN') + const token = localStorage.getItem('JWT_TOKEN'); const [_, tokenInfo] = token.split('.'); const {name, email} = JSON.parse(atob(tokenInfo)); - + return { name: name || 'Jhon Doe', email: email || 'Email not found' - } + }; } private checkAssignment(params): void { diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts index 38df6d2c5..7dfa42522 100644 --- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts +++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.config.ts @@ -17,16 +17,18 @@ * under the License. */ -export const sideBarNamesConfig: Record<string, string> = { - resourses: 'Resources', - reports: 'Reports', - audit: 'Audit', - billing: 'Billing', - administration: 'Administration', - users: 'Users', - projects: 'Projects', - resources: 'Resources', - configuration: 'Configuration' +export enum Sidebar_Names_Config { + reports = 'Reports', + audit = 'Audit', + billing = 'Billing', + administration = 'Administration', + users = 'Users', + projects = 'Projects', + resources = 'Resources', + configuration = 'Configuration', + instances = 'Instances', + images = 'Images', + connectedPlatforms = 'Connected platforms' } export interface UserInfo { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@datalab.apache.org For additional commands, e-mail: commits-h...@datalab.apache.org