You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by dg...@apache.org on 2020/04/29 15:54:03 UTC
[incubator-dlab] 01/01: [DLAB-1758]: Added audit page
This is an automated email from the ASF dual-hosted git repository.
dgnatyshyn pushed a commit to branch DLAB-1758
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit 299b1db193671275845298868dc1538431342b13
Author: Dmytro Gnatyshyn <di...@ukr.net>
AuthorDate: Wed Apr 29 18:53:23 2020 +0300
[DLAB-1758]: Added audit page
---
.../main/resources/webapp/src/app/app.module.ts | 4 +-
.../resources/webapp/src/app/app.routing.module.ts | 10 +-
.../app/audit/audit-grid/audit-grid.component.html | 97 +++++++++
.../app/audit/audit-grid/audit-grid.component.scss | 219 +++++++++++++++++++++
.../app/audit/audit-grid/audit-grid.component.ts | 50 +++++
.../audit-toolbar/audit-toolbar.component.html} | 10 +-
.../audit-toolbar/audit-toolbar.component.scss | 140 +++++++++++++
.../audit/audit-toolbar/audit-toolbar.component.ts | 113 +++++++++++
.../webapp/src/app/audit/audit.component.ts | 94 +++++++++
.../resources/webapp/src/app/audit/audit.module.ts | 48 +++++
.../webapp/src/app/audit/filter-audit.model.ts | 21 ++
.../webapp/src/app/core/services/audit.service.ts | 23 +++
.../src/app/reporting/reporting.component.ts | 1 -
.../app/reporting/toolbar/toolbar.component.html | 4 +-
.../src/app/shared/navbar/navbar.component.html | 5 +
15 files changed, 828 insertions(+), 11 deletions(-)
diff --git a/services/self-service/src/main/resources/webapp/src/app/app.module.ts b/services/self-service/src/main/resources/webapp/src/app/app.module.ts
index e23e14a..767eba1 100644
--- a/services/self-service/src/main/resources/webapp/src/app/app.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/app.module.ts
@@ -30,7 +30,7 @@ import { AppComponent } from './app.component';
import { AppRoutingModule } from './app.routing.module';
import { LoginModule } from './login/login.module';
-import { LayoutModule } from './layout/layout.module'
+import { LayoutModule } from './layout/layout.module';
import { GuidesModule } from './help';
import { ServicePagesModule } from './service-pages/service-pages.module';
@@ -41,6 +41,7 @@ import { AdministrationModule } from './administration/administration.module';
import { WebterminalModule } from './webterminal';
import { CoreModule } from './core/core.module';
import { SwaggerAPIModule } from './swagger';
+import {AuditModule} from './audit/audit.module';
@NgModule({
declarations: [AppComponent],
@@ -56,6 +57,7 @@ import { SwaggerAPIModule } from './swagger';
GuidesModule,
ServicePagesModule,
ReportingModule,
+ AuditModule,
AdministrationModule,
WebterminalModule,
SwaggerAPIModule,
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 3c8ae3f..0cc0f4a 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
@@ -21,7 +21,7 @@ import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.module';
-import { LayoutComponent } from './layout/layout.component'
+import { LayoutComponent } from './layout/layout.component';
import { ResourcesComponent } from './resources/resources.component';
import { AccessNotebookGuideComponent, PublicKeyGuideComponent } from './help';
import { NotFoundComponent } from './service-pages/not-found/not-found.component';
@@ -34,6 +34,7 @@ import { RolesComponent } from './administration/roles/roles.component';
import { SwaggerComponent } from './swagger/swagger.component';
import { AuthorizationGuard, CheckParamsGuard, CloudProviderGuard, AdminGuard } from './core/services';
+import {AuditComponent} from './audit/audit.component';
const routes: Routes = [{
path: 'login',
@@ -79,7 +80,12 @@ const routes: Routes = [{
path: 'help/accessnotebookguide',
component: AccessNotebookGuideComponent,
canActivate: [AuthorizationGuard]
- }
+ },
+ {
+ path: 'audit',
+ component: AuditComponent,
+ canActivate: [AuthorizationGuard, AdminGuard],
+ },
]
}, {
path: 'terminal/:id/:endpoint',
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.html
new file mode 100644
index 0000000..c8d33e8
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.html
@@ -0,0 +1,97 @@
+<!--
+ ~ 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="audit-table-wrapper">
+ <table mat-table [dataSource]="auditData" class="data-grid audit mat-elevation-z6">
+
+ <ng-container matColumnDef="user">
+ <th mat-header-cell *matHeaderCellDef class="th_user label-header">
+ <div class="label"><span> User</span></div>
+ <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <i class="material-icons">
+ <span *ngIf="filterAuditData.users.length > 0; else user_filtered">filter_list</span>
+ <ng-template #user_filtered>more_vert</ng-template>
+ </i>
+ </button>
+ </th>
+ <td mat-cell *matCellDef="let element"><span class="table-item user-col">{{element.user}}</span></td>
+ <td mat-footer-cell *matFooterCellDef class="table-footer"></td>
+ </ng-container>
+
+ <ng-container matColumnDef="action">
+ <th mat-header-cell *matHeaderCellDef class="th_action label-header">
+<!-- <div class="sort">-->
+<!-- <div class="sort-arrow up" (click)="sortBy('user', 'down')" [ngClass]="{'active': !!this.active['userdown']}"></div>-->
+<!-- <div class="sort-arrow down" (click)="sortBy('user', 'up')" [ngClass]="{'active': !!this.active['userup']}"></div>-->
+<!-- </div>-->
+ <div class="label">
+ <span class="text"> Action </span>
+ </div>
+ <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
+ <i class="material-icons">
+ <span *ngIf="filterAuditData.actions.length > 0; else action_filtered">filter_list</span>
+ <ng-template #action_filtered>more_vert</ng-template>
+ </i>
+ </button>
+ </th>
+ <td mat-cell *matCellDef=" let element"> {{element.action}} </td>
+ <td mat-footer-cell *matFooterCellDef class="table-footer"></td>
+ </ng-container>
+
+ <ng-container matColumnDef="date">
+ <th mat-header-cell *matHeaderCellDef class="th_date label-header">
+<!-- <div class="sort">-->
+<!-- <div class="sort-arrow up" (click)="sortBy('project', 'down')" [ngClass]="{'active': !!this.active['projectdown']}"></div>-->
+<!-- <div class="sort-arrow down" (click)="sortBy('project', 'up')" [ngClass]="{'active': !!this.active['projectup']}"></div>-->
+<!-- </div>-->
+ <div class="label"><span class="text">Date</span></div>
+ </th>
+ <td mat-cell *matCellDef="let element"> {{element.date}} </td>
+ <td mat-footer-cell *matFooterCellDef class="table-footer"></td>
+ </ng-container>
+
+ <ng-container matColumnDef="user-filter">
+ <th mat-header-cell *matHeaderCellDef class="filter-row-item">
+ <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'users'"
+ [items]="filterConfiguration.users" [model]="filterAuditData.users"></multi-select-dropdown>
+ </th>
+ </ng-container>
+ <ng-container matColumnDef="action-filter">
+ <th mat-header-cell *matHeaderCellDef class="filter-row-item">
+ <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)" [type]="'actions'"
+ [items]="filterConfiguration.actions" [model]="filterAuditData.actions"></multi-select-dropdown>
+ </th>
+ </ng-container>
+ <ng-container matColumnDef="date-filter">
+ <th mat-header-cell *matHeaderCellDef class="filter-row-item">
+
+ </th>
+ </ng-container>
+
+ <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true" class="header-row"></tr>
+
+ <tr [hidden]="!collapseFilterRow" mat-header-row *matHeaderRowDef="displayedFilterColumns; sticky: true"
+ class="filter-row"></tr>
+ <tr mat-row *matRowDef="let row; columns: displayedColumns;" class="content-row"></tr>
+
+<!-- <tr [hidden]="!auditData?.length" mat-footer-row *matFooterRowDef="displayedColumns; sticky: true"-->
+<!-- class="header-row"></tr>-->
+<!-- <tr [hidden]="reportData?.length" mat-footer-row *matFooterRowDef="['placeholder']"></tr>-->
+ </table>
+</section>
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.scss b/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.scss
new file mode 100644
index 0000000..352384a
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.scss
@@ -0,0 +1,219 @@
+/*!
+ * 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.
+ */
+
+.audit-table-wrapper {
+ width: 100%;
+
+ .audit {
+ width: 100%;
+ min-width: 1100px;
+ overflow: auto;
+ border-collapse: inherit;
+
+ .mat-cell {
+ vertical-align: middle;
+ }
+
+ tr {
+ .th_user {
+ width: 25%;
+ }
+
+ .th_action {
+ width: 50%;
+ }
+
+ .th_date {
+ width: 20%;
+ }
+
+ th {
+ padding-right: 5px;
+ z-index: 2 !important;
+
+ &.th_charges {
+ z-index: 3 !important;
+ }
+ }
+
+ td {
+ font-size: 13px;
+ padding-left: 15px;
+
+ &.info {
+ z-index: 1 !important;
+ text-align: center;
+ padding: 40px;
+ }
+ }
+
+ &.filter-row {
+ th {
+ padding: 5px;
+ font-size: 13px;
+ }
+
+ .filter-field {
+ font-size: 13px;
+ }
+
+ }
+
+ &.header-row {
+ th {
+ font-size: 11px;
+
+ .label {
+ padding-left: 0;
+ }
+ }
+ }
+ }
+
+
+ .tags {
+ .label {
+ padding-top: 0;
+ }
+ }
+
+ .service {
+ min-width: 175px;
+ }
+
+ .env_name {
+ width: 16%;
+ min-width: 200px;
+ }
+
+ .th_project {
+ width: 12%;
+ }
+
+ .th_type {
+ width: 10%;
+ min-width: 150px;
+ }
+
+ .th_status {
+ width: 8%;
+ min-width: 150px;
+ }
+
+ .th_charges {
+ width: 10%;
+ min-width: 155px;
+ text-align: right;
+
+ .label {
+ padding-top: 0;
+ }
+ }
+
+ .th_project {
+ min-width: 150px;
+ }
+
+ .tags-col {
+ padding: 5px;
+
+ mat-chip {
+ min-height: 20px;
+ padding: 5px 10px;
+ font-size: 13px;
+ max-width: 110px !important;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ display: inline-block;
+ line-height: 10px;
+ margin: 2px;
+ }
+ }
+
+ .mat-column-charge {
+ text-align: right;
+ }
+
+ .header-row {
+ position: unset;
+
+ .th_charges {
+ padding-top: 0;
+
+ .label {
+ padding-top: 12px;
+ }
+ }
+
+ .label {
+ display: inline-block;
+ padding-top: 13px;
+ vertical-align: super !important;
+
+ .text {
+ padding-left: 15px;
+ }
+ }
+
+ .sort {
+ position: absolute;
+ bottom: 20px;
+
+ &-arrow {
+ width: 6px;
+ height: 6px;
+ border: 3px solid transparent;
+ border-bottom: 3px solid rgba(0, 0, 0, .54);
+ border-left: 3px solid rgba(0, 0, 0, .54);
+ cursor: pointer;
+
+ &.active {
+ border-bottom: 3px solid #35afd5;
+ border-left: 3px solid #35afd5;
+ }
+ }
+
+ .down {
+ transform: rotate(-45deg);
+ }
+
+ .up {
+ transform: rotate(135deg);
+ }
+ }
+ }
+ }
+
+ .dashboard_table_body {
+ td:first-child {
+ cursor: default;
+ }
+
+ .dropdown-multiselect {
+ button {
+ font-size: 14px;
+ height: 34px;
+ padding: 7px 20px;
+ }
+ }
+ }
+ .user-col{
+ padding-left: 5px;
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.ts
new file mode 100644
index 0000000..7e8b575
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit-grid/audit-grid.component.ts
@@ -0,0 +1,50 @@
+/*
+ * 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 {FilterAuditModel} from '../filter-audit.model';
+
+@Component({
+ selector: 'dlab-audit-grid',
+ templateUrl: './audit-grid.component.html',
+ styleUrls: ['./audit-grid.component.scss'],
+
+})
+export class AuditGridComponent implements OnInit {
+ public auditData: Array<object>;
+ public displayedColumns: string[] = ['user', 'action', 'date'];
+ public displayedFilterColumns: string[] = ['user-filter', 'action-filter', 'date-filter'];
+ public collapseFilterRow: boolean = true;
+ public filterConfiguration: FilterAuditModel = new FilterAuditModel([], [], '', '');
+ public filterAuditData: FilterAuditModel = new FilterAuditModel([], [], '', '');
+
+ ngOnInit() {}
+
+ public refreshAudit(auditData) {
+ this.auditData = auditData;
+ }
+
+ toggleFilterRow(): void {
+ this.collapseFilterRow = !this.collapseFilterRow;
+ }
+
+ onUpdate($event): void {
+ this.filterAuditData[$event.type] = $event.model;
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html b/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.html
similarity index 86%
copy from services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html
copy to services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.html
index 583371e..601a4dd 100644
--- a/services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.html
@@ -17,8 +17,8 @@
~ under the License.
-->
<section class="toolbar">
- <div class="info_color" *ngIf="reportData">
- <div class="general">
+ <div class="info_color">
+ <div class="general" *ngIf="reportData">
<div><span>Service base name: </span><strong>{{ reportData.sbn }}</strong></div>
<div *ngIf="reportData.tag_resource_id"><span>Resource tag ID:
</span><strong>{{ reportData.tag_resource_id }}</strong></div>
@@ -34,9 +34,9 @@
<ng-daterangepicker [(ngModel)]="value" [options]="options" (ngModelChange)="onChange($event)"></ng-daterangepicker>
</div>
<div class="action-butt">
- <button mat-raised-button class="butt" (click)="export($event)" [disabled]="!reportData?.report_lines.length">
- <i class="material-icons">file_download</i>Export
- </button>
+<!-- <button mat-raised-button class="butt" (click)="export($event)" [disabled]="!reportData?.report_lines.length">-->
+<!-- <i class="material-icons">file_download</i>Export-->
+<!-- </button>-->
<button mat-raised-button class="butt" (click)="rebuild($event)">
<i class="material-icons">autorenew</i>Refresh
</button>
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.scss b/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.scss
new file mode 100644
index 0000000..4a150bf
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.scss
@@ -0,0 +1,140 @@
+/*
+ * 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.toolbar {
+ display: flex;
+ justify-content: space-between;
+ font-weight: 300;
+ width: 100%;
+
+ >div {
+ width: 33%;
+ }
+
+ >div:nth-child(2) {
+ text-align: center;
+ }
+
+ >div:nth-child(3) {
+ text-align: right;
+ }
+
+ .action-butt {
+ align-self: center;
+ }
+
+ button {
+ &:first-child {
+ margin-right: 10px;
+ }
+ }
+
+ .butt-report-range {
+ width: 240px;
+ margin-right: 10px;
+ }
+
+ .general {
+ font-size: 13px;
+
+ div {
+ span {
+ width: 190px;
+ display: inline-block;
+ }
+ }
+ }
+}
+
+/* daterangepicker themes */
+#range-picker {
+ margin-top: 5px;
+}
+
+#range-picker path#Shape {
+ fill: #36afd5;
+}
+
+#range-picker .ng-daterangepicker,
+#range-picker .ng-daterangepicker.is-active,
+#range-picker .ng-daterangepicker .calendar {
+ border: none;
+ border-radius: 0;
+ box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12);
+}
+
+#range-picker .ng-daterangepicker .calendar::after {
+ border-top: 1px solid rgba(234, 234, 234, 0.64);
+ border-left: 1px solid rgba(234, 234, 234, 0.64);
+}
+
+#range-picker .ng-daterangepicker .calendar .side-container .side-button {
+ background: #fff;
+ color: #718ba6;
+ border: none;
+ border-radius: 0px;
+ box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12)
+}
+
+#range-picker .ng-daterangepicker .calendar .side-container .side-button.is-active,
+#range-picker .ng-daterangepicker .input-section .label-txt {
+ color: #35afd5;
+}
+
+#range-picker .ng-daterangepicker .calendar .calendar-container .day-num.is-active,
+#range-picker .ng-daterangepicker .calendar .calendar-container .days .day-num:hover {
+ background: #35afd5;
+ background-clip: padding-box;
+
+}
+
+#range-picker .ng-daterangepicker .calendar .calendar-container .day-names,
+#range-picker .ng-daterangepicker .calendar .calendar-container .days {
+ width: 310px;
+}
+
+#range-picker .ng-daterangepicker .calendar .day.is-within-range.is-first-weekday,
+#range-picker .ng-daterangepicker .calendar .day.is-within-range.is-last-weekday {
+ background-clip: padding-box;
+}
+
+#range-picker .ng-daterangepicker .calendar .calendar-container .day.is-within-range {
+ background: #e9f8fc
+}
+
+#range-picker .ng-daterangepicker .input-section .cal-icon svg path {
+ fill: #35afd5;
+}
+
+#range-picker .ng-daterangepicker .input-section .value-txt {
+ color: #718ba6;
+}
+
+#range-picker .ng-daterangepicker .input-section .value-txt.untouched,
+#range-picker .ng-daterangepicker .input-section .label-txt.untouched {
+ color: #fff;
+}
+
+#range-picker .ng-daterangepicker .input-section .value-txt.untouched::after {
+ content: 'Select date';
+ position: absolute;
+ top: 22px;
+ left: 34px;
+ color: #718ba6;
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.ts b/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.ts
new file mode 100644
index 0000000..3de049f
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit-toolbar/audit-toolbar.component.ts
@@ -0,0 +1,113 @@
+/*
+ * 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, AfterViewInit, Output, EventEmitter, ViewEncapsulation, ViewChild } from '@angular/core';
+import { NgDateRangePickerOptions } from 'ng-daterangepicker';
+import { DICTIONARY } from '../../../dictionary/global.dictionary';
+import {skip} from 'rxjs/operators';
+import {Subscription} from 'rxjs';
+import {HealthStatusService} from '../../core/services';
+import {GeneralEnvironmentStatus} from '../../administration/management/management.model';
+
+@Component({
+ selector: 'audit-toolbar',
+ templateUrl: './audit-toolbar.component.html',
+ styleUrls: ['./audit-toolbar.component.scss'],
+ encapsulation: ViewEncapsulation.None
+})
+export class AuditToolbarComponent implements OnInit, AfterViewInit {
+ readonly DICTIONARY = DICTIONARY;
+ value: any;
+ reportData: any;
+ availablePeriodFrom: string;
+ availablePeriodTo: string;
+ subscriptions: Subscription = new Subscription();
+ healthStatus: GeneralEnvironmentStatus;
+
+ rangeOptions = { 'YTD': 'Year To Date', 'QTD': 'Quarter To Date', 'MTD': 'Month To Date', 'reset': 'All Period Report' };
+ options: NgDateRangePickerOptions;
+ rangeLabels: any;
+
+ @Output() rebuildReport: EventEmitter<{}> = new EventEmitter();
+ @Output() exportReport: EventEmitter<{}> = new EventEmitter();
+ @Output() setRangeOption: EventEmitter<{}> = new EventEmitter();
+
+ constructor(private healthStatusService: HealthStatusService) {
+ this.options = {
+ theme: 'default',
+ range: 'tm',
+ dayNames: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
+ presetNames: ['This Month', 'Last Month', 'This Week', 'Last Week', 'This Year', 'Last Year', 'From', 'To'],
+ dateFormat: 'dd MMM y',
+ outputFormat: 'YYYY/MM/DD',
+ startOfWeek: 1
+ };
+ }
+
+ ngOnInit() {
+ // if (localStorage.getItem('report_period')) {
+ // const availableRange = JSON.parse(localStorage.getItem('report_period'));
+ // this.availablePeriodFrom = availableRange.start_date;
+ // this.availablePeriodTo = availableRange.end_date; }
+ // this.subscriptions.add(this.healthStatusService.statusData.pipe(skip(1)).subscribe(result => {
+ // this.healthStatus = result;
+ // }));
+ }
+
+ ngAfterViewInit() {
+ this.clearRangePicker();
+ }
+
+ setDateRange() {
+ const availableRange = JSON.parse(localStorage.getItem('report_period'));
+
+ this.availablePeriodFrom = availableRange.start_date;
+ this.availablePeriodTo = availableRange.end_date;
+ }
+
+ clearRangePicker(): void {
+ const rangeLabels = <NodeListOf<Element>>document.querySelectorAll('.value-txt');
+
+ for (let label = 0; label < rangeLabels.length; ++label)
+ rangeLabels[label].classList.add('untouched');
+ }
+
+ onChange(dateRange: string): void {
+ const rangeLabels = <NodeListOf<Element>>document.querySelectorAll('.value-txt');
+
+ for (let label = 0; label < rangeLabels.length; ++label)
+ if (rangeLabels[label].classList.contains('untouched')) {
+ rangeLabels[label].classList.remove('untouched');
+ }
+
+ const reportDateRange = dateRange.split('-');
+ this.setRangeOption.emit({
+ start_date: reportDateRange[0].split('/').join('-'),
+ end_date: reportDateRange[1].split('/').join('-')
+ });
+ }
+
+ rebuild($event): void {
+ this.rebuildReport.emit($event);
+ }
+
+ // export($event): void {
+ // this.exportReport.emit($event);
+ // }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit.component.ts b/services/self-service/src/main/resources/webapp/src/app/audit/audit.component.ts
new file mode 100644
index 0000000..92ca006
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit.component.ts
@@ -0,0 +1,94 @@
+/*
+ * 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, OnDestroy, ViewChild } from '@angular/core';
+import { ToastrService } from 'ngx-toastr';
+import {HealthStatusService} from '../core/services';
+import { DICTIONARY} from '../../dictionary/global.dictionary';
+import {AuditToolbarComponent} from './audit-toolbar/audit-toolbar.component';
+import {AuditGridComponent} from './audit-grid/audit-grid.component';
+import {AuditService} from '../core/services/audit.service';
+
+
+@Component({
+ selector: 'dlab-reporting',
+ template: `
+ <div class="base-retreat">
+<!-- <dlab-toolbar (rebuildReport)="rebuildBillingReport()"-->
+<!-- (exportReport)="exportBillingReport()"-->
+<!-- (setRangeOption)="setRangeOption($event)">-->
+<!-- </dlab-toolbar>-->
+<!-- <mat-divider></mat-divider>-->
+<!-- <dlab-reporting-grid (filterReport)="filterReport($event)" (resetRangePicker)="resetRangePicker()"></dlab-reporting-grid>-->
+ <audit-toolbar>
+ </audit-toolbar>
+ <mat-divider></mat-divider>
+ <dlab-audit-grid></dlab-audit-grid>
+ </div>
+
+ `,
+ styles: [`
+ footer {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ background: #a1b7d1;
+ color: #ffffff;
+ text-align: right;
+ padding: 5px 15px;
+ font-size: 18px;
+ box-shadow: 0 9px 18px 15px #f5f5f5;
+ }
+ `]
+})
+export class AuditComponent implements OnInit, OnDestroy {
+ readonly DICTIONARY = DICTIONARY;
+
+ @ViewChild(AuditGridComponent, { static: true }) auditGrid: AuditGridComponent;
+ @ViewChild(AuditToolbarComponent, { static: true }) auditToolbar: AuditToolbarComponent;
+
+ public auditData;
+
+ constructor(
+ private healthStatusService: HealthStatusService,
+ private auditService: AuditService,
+ public toastr: ToastrService,
+ ) { }
+
+ ngOnInit() {
+ this.getEnvironmentHealthStatus();
+ this.buildAuditReport();
+ }
+
+ ngOnDestroy() {
+ }
+
+ public buildAuditReport() {
+ this.auditData = this.auditService.getAuditData();
+ this.auditGrid.refreshAudit(this.auditData);
+
+ }
+
+ private getEnvironmentHealthStatus() {
+ this.healthStatusService.getEnvironmentHealthStatus()
+ .subscribe((result: any) => {});
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/audit.module.ts b/services/self-service/src/main/resources/webapp/src/app/audit/audit.module.ts
new file mode 100644
index 0000000..c799d23
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/audit.module.ts
@@ -0,0 +1,48 @@
+/*
+ * 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 { FormsModule } from '@angular/forms';
+import { NgDateRangePickerModule } from 'ng-daterangepicker';
+import { MaterialModule } from '../shared/material.module';
+import { FormControlsModule } from '../shared/form-controls';
+import { KeysPipeModule, LineBreaksPipeModule } from '../core/pipes';
+import {AuditComponent} from './audit.component';
+import {AuditGridComponent} from './audit-grid/audit-grid.component';
+import {AuditToolbarComponent} from './audit-toolbar/audit-toolbar.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ FormControlsModule,
+ KeysPipeModule,
+ LineBreaksPipeModule,
+ NgDateRangePickerModule,
+ MaterialModule
+ ],
+ declarations: [
+ AuditGridComponent,
+ AuditToolbarComponent,
+ AuditComponent
+ ],
+ exports: [AuditComponent]
+})
+export class AuditModule { }
diff --git a/services/self-service/src/main/resources/webapp/src/app/audit/filter-audit.model.ts b/services/self-service/src/main/resources/webapp/src/app/audit/filter-audit.model.ts
new file mode 100644
index 0000000..37f07f9
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/audit/filter-audit.model.ts
@@ -0,0 +1,21 @@
+export class FilterAuditModel {
+
+ static getDefault(): FilterAuditModel {
+ return new FilterAuditModel([], [], '', '');
+ }
+
+ constructor(
+ public users: Array<string>,
+ public actions: Array<string>,
+ public date_start: string,
+ public date_end: string,
+ ) { }
+
+ defaultConfigurations(): void {
+ this.users = [];
+ this.actions = [];
+ this.date_start = '';
+ this.date_end = '';
+
+ }
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/audit.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/audit.service.ts
new file mode 100644
index 0000000..87f970f
--- /dev/null
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/audit.service.ts
@@ -0,0 +1,23 @@
+import { Injectable } from '@angular/core';
+import {ApplicationServiceFacade} from './applicationServiceFacade.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuditService {
+ constructor(private applicationServiceFacade: ApplicationServiceFacade) {
+ }
+
+ public getAuditData() {
+ return [
+ {user: 'Dlab-test-user1', action: 'Created project ProjectA', date: new Date().toLocaleString()},
+ {user: 'Dlab-test-user2', action: 'Created notebook Rstudio', date: new Date().toLocaleString()},
+ {user: 'Dlab-test-user1', action: 'Stopped notebook Rstudio', date: new Date().toLocaleString()},
+ {user: 'Dlab-test-user1', action: 'Started notebook Rstudio', date: new Date().toLocaleString()},
+ {user: 'Dlab-test-user3', action: 'Created EMR Emr1', date: new Date().toLocaleString()},
+ {user: 'Dlab-test-user1', action: 'Created notebook Rstudio2', date: new Date().toLocaleString()},
+ {user: 'Dlab-test-user2', action: 'Terminated notebook Rstudio', date: new Date().toLocaleString()},
+ ];
+ }
+
+}
diff --git a/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts b/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts
index 03f7ca9..1692ef1 100644
--- a/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts
@@ -156,7 +156,6 @@ export class ReportingComponent implements OnInit, OnDestroy {
types.push(item['resource_type']);
if (item.shape && types.indexOf(item.shape)) {
- console.log(item);
if (item.shape.indexOf('Master') > -1) {
for (let shape of item.shape.split(/(?=Slave)/g)) {
shape = shape.replace('Master: ', '');
diff --git a/services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html b/services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html
index 583371e..d912f78 100644
--- a/services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/reporting/toolbar/toolbar.component.html
@@ -17,8 +17,8 @@
~ under the License.
-->
<section class="toolbar">
- <div class="info_color" *ngIf="reportData">
- <div class="general">
+ <div class="info_color" >
+ <div class="general" *ngIf="reportData">
<div><span>Service base name: </span><strong>{{ reportData.sbn }}</strong></div>
<div *ngIf="reportData.tag_resource_id"><span>Resource tag ID:
</span><strong>{{ reportData.tag_resource_id }}</strong></div>
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 f2d715f..1028d72 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
@@ -100,6 +100,11 @@
<span *ngIf="isExpanded; else billing">Billing Report</span>
<ng-template #billing><i class="material-icons">account_balance_wallet</i></ng-template>
</a>
+ <a class="nav-item" [routerLink]="['/audit']"
+ [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}">
+ <span *ngIf="isExpanded; else audit">Audit Report</span>
+ <ng-template #audit><i class="material-icons">library_books</i></ng-template>
+ </a>
</div>
<div>
<a class="nav-item" [routerLink]="['/swagger']" [routerLinkActive]="['active']"
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org