You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datalab.apache.org by yt...@apache.org on 2021/08/10 07:59:14 UTC
[incubator-datalab] 04/09: [DATALAB-2347] refactored Project list
component
This is an automated email from the ASF dual-hosted git repository.
ytykhun pushed a commit to branch DATALAB-2347
in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 62374eab25f04cc30874348a1152ed4cbab7d300
Author: Yurii Tykhun <ty...@gmail.com>
AuthorDate: Fri Jul 30 18:12:36 2021 +0300
[DATALAB-2347] refactored Project list component
---
.../project-list/project-list.component.html | 193 ++++++++++-----------
.../project-list/project-list.component.scss | 68 ++++----
.../project/project-list/project-list.component.ts | 88 +++++-----
3 files changed, 176 insertions(+), 173 deletions(-)
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.html
index e407d30..27e2ba4 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.html
@@ -18,107 +18,106 @@
-->
<div class="table-wrapper scrolling">
<table mat-table [dataSource]="dataSource" class="projects-table mat-elevation-z6 selection">
- <ng-container matColumnDef="name">
- <th mat-header-cell *matHeaderCellDef class="name"> Project name </th>
- <td mat-cell *matCellDef="let element" class="name project-name"> {{element.name}} </td>
- </ng-container>
+ <ng-container matColumnDef="name">
+ <th mat-header-cell *matHeaderCellDef class="name"> Project name </th>
+ <td mat-cell *matCellDef="let element" class="name project-name"> {{element.name}} </td>
+ </ng-container>
- <ng-container matColumnDef="groups">
- <th mat-header-cell *matHeaderCellDef class="groups"> Group </th>
- <td mat-cell *matCellDef="let element" class="groups">
- <div class="mat-chip-list-wrap scrolling">
- <mat-chip-list>
- <mat-chip *ngFor="let group of element.groups"
- [matTooltip]="group"
- matTooltipPosition="above"
- class="ellipsis"
- >
- {{ group }}
- </mat-chip>
- </mat-chip-list>
- </div>
- </td>
- </ng-container>
-
- <ng-container matColumnDef="endpoints">
- <th mat-header-cell *matHeaderCellDef class="endpoints">
- <span class="label-endpoint"> Endpoint </span>
- <span class="label-endpoint-status"> Endpoint status </span>
- <span class="label-status">Edge node status </span>
- </th>
- <td mat-cell *matCellDef="let element" class="source endpoints">
- <div *ngIf="!element.endpoints?.length; else list">
- <span *ngIf="!element.endpoints.length" class="no-details">no details</span>
- </div>
- <ng-template #list>
- <div *ngFor="let endpoint of element.endpoints" class="resource-wrap">
- <div class="resource-name">
- <a class="project-endpoint-name">
- {{ endpoint.name }}
- </a>
- </div>
- <div class="resource-status">
- <span [ngClass]="{'active' : endpoint.endpointStatus === 'ACTIVE', 'failed': endpoint.endpointStatus === 'INACTIVE'}">
- {{ (endpoint.endpointStatus | titlecase) || 'N/A'}}
- </span>
- </div>
-
- <span class="status resource-status"
- [ngClass]="endpoint?.status.toLowerCase() || ''">{{ endpoint?.status.toLowerCase() }}</span>
+ <ng-container matColumnDef="groups">
+ <th mat-header-cell *matHeaderCellDef class="groups"> Group </th>
+ <td mat-cell *matCellDef="let element" class="groups">
+ <div class="mat-chip-list-wrap scrolling">
+ <mat-chip-list>
+ <mat-chip
+ *ngFor="let group of element.groups"
+ [matTooltip]="group"
+ matTooltipPosition="above"
+ class="ellipsis"
+ >
+ {{ group }}
+ </mat-chip>
+ </mat-chip-list>
</div>
- </ng-template>
- </td>
- </ng-container>
+ </td>
+ </ng-container>
- <ng-container matColumnDef="actions">
- <th mat-header-cell *matHeaderCellDef class="project-actions">
- <span class="label"> Actions </span>
- </th>
- <td mat-cell *matCellDef="let element" class="settings">
- <span #settings (click)="actions.toggle($event, settings)" class="actions"></span>
- <bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left">
- <ul class="list-unstyled actions-list">
- <div class="active-items"></div>
- <li class="project-seting-item" *ngIf="element.areStoppedNode" (click)="openEdgeDialog('start', element)">
- <i class="material-icons">play_circle_outline</i>
- <a class="action">
- Start edge node
- </a>
- </li>
- <li class="project-seting-item" *ngIf="element.areRunningNode" (click)="openEdgeDialog('stop', element )">
- <i class="material-icons">pause_circle_outline</i>
- <a class="action" >
- Stop edge node
- </a>
- </li>
- <!-- <li class="project-seting-item " *ngIf="element.areTerminatedNode" (click)="openEdgeDialog('recreate', element)">
- <i class="material-icons">refresh</i>
- <a class="action">
- Recreate edge node
- </a>
- </li> -->
- <li class="project-seting-item " *ngIf="element.areStoppedNode || element.areRunningNode" (click)="openEdgeDialog('terminate', element)">
- <i class="material-icons">phonelink_off</i>
- <a class="action">
- Terminate edge node
- </a>
- </li>
- <li class="project-seting-item" (click)="editProject(element)" *ngIf="!isProjectAdmin">
- <i class="material-icons">mode_edit</i>
- <a >
- Edit project
- </a>
- </li>
- </ul>
- </bubble-up>
- </td>
- <td class="settings">
+ <ng-container matColumnDef="endpoints">
+ <th mat-header-cell *matHeaderCellDef class="endpoints">
+ <span class="label-endpoint"> Endpoint </span>
+ <span class="label-endpoint-status"> Endpoint status </span>
+ <span class="label-status">Edge node status </span>
+ </th>
+ <td mat-cell *matCellDef="let element" class="source endpoints">
+ <div *ngIf="!element.endpoints?.length; else list">
+ <span *ngIf="!element.endpoints.length" class="no-details">no details</span>
+ </div>
+ <ng-template #list>
+ <div *ngFor="let endpoint of element.endpoints" class="resource-wrap">
+ <div class="resource-name">
+ <a class="project-endpoint-name">
+ {{ endpoint.name }}
+ </a>
+ </div>
+ <div class="resource-status">
+ <span [ngClass]="{'active' : endpoint.endpointStatus === 'ACTIVE', 'failed': endpoint.endpointStatus === 'INACTIVE'}">
+ {{ (endpoint.endpointStatus | titlecase) || 'N/A'}}
+ </span>
+ </div>
- </td>
+ <span class="status resource-status" [ngClass]="endpoint?.status.toLowerCase() || ''">
+ {{ endpoint?.status.toLowerCase() }}
+ </span>
+ </div>
+ </ng-template>
+ </td>
+ </ng-container>
- </ng-container>
+ <ng-container matColumnDef="actions">
+ <th mat-header-cell *matHeaderCellDef class="project-actions">
+ <span class="label"> Actions </span>
+ </th>
+ <td mat-cell *matCellDef="let element" class="settings">
+ <span #settings (click)="actions.toggle($event, settings)" class="actions"></span>
+ <bubble-up #actions class="list-menu" position="bottom-left" alternative="top-left">
+ <ul class="list-unstyled actions-list">
+ <div class="active-items"></div>
+ <li class="project-seting-item" *ngIf="element.areStoppedNode" (click)="openEdgeDialog('start', element)">
+ <i class="material-icons">play_circle_outline</i>
+ <a class="action">
+ Start edge node
+ </a>
+ </li>
+ <li class="project-seting-item" *ngIf="element.areRunningNode" (click)="openEdgeDialog('stop', element )">
+ <i class="material-icons">pause_circle_outline</i>
+ <a class="action" >
+ Stop edge node
+ </a>
+ </li>
+ <!-- <li class="project-seting-item " *ngIf="element.areTerminatedNode" (click)="openEdgeDialog('recreate', element)">
+ <i class="material-icons">refresh</i>
+ <a class="action">
+ Recreate edge node
+ </a>
+ </li> -->
+ <li class="project-seting-item " *ngIf="element.areStoppedNode || element.areRunningNode" (click)="openEdgeDialog('terminate', element)">
+ <i class="material-icons">phonelink_off</i>
+ <a class="action">
+ Terminate edge node
+ </a>
+ </li>
+ <li class="project-seting-item" (click)="editProject(element)" *ngIf="!isProjectAdmin">
+ <i class="material-icons">mode_edit</i>
+ <a >
+ Edit project
+ </a>
+ </li>
+ </ul>
+ </bubble-up>
+ </td>
+ <td class="settings"></td>
+ </ng-container>
- <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
- <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
-</table>
+ <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+ <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+ </table>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.scss b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.scss
index 140feb4..836b822 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.scss
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.scss
@@ -17,13 +17,12 @@
* under the License.
*/
-
-.table-wrapper{
- height: calc(100vh - 120px);
- overflow: auto;
+.table-wrapper {
position: relative;
- margin: 0 -15px -15px -15px;
+ margin: 0 -15px -15px -15px;
padding: 0 15px 15px 15px;
+ height: calc(100vh - 120px);
+ overflow: auto;
.mat-header-cell {
position: sticky;
top: 0;
@@ -31,6 +30,7 @@
background: white;
}
}
+
table {
width: 100%;
@@ -41,16 +41,16 @@ table {
.name {
width: 25%;
padding: 20px 0 10px 24px;
- &.project-name{
+ &.project-name {
padding-top: 10px;
}
}
- th.name{
+ th.name {
padding-top: 10px;
}
- .mat-header-row{
+ .mat-header-row {
padding-top: 12px;
}
@@ -59,13 +59,15 @@ table {
padding: 15px 0;
.resource-wrap {
- .resource-name, .resource-status {
+ .resource-name,
+ .resource-status {
width: 30%;
padding-left: 0;
}
}
- .label-endpoint, .label-endpoint-status {
+ .label-endpoint,
+ .label-endpoint-status {
display: inline-block;
width: 30%;
}
@@ -75,7 +77,7 @@ table {
}
&.source {
- &.endpoints .resource-wrap{
+ &.endpoints .resource-wrap {
justify-content: flex-start;
}
.no-details {
@@ -94,19 +96,19 @@ table {
}
.project-actions {
- color: #607d8b;
width: 10%;
+ padding: 10px 24px;
+ color: #607d8b;
text-align: right;
vertical-align: top;
- padding: 10px 24px;
- &.mat-header-cell{
+ &.mat-header-cell {
padding-top: 19px;
- color: rgba(0,0,0,.54);
+ color: rgba(0, 0, 0, 0.54);
}
span:not(.mat-header-cell span) {
- transition: all .5s ease-in-out;
+ transition: all 0.5s ease-in-out;
cursor: pointer;
.mat-icon {
@@ -126,47 +128,49 @@ td.settings {
vertical-align: middle !important;
text-align: right;
.actions {
- margin-top: 3px;
- background-image: url(../../../../assets/svg/settings_icon.svg);
+ display: inline-block;
width: 16px;
height: 16px;
- display: inline-block;
+ margin-top: 3px;
+ background-image: url(../../../../assets/svg/settings_icon.svg);
text-align: center;
cursor: pointer;
}
}
-.project-seting-item{
+
+.project-seting-item {
display: flex;
- padding: 10px;
align-items: center;
+ padding: 10px;
border-bottom: 1px solid #edf1f5;
cursor: pointer;
color: #577289;
- &:last-child{
+ &:last-child {
border-bottom: none;
}
- &:hover{
+ &:hover {
color: #36afd5;
- transition: all .45s ease-in-out;
+ transition: all 0.45s ease-in-out;
}
- a{
+ a {
padding-left: 5px;
}
}
+
.material-icons {
font-size: 18px;
padding-top: 1px;
}
-.list-menu{
+.list-menu {
min-width: 205px;
}
-.project-endpoint-name{
- color: #577289;
+.project-endpoint-name {
+ color: #577289;
}
-.actions-list{
+.actions-list {
padding: 10px 15px;
}
@@ -174,8 +178,4 @@ td.settings {
max-width: 200px !important;
white-space: nowrap;
display: inline-block;
-}
-
-
-
-
+}
\ No newline at end of file
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.ts
index 6ee2f2a..41a2127 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-list/project-list.component.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import {Component, OnInit, Output, EventEmitter, OnDestroy, Inject, Input} from '@angular/core';
+import { Component, OnInit, Output, EventEmitter, OnDestroy, Inject, Input } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { MatTableDataSource } from '@angular/material/table';
import { Subscription } from 'rxjs';
@@ -25,11 +25,8 @@ import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dial
import { ProjectDataService } from '../project-data.service';
import { Project, Endpoint } from '../project.component';
-import { CheckUtils } from '../../../core/util';
import {ProgressBarService} from '../../../core/services/progress-bar.service';
import {EdgeActionDialogComponent} from '../../../shared/modal-dialog/edge-action-dialog';
-import {EndpointService} from '../../../core/services';
-
@Component({
selector: 'project-list',
@@ -47,16 +44,14 @@ export class ProjectListComponent implements OnInit, OnDestroy {
@Output() toggleStatus: EventEmitter<{}> = new EventEmitter();
private subscriptions: Subscription = new Subscription();
- constructor(
+ constructor (
public toastr: ToastrService,
private projectDataService: ProjectDataService,
private progressBarService: ProgressBarService,
@Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<ProjectListComponent>,
public dialog: MatDialog,
- ) {
- }
-
+ ) { }
ngOnInit() {
this.getProjectList();
@@ -68,23 +63,30 @@ export class ProjectListComponent implements OnInit, OnDestroy {
private getProjectList() {
this.progressBarService.startProgressBar();
- this.subscriptions.add(this.projectDataService._projects.subscribe((value: Project[]) => {
- this.projectList = value;
- if (this.projectList) {
- this.projectList.forEach(project => {
- project.areRunningNode = this.areResoursesInStatuses(project.endpoints, ['RUNNING']);
- project.areStoppedNode = this.areResoursesInStatuses(project.endpoints, ['STOPPED']);
- project.areTerminatedNode = this.areResoursesInStatuses(project.endpoints, ['TERMINATED', 'FAILED']);
- });
- }
- if (value) this.dataSource = new MatTableDataSource(value);
- this.progressBarService.stopProgressBar();
- }, () => this.progressBarService.stopProgressBar()));
+ this.subscriptions.add(this.projectDataService._projects
+ .subscribe(
+ (value: Project[]) => {
+ this.projectList = value;
+ if (this.projectList) {
+ this.projectList.forEach(project => {
+ project.areRunningNode = this.areResoursesInStatuses(project.endpoints, ['RUNNING']);
+ project.areStoppedNode = this.areResoursesInStatuses(project.endpoints, ['STOPPED']);
+ project.areTerminatedNode = this.areResoursesInStatuses(project.endpoints, ['TERMINATED', 'FAILED']);
+ });
+ }
+ if (value) this.dataSource = new MatTableDataSource(value);
+ this.progressBarService.stopProgressBar();
+ },
+ () => this.progressBarService.stopProgressBar()
+ )
+ );
}
public showActiveInstances(): void {
const filteredList = this.projectList.map(project => {
- project.endpoints = project.endpoints.filter((endpoint: Endpoint) => endpoint.status !== 'TERMINATED' && endpoint.status !== 'TERMINATING' && endpoint.status !== 'FAILED');
+ project.endpoints = project.endpoints.filter((endpoint: Endpoint) => {
+ return endpoint.status !== 'TERMINATED' && endpoint.status !== 'TERMINATING' && endpoint.status !== 'FAILED'
+ });
return project;
});
@@ -96,32 +98,34 @@ export class ProjectListComponent implements OnInit, OnDestroy {
}
public openEdgeDialog(action, project) {
- const endpoints = project.endpoints.filter(endpoint => {
- if (action === 'stop') {
- return endpoint.status === 'RUNNING';
- }
- if (action === 'start') {
- return endpoint.status === 'STOPPED';
- }
- if (action === 'terminate') {
- return endpoint.status === 'RUNNING' || endpoint.status === 'STOPPED';
- }
- if (action === 'recreate') {
- return endpoint.status === 'TERMINATED' || endpoint.status === 'FAILED';
- }
- });
- if (action === 'terminate' && endpoints.length === 1) {
- this.toggleStatus.emit({project, endpoint: endpoints, action, oneEdge: true});
- } else {
- this.dialog.open(EdgeActionDialogComponent, {data: {type: action, item: endpoints}, panelClass: 'modal-sm'})
- .afterClosed().subscribe(endpoint => {
+ const endpoints = project.endpoints.filter(endpoint => {
+ if (action === 'stop') {
+ return endpoint.status === 'RUNNING';
+ }
+ if (action === 'start') {
+ return endpoint.status === 'STOPPED';
+ }
+ if (action === 'terminate') {
+ return endpoint.status === 'RUNNING' || endpoint.status === 'STOPPED';
+ }
+ if (action === 'recreate') {
+ return endpoint.status === 'TERMINATED' || endpoint.status === 'FAILED';
+ }
+ });
+ if (action === 'terminate' && endpoints.length === 1) {
+ this.toggleStatus.emit({ project, endpoint: endpoints, action, oneEdge: true });
+ } else {
+ this.dialog.open(EdgeActionDialogComponent, { data: { type: action, item: endpoints }, panelClass: 'modal-sm' })
+ .afterClosed().subscribe(
+ endpoint => {
if (endpoint && endpoint.length) {
this.toggleStatus.emit({project, endpoint, action});
}
- }, error => this.toastr.error(error.message || `Endpoint ${action} failed!`, 'Oops!')
+ },
+ error => this.toastr.error(error.message || `Endpoint ${action} failed!`, 'Oops!')
);
- }
}
+ }
public areResoursesInStatuses(resources, statuses: Array<string>) {
return resources.some(resource => statuses.some(status => resource.status === status));
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datalab.apache.org
For additional commands, e-mail: commits-help@datalab.apache.org