Showing
42 changed files
with
1125 additions
and
35 deletions
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | "version": "3.0.0", | 3 | "version": "3.0.0", |
4 | "scripts": { | 4 | "scripts": { |
5 | "ng": "ng", | 5 | "ng": "ng", |
6 | - "start": "ng serve --host 0.0.0.0 --open", | 6 | + "start": "ng serve --open", |
7 | "build": "ng build", | 7 | "build": "ng build", |
8 | "build:prod": "ng build --prod --vendor-chunk", | 8 | "build:prod": "ng build --prod --vendor-chunk", |
9 | "test": "ng test", | 9 | "test": "ng test", |
@@ -165,7 +165,14 @@ export class AuthService { | @@ -165,7 +165,14 @@ export class AuthService { | ||
165 | if (captureLastUrl) { | 165 | if (captureLastUrl) { |
166 | this.redirectUrl = this.router.url; | 166 | this.redirectUrl = this.router.url; |
167 | } | 167 | } |
168 | - this.clearJwtToken(); | 168 | + this.http.post('/api/auth/logout', null, defaultHttpOptions(true, true)) |
169 | + .subscribe(() => { | ||
170 | + this.clearJwtToken(); | ||
171 | + }, | ||
172 | + () => { | ||
173 | + this.clearJwtToken(); | ||
174 | + } | ||
175 | + ); | ||
169 | } | 176 | } |
170 | 177 | ||
171 | private notifyUserLoaded(isUserLoaded: boolean) { | 178 | private notifyUserLoaded(isUserLoaded: boolean) { |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Injectable } from '@angular/core'; | ||
18 | +import { defaultHttpOptions } from './http-utils'; | ||
19 | +import { Observable } from 'rxjs/index'; | ||
20 | +import { HttpClient } from '@angular/common/http'; | ||
21 | +import { PageLink, TimePageLink } from '@shared/models/page/page-link'; | ||
22 | +import { PageData } from '@shared/models/page/page-data'; | ||
23 | +import { AuditLog } from '@shared/models/audit-log.models'; | ||
24 | +import { EntityId } from '@shared/models/id/entity-id'; | ||
25 | + | ||
26 | +@Injectable({ | ||
27 | + providedIn: 'root' | ||
28 | +}) | ||
29 | +export class AuditLogService { | ||
30 | + | ||
31 | + constructor( | ||
32 | + private http: HttpClient | ||
33 | + ) { } | ||
34 | + | ||
35 | + public getAuditLogs(pageLink: TimePageLink, | ||
36 | + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> { | ||
37 | + return this.http.get<PageData<AuditLog>>(`/api/audit/logs${pageLink.toQuery()}`, | ||
38 | + defaultHttpOptions(ignoreLoading, ignoreErrors)); | ||
39 | + } | ||
40 | + | ||
41 | + public getAuditLogsByCustomerId(customerId: string, pageLink: TimePageLink, | ||
42 | + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> { | ||
43 | + return this.http.get<PageData<AuditLog>>(`/api/audit/logs/customer/${customerId}${pageLink.toQuery()}`, | ||
44 | + defaultHttpOptions(ignoreLoading, ignoreErrors)); | ||
45 | + } | ||
46 | + | ||
47 | + public getAuditLogsByUserId(userId: string, pageLink: TimePageLink, | ||
48 | + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> { | ||
49 | + return this.http.get<PageData<AuditLog>>(`/api/audit/logs/user/${userId}${pageLink.toQuery()}`, | ||
50 | + defaultHttpOptions(ignoreLoading, ignoreErrors)); | ||
51 | + } | ||
52 | + | ||
53 | + public getAuditLogsByEntityId(entityId: EntityId, pageLink: TimePageLink, | ||
54 | + ignoreErrors: boolean = false, ignoreLoading: boolean = false): Observable<PageData<AuditLog>> { | ||
55 | + return this.http.get<PageData<AuditLog>>(`/api/audit/logs/entity/${entityId.entityType}/${entityId.id}${pageLink.toQuery()}`, | ||
56 | + defaultHttpOptions(ignoreLoading, ignoreErrors)); | ||
57 | + } | ||
58 | + | ||
59 | +} |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<mat-toolbar fxLayout="row" color="primary"> | ||
19 | + <h2 translate>audit-log.audit-log-details</h2> | ||
20 | + <span fxFlex></span> | ||
21 | + <button mat-button mat-icon-button | ||
22 | + [mat-dialog-close]="false" | ||
23 | + type="button"> | ||
24 | + <mat-icon class="material-icons">close</mat-icon> | ||
25 | + </button> | ||
26 | +</mat-toolbar> | ||
27 | +<div mat-dialog-content fxLayout="column"> | ||
28 | + <label translate class="tb-title no-padding">audit-log.action-data</label> | ||
29 | + <div #actionDataEditor class="tb-audit-log-action-data"> | ||
30 | + </div> | ||
31 | + <span style="min-height: 30px;"></span> | ||
32 | + <label [fxShow]="displayFailureDetails" translate class="tb-title no-padding">audit-log.failure-details</label> | ||
33 | + <div #failureDetailsEditor [fxShow]="displayFailureDetails" class="tb-audit-log-failure-details"> | ||
34 | + </div> | ||
35 | +</div> | ||
36 | +<div mat-dialog-actions fxLayout="row"> | ||
37 | + <span fxFlex></span> | ||
38 | + <button mat-button color="primary" | ||
39 | + style="margin-right: 20px;" | ||
40 | + type="button" | ||
41 | + [disabled]="(isLoading$ | async)" | ||
42 | + [mat-dialog-close]="false" cdkFocusInitial> | ||
43 | + {{ 'action.close' | translate }} | ||
44 | + </button> | ||
45 | +</div> |
1 | +/** | ||
2 | + * Copyright © 2016-2019 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +:host { | ||
17 | + .tb-audit-log-action-data, | ||
18 | + .tb-audit-log-failure-details { | ||
19 | + width: 100%; | ||
20 | + min-width: 400px; | ||
21 | + height: 100%; | ||
22 | + min-height: 50px; | ||
23 | + border: 1px solid #c0c0c0; | ||
24 | + } | ||
25 | +} |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { | ||
18 | + Component, | ||
19 | + ElementRef, | ||
20 | + Inject, | ||
21 | + OnInit, | ||
22 | + Renderer2, | ||
23 | + ViewChild | ||
24 | +} from '@angular/core'; | ||
25 | +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; | ||
26 | +import { PageComponent } from '@shared/components/page.component'; | ||
27 | +import { Store } from '@ngrx/store'; | ||
28 | +import { AppState } from '@core/core.state'; | ||
29 | +import { TbAnchorComponent } from '@shared/components/tb-anchor.component'; | ||
30 | +import { ActionStatus, AuditLog } from '@shared/models/audit-log.models'; | ||
31 | + | ||
32 | +import * as ace from 'ace-builds'; | ||
33 | + | ||
34 | +export interface AuditLogDetailsDialogData { | ||
35 | + auditLog: AuditLog; | ||
36 | +} | ||
37 | + | ||
38 | +@Component({ | ||
39 | + selector: 'tb-audit-log-details-dialog', | ||
40 | + templateUrl: './audit-log-details-dialog.component.html', | ||
41 | + styleUrls: ['./audit-log-details-dialog.component.scss'] | ||
42 | +}) | ||
43 | +export class AuditLogDetailsDialogComponent extends PageComponent implements OnInit { | ||
44 | + | ||
45 | + @ViewChild('actionDataEditor', {static: true}) | ||
46 | + actionDataEditorElmRef: ElementRef; | ||
47 | + private actionDataEditor: ace.Ace.Editor; | ||
48 | + | ||
49 | + @ViewChild('failureDetailsEditor', {static: true}) | ||
50 | + failureDetailsEditorElmRef: ElementRef; | ||
51 | + private failureDetailsEditor: ace.Ace.Editor; | ||
52 | + | ||
53 | + auditLog: AuditLog; | ||
54 | + displayFailureDetails: boolean; | ||
55 | + actionData: string; | ||
56 | + actionFailureDetails: string; | ||
57 | + | ||
58 | + @ViewChild('entityDetailsForm', {static: true}) entityDetailsFormAnchor: TbAnchorComponent; | ||
59 | + | ||
60 | + constructor(protected store: Store<AppState>, | ||
61 | + @Inject(MAT_DIALOG_DATA) public data: AuditLogDetailsDialogData, | ||
62 | + public dialogRef: MatDialogRef<AuditLogDetailsDialogComponent>, | ||
63 | + private renderer: Renderer2) { | ||
64 | + super(store); | ||
65 | + } | ||
66 | + | ||
67 | + ngOnInit(): void { | ||
68 | + this.auditLog = this.data.auditLog; | ||
69 | + this.displayFailureDetails = this.auditLog.actionStatus === ActionStatus.FAILURE; | ||
70 | + this.actionData = this.auditLog.actionData ? JSON.stringify(this.auditLog.actionData, null, 2) : ''; | ||
71 | + this.actionFailureDetails = this.auditLog.actionFailureDetails; | ||
72 | + | ||
73 | + this.actionDataEditor = this.createEditor(this.actionDataEditorElmRef, this.actionData); | ||
74 | + if (this.displayFailureDetails) { | ||
75 | + this.failureDetailsEditor = this.createEditor(this.failureDetailsEditorElmRef, this.actionFailureDetails); | ||
76 | + } | ||
77 | + } | ||
78 | + | ||
79 | + createEditor(editorElementRef: ElementRef, content: string): ace.Ace.Editor { | ||
80 | + const editorElement = editorElementRef.nativeElement; | ||
81 | + let editorOptions: Partial<ace.Ace.EditorOptions> = { | ||
82 | + mode: 'ace/mode/java', | ||
83 | + theme: 'ace/theme/github', | ||
84 | + showGutter: false, | ||
85 | + showPrintMargin: false, | ||
86 | + readOnly: true | ||
87 | + }; | ||
88 | + | ||
89 | + const advancedOptions = { | ||
90 | + enableSnippets: false, | ||
91 | + enableBasicAutocompletion: false, | ||
92 | + enableLiveAutocompletion: false | ||
93 | + }; | ||
94 | + | ||
95 | + editorOptions = {...editorOptions, ...advancedOptions}; | ||
96 | + const editor = ace.edit(editorElement, editorOptions); | ||
97 | + editor.session.setUseWrapMode(false); | ||
98 | + editor.setValue(content, -1); | ||
99 | + this.updateEditorSize(editorElement, content, editor); | ||
100 | + return editor; | ||
101 | + } | ||
102 | + | ||
103 | + updateEditorSize(editorElement: any, content: string, editor: ace.Ace.Editor) { | ||
104 | + let newHeight = 200; | ||
105 | + let newWidth = 600; | ||
106 | + if (content && content.length > 0) { | ||
107 | + const lines = content.split('\n'); | ||
108 | + newHeight = 16 * lines.length + 16; | ||
109 | + let maxLineLength = 0; | ||
110 | + lines.forEach((row) => { | ||
111 | + const line = row.replace(/\t/g, ' ').replace(/\n/g, ''); | ||
112 | + const lineLength = line.length; | ||
113 | + maxLineLength = Math.max(maxLineLength, lineLength); | ||
114 | + }); | ||
115 | + newWidth = 8 * maxLineLength + 16; | ||
116 | + } | ||
117 | + newHeight = Math.min(400, newHeight); | ||
118 | + this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px'); | ||
119 | + this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px'); | ||
120 | + this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px'); | ||
121 | + editor.resize(); | ||
122 | + } | ||
123 | + | ||
124 | +} |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { | ||
18 | + DateEntityTableColumn, | ||
19 | + EntityTableColumn, | ||
20 | + EntityTableConfig | ||
21 | +} from '@home/models/entity/entities-table-config.models'; | ||
22 | +import { | ||
23 | + actionStatusTranslations, | ||
24 | + actionTypeTranslations, | ||
25 | + AuditLog, | ||
26 | + AuditLogMode | ||
27 | +} from '@shared/models/audit-log.models'; | ||
28 | +import { | ||
29 | + EntityTypeResource, | ||
30 | + EntityTypeTranslation, | ||
31 | + entityTypeTranslations | ||
32 | +} from '@shared/models/entity-type.models'; | ||
33 | +import { AuditLogService } from '@core/http/audit-log.service'; | ||
34 | +import { TranslateService } from '@ngx-translate/core'; | ||
35 | +import { DatePipe } from '@angular/common'; | ||
36 | +import { Direction } from '@shared/models/page/sort-order'; | ||
37 | +import { MatDialog } from '@angular/material'; | ||
38 | +import { PageLink, TimePageLink } from '@shared/models/page/page-link'; | ||
39 | +import { Observable } from 'rxjs'; | ||
40 | +import { PageData } from '@shared/models/page/page-data'; | ||
41 | +import { EntityId } from '@shared/models/id/entity-id'; | ||
42 | +import { UserId } from '@shared/models/id/user-id'; | ||
43 | +import { CustomerId } from '@shared/models/id/customer-id'; | ||
44 | +import { | ||
45 | + AuditLogDetailsDialogComponent, | ||
46 | + AuditLogDetailsDialogData | ||
47 | +} from '@home/components/audit-log/audit-log-details-dialog.component'; | ||
48 | + | ||
49 | +export class AuditLogTableConfig extends EntityTableConfig<AuditLog, TimePageLink> { | ||
50 | + | ||
51 | + constructor(private auditLogService: AuditLogService, | ||
52 | + private translate: TranslateService, | ||
53 | + private datePipe: DatePipe, | ||
54 | + private dialog: MatDialog, | ||
55 | + private auditLogMode: AuditLogMode = AuditLogMode.TENANT, | ||
56 | + public entityId: EntityId = null, | ||
57 | + public userId: UserId = null, | ||
58 | + public customerId: CustomerId = null, | ||
59 | + updateOnInit = true) { | ||
60 | + super(); | ||
61 | + this.loadDataOnInit = updateOnInit; | ||
62 | + this.tableTitle = ''; | ||
63 | + this.useTimePageLink = true; | ||
64 | + this.detailsPanelEnabled = false; | ||
65 | + this.selectionEnabled = false; | ||
66 | + this.searchEnabled = true; | ||
67 | + this.addEnabled = false; | ||
68 | + this.entitiesDeleteEnabled = false; | ||
69 | + this.actionsColumnTitle = 'audit-log.details'; | ||
70 | + this.entityTranslations = { | ||
71 | + noEntities: 'audit-log.no-audit-logs-prompt', | ||
72 | + search: 'audit-log.search' | ||
73 | + }; | ||
74 | + this.entityResources = { | ||
75 | + } as EntityTypeResource; | ||
76 | + | ||
77 | + this.entitiesFetchFunction = pageLink => this.fetchAuditLogs(pageLink); | ||
78 | + | ||
79 | + this.defaultSortOrder = {property: 'createdTime', direction: Direction.DESC}; | ||
80 | + | ||
81 | + this.columns.push( | ||
82 | + new DateEntityTableColumn<AuditLog>('createdTime', 'audit-log.timestamp', this.datePipe, '150px')); | ||
83 | + | ||
84 | + if (this.auditLogMode !== AuditLogMode.ENTITY) { | ||
85 | + this.columns.push( | ||
86 | + new EntityTableColumn<AuditLog>('entityType', 'audit-log.entity-type', '100%', | ||
87 | + (entity) => translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type)), | ||
88 | + new EntityTableColumn<AuditLog>('entityName', 'audit-log.entity-name'), | ||
89 | + ); | ||
90 | + } | ||
91 | + | ||
92 | + if (this.auditLogMode !== AuditLogMode.USER) { | ||
93 | + this.columns.push( | ||
94 | + new EntityTableColumn<AuditLog>('userName', 'audit-log.user') | ||
95 | + ); | ||
96 | + } | ||
97 | + | ||
98 | + this.columns.push( | ||
99 | + new EntityTableColumn<AuditLog>('actionType', 'audit-log.type', '100%', | ||
100 | + (entity) => translate.instant(actionTypeTranslations.get(entity.actionType))), | ||
101 | + new EntityTableColumn<AuditLog>('actionStatus', 'audit-log.status', '100%', | ||
102 | + (entity) => translate.instant(actionStatusTranslations.get(entity.actionStatus))) | ||
103 | + ); | ||
104 | + | ||
105 | + this.cellActionDescriptors.push( | ||
106 | + { | ||
107 | + name: this.translate.instant('audit-log.details'), | ||
108 | + icon: 'more_horiz', | ||
109 | + isEnabled: () => true, | ||
110 | + onAction: ($event, entity) => this.showAuditLogDetails(entity) | ||
111 | + } | ||
112 | + ); | ||
113 | + } | ||
114 | + | ||
115 | + fetchAuditLogs(pageLink: TimePageLink): Observable<PageData<AuditLog>> { | ||
116 | + switch (this.auditLogMode) { | ||
117 | + case AuditLogMode.TENANT: | ||
118 | + return this.auditLogService.getAuditLogs(pageLink); | ||
119 | + case AuditLogMode.ENTITY: | ||
120 | + return this.auditLogService.getAuditLogsByEntityId(this.entityId, pageLink); | ||
121 | + case AuditLogMode.USER: | ||
122 | + return this.auditLogService.getAuditLogsByUserId(this.userId.id, pageLink); | ||
123 | + case AuditLogMode.CUSTOMER: | ||
124 | + return this.auditLogService.getAuditLogsByCustomerId(this.customerId.id, pageLink); | ||
125 | + } | ||
126 | + } | ||
127 | + | ||
128 | + showAuditLogDetails(entity: AuditLog) { | ||
129 | + this.dialog.open<AuditLogDetailsDialogComponent, AuditLogDetailsDialogData>(AuditLogDetailsDialogComponent, { | ||
130 | + disableClose: true, | ||
131 | + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], | ||
132 | + data: { | ||
133 | + auditLog: entity | ||
134 | + } | ||
135 | + }); | ||
136 | + } | ||
137 | + | ||
138 | +} |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<tb-entities-table [entitiesTableConfig]="auditLogTableConfig" [ngClass]="{'tb-details-mode': detailsMode}"></tb-entities-table> |
1 | +/** | ||
2 | + * Copyright © 2016-2019 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +:host ::ng-deep { | ||
17 | + tb-entities-table.tb-details-mode { | ||
18 | + .mat-drawer-container { | ||
19 | + background-color: white; | ||
20 | + } | ||
21 | + } | ||
22 | +} |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Component, Input, OnInit, ViewChild } from '@angular/core'; | ||
18 | +import { AuditLogService } from '@core/http/audit-log.service'; | ||
19 | +import { TranslateService } from '@ngx-translate/core'; | ||
20 | +import { DatePipe } from '@angular/common'; | ||
21 | +import { MatDialog } from '@angular/material'; | ||
22 | +import { AuditLogMode } from '@shared/models/audit-log.models'; | ||
23 | +import { EntityId } from '@shared/models/id/entity-id'; | ||
24 | +import { UserId } from '@shared/models/id/user-id'; | ||
25 | +import { CustomerId } from '@shared/models/id/customer-id'; | ||
26 | +import { AuditLogTableConfig } from '@home/components/audit-log/audit-log-table-config'; | ||
27 | +import { EntitiesTableComponent } from '@home/components/entity/entities-table.component'; | ||
28 | +import { Store } from '@ngrx/store'; | ||
29 | +import { AppState } from '@core/core.state'; | ||
30 | +import { Authority } from '@shared/models/authority.enum'; | ||
31 | +import { getCurrentAuthUser } from '@core/auth/auth.selectors'; | ||
32 | + | ||
33 | +@Component({ | ||
34 | + selector: 'tb-audit-log-table', | ||
35 | + templateUrl: './audit-log-table.component.html', | ||
36 | + styleUrls: ['./audit-log-table.component.scss'] | ||
37 | +}) | ||
38 | +export class AuditLogTableComponent implements OnInit { | ||
39 | + | ||
40 | + @Input() | ||
41 | + auditLogMode: AuditLogMode; | ||
42 | + | ||
43 | + @Input() | ||
44 | + detailsMode: boolean; | ||
45 | + | ||
46 | + activeValue = false; | ||
47 | + dirtyValue = false; | ||
48 | + entityIdValue: EntityId; | ||
49 | + userIdValue: UserId; | ||
50 | + customerIdValue: CustomerId; | ||
51 | + | ||
52 | + @Input() | ||
53 | + set active(active: boolean) { | ||
54 | + if (this.activeValue !== active) { | ||
55 | + this.activeValue = active; | ||
56 | + if (this.activeValue && this.dirtyValue) { | ||
57 | + this.dirtyValue = false; | ||
58 | + this.entitiesTable.updateData(); | ||
59 | + } | ||
60 | + } | ||
61 | + } | ||
62 | + | ||
63 | + @Input() | ||
64 | + set entityId(entityId: EntityId) { | ||
65 | + this.entityIdValue = entityId; | ||
66 | + if (this.auditLogTableConfig && this.auditLogTableConfig.entityId !== entityId) { | ||
67 | + this.auditLogTableConfig.entityId = entityId; | ||
68 | + this.entitiesTable.resetSortAndFilter(this.activeValue); | ||
69 | + if (!this.activeValue) { | ||
70 | + this.dirtyValue = true; | ||
71 | + } | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + @Input() | ||
76 | + set userId(userId: UserId) { | ||
77 | + this.userIdValue = userId; | ||
78 | + if (this.auditLogTableConfig && this.auditLogTableConfig.userId !== userId) { | ||
79 | + this.auditLogTableConfig.userId = userId; | ||
80 | + this.entitiesTable.resetSortAndFilter(this.activeValue); | ||
81 | + if (!this.activeValue) { | ||
82 | + this.dirtyValue = true; | ||
83 | + } | ||
84 | + } | ||
85 | + } | ||
86 | + | ||
87 | + @Input() | ||
88 | + set customerId(customerId: CustomerId) { | ||
89 | + this.customerIdValue = customerId; | ||
90 | + if (this.auditLogTableConfig && this.auditLogTableConfig.customerId !== customerId) { | ||
91 | + this.auditLogTableConfig.customerId = customerId; | ||
92 | + this.entitiesTable.resetSortAndFilter(this.activeValue); | ||
93 | + if (!this.activeValue) { | ||
94 | + this.dirtyValue = true; | ||
95 | + } | ||
96 | + } | ||
97 | + } | ||
98 | + | ||
99 | + @ViewChild(EntitiesTableComponent, {static: true}) entitiesTable: EntitiesTableComponent; | ||
100 | + | ||
101 | + auditLogTableConfig: AuditLogTableConfig; | ||
102 | + | ||
103 | + constructor(private auditLogService: AuditLogService, | ||
104 | + private translate: TranslateService, | ||
105 | + private datePipe: DatePipe, | ||
106 | + private dialog: MatDialog, | ||
107 | + private store: Store<AppState>) { | ||
108 | + } | ||
109 | + | ||
110 | + ngOnInit() { | ||
111 | + let updateOnInit = this.activeValue; | ||
112 | + this.dirtyValue = !this.activeValue; | ||
113 | + if (!this.auditLogMode) { | ||
114 | + const authUser = getCurrentAuthUser(this.store); | ||
115 | + if (authUser.authority === Authority.TENANT_ADMIN) { | ||
116 | + this.auditLogMode = AuditLogMode.TENANT; | ||
117 | + } | ||
118 | + updateOnInit = true; | ||
119 | + } | ||
120 | + this.auditLogTableConfig = new AuditLogTableConfig( | ||
121 | + this.auditLogService, | ||
122 | + this.translate, | ||
123 | + this.datePipe, | ||
124 | + this.dialog, | ||
125 | + this.auditLogMode, | ||
126 | + this.entityIdValue, | ||
127 | + this.userIdValue, | ||
128 | + this.customerIdValue, | ||
129 | + updateOnInit | ||
130 | + ); | ||
131 | + } | ||
132 | + | ||
133 | +} |
@@ -158,10 +158,10 @@ | @@ -158,10 +158,10 @@ | ||
158 | [ngStyle]="cellStyle(entity, column, row, col)"></mat-cell> | 158 | [ngStyle]="cellStyle(entity, column, row, col)"></mat-cell> |
159 | </ng-container> | 159 | </ng-container> |
160 | <ng-container matColumnDef="actions" stickyEnd> | 160 | <ng-container matColumnDef="actions" stickyEnd> |
161 | - <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px' }"> | 161 | + <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px', maxWidth: (cellActionDescriptors.length * 40) + 'px' }"> |
162 | {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }} | 162 | {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }} |
163 | </mat-header-cell> | 163 | </mat-header-cell> |
164 | - <mat-cell *matCellDef="let entity" [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px' }"> | 164 | + <mat-cell *matCellDef="let entity" [ngStyle.gt-md]="{ minWidth: (cellActionDescriptors.length * 40) + 'px', maxWidth: (cellActionDescriptors.length * 40) + 'px' }"> |
165 | <div fxHide fxShow.gt-md fxFlex fxLayout="row" fxLayoutAlign="end"> | 165 | <div fxHide fxShow.gt-md fxFlex fxLayout="row" fxLayoutAlign="end"> |
166 | <button mat-button mat-icon-button [disabled]="isLoading$ | async" | 166 | <button mat-button mat-icon-button [disabled]="isLoading$ | async" |
167 | [fxShow]="actionDescriptor.isEnabled(entity)" *ngFor="let actionDescriptor of cellActionDescriptors" | 167 | [fxShow]="actionDescriptor.isEnabled(entity)" *ngFor="let actionDescriptor of cellActionDescriptors" |
@@ -32,9 +32,22 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod | @@ -32,9 +32,22 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod | ||
32 | import { MatTab } from '@angular/material'; | 32 | import { MatTab } from '@angular/material'; |
33 | import { EntityAction } from '@home/models/entity/entity-component.models'; | 33 | import { EntityAction } from '@home/models/entity/entity-component.models'; |
34 | import { BehaviorSubject } from 'rxjs'; | 34 | import { BehaviorSubject } from 'rxjs'; |
35 | +import { Authority } from '@app/shared/models/authority.enum'; | ||
36 | +import { selectAuthUser, getCurrentAuthUser } from '@core/auth/auth.selectors'; | ||
37 | +import { AuthUser } from '@shared/models/user.model'; | ||
38 | +import { EntityType } from '@shared/models/entity-type.models'; | ||
39 | +import { AuditLogMode } from '@shared/models/audit-log.models'; | ||
35 | 40 | ||
36 | export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit, AfterViewInit { | 41 | export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends PageComponent implements OnInit, AfterViewInit { |
37 | 42 | ||
43 | + authorities = Authority; | ||
44 | + | ||
45 | + entityTypes = EntityType; | ||
46 | + | ||
47 | + auditLogModes = AuditLogMode; | ||
48 | + | ||
49 | + authUser: AuthUser; | ||
50 | + | ||
38 | entityValue: T; | 51 | entityValue: T; |
39 | 52 | ||
40 | @ViewChildren(MatTab) entityTabs: QueryList<MatTab>; | 53 | @ViewChildren(MatTab) entityTabs: QueryList<MatTab>; |
@@ -68,6 +81,7 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag | @@ -68,6 +81,7 @@ export abstract class EntityTabsComponent<T extends BaseData<HasId>> extends Pag | ||
68 | 81 | ||
69 | protected constructor(protected store: Store<AppState>) { | 82 | protected constructor(protected store: Store<AppState>) { |
70 | super(store); | 83 | super(store); |
84 | + this.authUser = getCurrentAuthUser(store); | ||
71 | } | 85 | } |
72 | 86 | ||
73 | ngOnInit() { | 87 | ngOnInit() { |
@@ -22,10 +22,13 @@ import {EntitiesTableComponent} from './entity/entities-table.component'; | @@ -22,10 +22,13 @@ import {EntitiesTableComponent} from './entity/entities-table.component'; | ||
22 | import {DetailsPanelComponent} from './details-panel.component'; | 22 | import {DetailsPanelComponent} from './details-panel.component'; |
23 | import {EntityDetailsPanelComponent} from './entity/entity-details-panel.component'; | 23 | import {EntityDetailsPanelComponent} from './entity/entity-details-panel.component'; |
24 | import {ContactComponent} from './contact.component'; | 24 | import {ContactComponent} from './contact.component'; |
25 | +import { AuditLogDetailsDialogComponent } from './audit-log/audit-log-details-dialog.component'; | ||
26 | +import { AuditLogTableComponent } from './audit-log/audit-log-table.component'; | ||
25 | 27 | ||
26 | @NgModule({ | 28 | @NgModule({ |
27 | entryComponents: [ | 29 | entryComponents: [ |
28 | - AddEntityDialogComponent | 30 | + AddEntityDialogComponent, |
31 | + AuditLogDetailsDialogComponent | ||
29 | ], | 32 | ], |
30 | declarations: | 33 | declarations: |
31 | [ | 34 | [ |
@@ -34,6 +37,8 @@ import {ContactComponent} from './contact.component'; | @@ -34,6 +37,8 @@ import {ContactComponent} from './contact.component'; | ||
34 | DetailsPanelComponent, | 37 | DetailsPanelComponent, |
35 | EntityDetailsPanelComponent, | 38 | EntityDetailsPanelComponent, |
36 | ContactComponent, | 39 | ContactComponent, |
40 | + AuditLogTableComponent, | ||
41 | + AuditLogDetailsDialogComponent | ||
37 | ], | 42 | ], |
38 | imports: [ | 43 | imports: [ |
39 | CommonModule, | 44 | CommonModule, |
@@ -44,7 +49,8 @@ import {ContactComponent} from './contact.component'; | @@ -44,7 +49,8 @@ import {ContactComponent} from './contact.component'; | ||
44 | AddEntityDialogComponent, | 49 | AddEntityDialogComponent, |
45 | DetailsPanelComponent, | 50 | DetailsPanelComponent, |
46 | EntityDetailsPanelComponent, | 51 | EntityDetailsPanelComponent, |
47 | - ContactComponent | 52 | + ContactComponent, |
53 | + AuditLogTableComponent | ||
48 | ] | 54 | ] |
49 | }) | 55 | }) |
50 | export class HomeComponentsModule { } | 56 | export class HomeComponentsModule { } |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" | ||
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | ||
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ||
21 | +</mat-tab> |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Component } from '@angular/core'; | ||
18 | +import { Store } from '@ngrx/store'; | ||
19 | +import { AppState } from '@core/core.state'; | ||
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | ||
21 | +import { AssetInfo } from '@app/shared/models/asset.models'; | ||
22 | + | ||
23 | +@Component({ | ||
24 | + selector: 'tb-asset-tabs', | ||
25 | + templateUrl: './asset-tabs.component.html', | ||
26 | + styleUrls: [] | ||
27 | +}) | ||
28 | +export class AssetTabsComponent extends EntityTabsComponent<AssetInfo> { | ||
29 | + | ||
30 | + constructor(protected store: Store<AppState>) { | ||
31 | + super(store); | ||
32 | + } | ||
33 | + | ||
34 | + ngOnInit() { | ||
35 | + super.ngOnInit(); | ||
36 | + } | ||
37 | + | ||
38 | +} |
@@ -22,14 +22,17 @@ import {AssetComponent} from './asset.component'; | @@ -22,14 +22,17 @@ import {AssetComponent} from './asset.component'; | ||
22 | import {AssetTableHeaderComponent} from './asset-table-header.component'; | 22 | import {AssetTableHeaderComponent} from './asset-table-header.component'; |
23 | import {AssetRoutingModule} from './asset-routing.module'; | 23 | import {AssetRoutingModule} from './asset-routing.module'; |
24 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; | 24 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
25 | +import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component'; | ||
25 | 26 | ||
26 | @NgModule({ | 27 | @NgModule({ |
27 | entryComponents: [ | 28 | entryComponents: [ |
28 | AssetComponent, | 29 | AssetComponent, |
30 | + AssetTabsComponent, | ||
29 | AssetTableHeaderComponent | 31 | AssetTableHeaderComponent |
30 | ], | 32 | ], |
31 | declarations: [ | 33 | declarations: [ |
32 | AssetComponent, | 34 | AssetComponent, |
35 | + AssetTabsComponent, | ||
33 | AssetTableHeaderComponent | 36 | AssetTableHeaderComponent |
34 | ], | 37 | ], |
35 | imports: [ | 38 | imports: [ |
@@ -55,6 +55,7 @@ import {AssetService} from '@app/core/http/asset.service'; | @@ -55,6 +55,7 @@ import {AssetService} from '@app/core/http/asset.service'; | ||
55 | import {AssetComponent} from '@modules/home/pages/asset/asset.component'; | 55 | import {AssetComponent} from '@modules/home/pages/asset/asset.component'; |
56 | import {AssetTableHeaderComponent} from '@modules/home/pages/asset/asset-table-header.component'; | 56 | import {AssetTableHeaderComponent} from '@modules/home/pages/asset/asset-table-header.component'; |
57 | import {AssetId} from '@app/shared/models/id/asset-id'; | 57 | import {AssetId} from '@app/shared/models/id/asset-id'; |
58 | +import { AssetTabsComponent } from '@home/pages/asset/asset-tabs.component'; | ||
58 | 59 | ||
59 | @Injectable() | 60 | @Injectable() |
60 | export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<AssetInfo>> { | 61 | export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<AssetInfo>> { |
@@ -75,6 +76,7 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse | @@ -75,6 +76,7 @@ export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<Asse | ||
75 | 76 | ||
76 | this.config.entityType = EntityType.ASSET; | 77 | this.config.entityType = EntityType.ASSET; |
77 | this.config.entityComponent = AssetComponent; | 78 | this.config.entityComponent = AssetComponent; |
79 | + this.config.entityTabsComponent = AssetTabsComponent; | ||
78 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.ASSET); | 80 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.ASSET); |
79 | this.config.entityResources = entityTypeResources.get(EntityType.ASSET); | 81 | this.config.entityResources = entityTypeResources.get(EntityType.ASSET); |
80 | 82 |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { NgModule } from '@angular/core'; | ||
18 | +import { RouterModule, Routes } from '@angular/router'; | ||
19 | +import { Authority } from '@shared/models/authority.enum'; | ||
20 | +import { AuditLogTableComponent } from '@home/components/audit-log/audit-log-table.component'; | ||
21 | + | ||
22 | +const routes: Routes = [ | ||
23 | + { | ||
24 | + path: 'auditLogs', | ||
25 | + component: AuditLogTableComponent, | ||
26 | + data: { | ||
27 | + auth: [Authority.TENANT_ADMIN], | ||
28 | + title: 'audit-log.audit-logs', | ||
29 | + breadcrumb: { | ||
30 | + label: 'audit-log.audit-logs', | ||
31 | + icon: 'track_changes' | ||
32 | + } | ||
33 | + } | ||
34 | + } | ||
35 | +]; | ||
36 | + | ||
37 | +@NgModule({ | ||
38 | + imports: [RouterModule.forChild(routes)], | ||
39 | + exports: [RouterModule] | ||
40 | +}) | ||
41 | +export class AuditLogRoutingModule { } |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { NgModule } from '@angular/core'; | ||
18 | +import { CommonModule } from '@angular/common'; | ||
19 | +import { SharedModule } from '@shared/shared.module'; | ||
20 | +import { AuditLogRoutingModule } from '@modules/home/pages/audit-log/audit-log-routing.module'; | ||
21 | + | ||
22 | +@NgModule({ | ||
23 | + declarations: [ | ||
24 | + ], | ||
25 | + imports: [ | ||
26 | + CommonModule, | ||
27 | + SharedModule, | ||
28 | + AuditLogRoutingModule | ||
29 | + ] | ||
30 | +}) | ||
31 | +export class AuditLogModule { } |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" | ||
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | ||
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.CUSTOMER" [customerId]="entity.id" detailsMode="true"></tb-audit-log-table> | ||
21 | +</mat-tab> |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Component } from '@angular/core'; | ||
18 | +import { Store } from '@ngrx/store'; | ||
19 | +import { AppState } from '@core/core.state'; | ||
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | ||
21 | +import { Customer } from '@shared/models/customer.model'; | ||
22 | + | ||
23 | +@Component({ | ||
24 | + selector: 'tb-customer-tabs', | ||
25 | + templateUrl: './customer-tabs.component.html', | ||
26 | + styleUrls: [] | ||
27 | +}) | ||
28 | +export class CustomerTabsComponent extends EntityTabsComponent<Customer> { | ||
29 | + | ||
30 | + constructor(protected store: Store<AppState>) { | ||
31 | + super(store); | ||
32 | + } | ||
33 | + | ||
34 | + ngOnInit() { | ||
35 | + super.ngOnInit(); | ||
36 | + } | ||
37 | + | ||
38 | +} |
@@ -20,13 +20,16 @@ import { SharedModule } from '@shared/shared.module'; | @@ -20,13 +20,16 @@ import { SharedModule } from '@shared/shared.module'; | ||
20 | import {CustomerComponent} from '@modules/home/pages/customer/customer.component'; | 20 | import {CustomerComponent} from '@modules/home/pages/customer/customer.component'; |
21 | import {CustomerRoutingModule} from './customer-routing.module'; | 21 | import {CustomerRoutingModule} from './customer-routing.module'; |
22 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; | 22 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
23 | +import { CustomerTabsComponent } from '@home/pages/customer/customer-tabs.component'; | ||
23 | 24 | ||
24 | @NgModule({ | 25 | @NgModule({ |
25 | entryComponents: [ | 26 | entryComponents: [ |
26 | - CustomerComponent | 27 | + CustomerComponent, |
28 | + CustomerTabsComponent | ||
27 | ], | 29 | ], |
28 | declarations: [ | 30 | declarations: [ |
29 | - CustomerComponent | 31 | + CustomerComponent, |
32 | + CustomerTabsComponent | ||
30 | ], | 33 | ], |
31 | imports: [ | 34 | imports: [ |
32 | CommonModule, | 35 | CommonModule, |
@@ -35,6 +35,7 @@ import { EntityAction } from '@home/models/entity/entity-component.models'; | @@ -35,6 +35,7 @@ import { EntityAction } from '@home/models/entity/entity-component.models'; | ||
35 | import {Customer} from '@app/shared/models/customer.model'; | 35 | import {Customer} from '@app/shared/models/customer.model'; |
36 | import {CustomerService} from '@app/core/http/customer.service'; | 36 | import {CustomerService} from '@app/core/http/customer.service'; |
37 | import {CustomerComponent} from '@modules/home/pages/customer/customer.component'; | 37 | import {CustomerComponent} from '@modules/home/pages/customer/customer.component'; |
38 | +import { CustomerTabsComponent } from '@home/pages/customer/customer-tabs.component'; | ||
38 | 39 | ||
39 | @Injectable() | 40 | @Injectable() |
40 | export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<Customer>> { | 41 | export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<Customer>> { |
@@ -48,6 +49,7 @@ export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<C | @@ -48,6 +49,7 @@ export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<C | ||
48 | 49 | ||
49 | this.config.entityType = EntityType.CUSTOMER; | 50 | this.config.entityType = EntityType.CUSTOMER; |
50 | this.config.entityComponent = CustomerComponent; | 51 | this.config.entityComponent = CustomerComponent; |
52 | + this.config.entityTabsComponent = CustomerTabsComponent; | ||
51 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.CUSTOMER); | 53 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.CUSTOMER); |
52 | this.config.entityResources = entityTypeResources.get(EntityType.CUSTOMER); | 54 | this.config.entityResources = entityTypeResources.get(EntityType.CUSTOMER); |
53 | 55 |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" | ||
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | ||
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ||
21 | +</mat-tab> |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Component } from '@angular/core'; | ||
18 | +import { Store } from '@ngrx/store'; | ||
19 | +import { AppState } from '@core/core.state'; | ||
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | ||
21 | +import { Dashboard } from '@shared/models/dashboard.models'; | ||
22 | + | ||
23 | +@Component({ | ||
24 | + selector: 'tb-dashboard-tabs', | ||
25 | + templateUrl: './dashboard-tabs.component.html', | ||
26 | + styleUrls: [] | ||
27 | +}) | ||
28 | +export class DashboardTabsComponent extends EntityTabsComponent<Dashboard> { | ||
29 | + | ||
30 | + constructor(protected store: Store<AppState>) { | ||
31 | + super(store); | ||
32 | + } | ||
33 | + | ||
34 | + ngOnInit() { | ||
35 | + super.ngOnInit(); | ||
36 | + } | ||
37 | + | ||
38 | +} |
@@ -23,15 +23,18 @@ import {ManageDashboardCustomersDialogComponent} from '@modules/home/pages/dashb | @@ -23,15 +23,18 @@ import {ManageDashboardCustomersDialogComponent} from '@modules/home/pages/dashb | ||
23 | import {DashboardRoutingModule} from './dashboard-routing.module'; | 23 | import {DashboardRoutingModule} from './dashboard-routing.module'; |
24 | import {MakeDashboardPublicDialogComponent} from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component'; | 24 | import {MakeDashboardPublicDialogComponent} from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component'; |
25 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; | 25 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
26 | +import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component'; | ||
26 | 27 | ||
27 | @NgModule({ | 28 | @NgModule({ |
28 | entryComponents: [ | 29 | entryComponents: [ |
29 | DashboardFormComponent, | 30 | DashboardFormComponent, |
31 | + DashboardTabsComponent, | ||
30 | ManageDashboardCustomersDialogComponent, | 32 | ManageDashboardCustomersDialogComponent, |
31 | MakeDashboardPublicDialogComponent | 33 | MakeDashboardPublicDialogComponent |
32 | ], | 34 | ], |
33 | declarations: [ | 35 | declarations: [ |
34 | DashboardFormComponent, | 36 | DashboardFormComponent, |
37 | + DashboardTabsComponent, | ||
35 | ManageDashboardCustomersDialogComponent, | 38 | ManageDashboardCustomersDialogComponent, |
36 | MakeDashboardPublicDialogComponent | 39 | MakeDashboardPublicDialogComponent |
37 | ], | 40 | ], |
@@ -62,6 +62,7 @@ import { | @@ -62,6 +62,7 @@ import { | ||
62 | MakeDashboardPublicDialogComponent, | 62 | MakeDashboardPublicDialogComponent, |
63 | MakeDashboardPublicDialogData | 63 | MakeDashboardPublicDialogData |
64 | } from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component'; | 64 | } from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component'; |
65 | +import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component'; | ||
65 | 66 | ||
66 | @Injectable() | 67 | @Injectable() |
67 | export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<DashboardInfo | Dashboard>> { | 68 | export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<DashboardInfo | Dashboard>> { |
@@ -79,6 +80,7 @@ export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig< | @@ -79,6 +80,7 @@ export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig< | ||
79 | 80 | ||
80 | this.config.entityType = EntityType.DASHBOARD; | 81 | this.config.entityType = EntityType.DASHBOARD; |
81 | this.config.entityComponent = DashboardFormComponent; | 82 | this.config.entityComponent = DashboardFormComponent; |
83 | + this.config.entityTabsComponent = DashboardTabsComponent; | ||
82 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.DASHBOARD); | 84 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.DASHBOARD); |
83 | this.config.entityResources = entityTypeResources.get(EntityType.DASHBOARD); | 85 | this.config.entityResources = entityTypeResources.get(EntityType.DASHBOARD); |
84 | 86 |
@@ -15,15 +15,7 @@ | @@ -15,15 +15,7 @@ | ||
15 | limitations under the License. | 15 | limitations under the License. |
16 | 16 | ||
17 | --> | 17 | --> |
18 | -<mat-tab label="{{entity?.name}}"> | ||
19 | - Hobotok<br/> | ||
20 | - {{ entity | json }} | ||
21 | -</mat-tab> | ||
22 | -<mat-tab *ngIf="entity?.additionalInfo?.gateway" label="Gateway"> | ||
23 | - Hobotok 2<br/> | ||
24 | - {{ entity | json }} | ||
25 | -</mat-tab> | ||
26 | -<mat-tab label="{{ 'extension.extensions' | translate }}"> | ||
27 | - Hobotok 2<br/> | ||
28 | - {{ entity | json }} | 18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | ||
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ||
29 | </mat-tab> | 21 | </mat-tab> |
@@ -28,8 +28,6 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone | @@ -28,8 +28,6 @@ import { EntityTabsComponent } from '../../components/entity/entity-tabs.compone | ||
28 | }) | 28 | }) |
29 | export class DeviceTabsComponent extends EntityTabsComponent<DeviceInfo> { | 29 | export class DeviceTabsComponent extends EntityTabsComponent<DeviceInfo> { |
30 | 30 | ||
31 | - entityType = EntityType; | ||
32 | - | ||
33 | constructor(protected store: Store<AppState>) { | 31 | constructor(protected store: Store<AppState>) { |
34 | super(store); | 32 | super(store); |
35 | } | 33 | } |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" | ||
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | ||
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ||
21 | +</mat-tab> |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Component } from '@angular/core'; | ||
18 | +import { Store } from '@ngrx/store'; | ||
19 | +import { AppState } from '@core/core.state'; | ||
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | ||
21 | +import { EntityViewInfo } from '@app/shared/models/entity-view.models'; | ||
22 | + | ||
23 | +@Component({ | ||
24 | + selector: 'tb-entity-view-tabs', | ||
25 | + templateUrl: './entity-view-tabs.component.html', | ||
26 | + styleUrls: [] | ||
27 | +}) | ||
28 | +export class EntityViewTabsComponent extends EntityTabsComponent<EntityViewInfo> { | ||
29 | + | ||
30 | + constructor(protected store: Store<AppState>) { | ||
31 | + super(store); | ||
32 | + } | ||
33 | + | ||
34 | + ngOnInit() { | ||
35 | + super.ngOnInit(); | ||
36 | + } | ||
37 | + | ||
38 | +} |
@@ -22,14 +22,17 @@ import {EntityViewComponent} from '@modules/home/pages/entity-view/entity-view.c | @@ -22,14 +22,17 @@ import {EntityViewComponent} from '@modules/home/pages/entity-view/entity-view.c | ||
22 | import {EntityViewTableHeaderComponent} from './entity-view-table-header.component'; | 22 | import {EntityViewTableHeaderComponent} from './entity-view-table-header.component'; |
23 | import {EntityViewRoutingModule} from './entity-view-routing.module'; | 23 | import {EntityViewRoutingModule} from './entity-view-routing.module'; |
24 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; | 24 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
25 | +import { EntityViewTabsComponent } from '@home/pages/entity-view/entity-view-tabs.component'; | ||
25 | 26 | ||
26 | @NgModule({ | 27 | @NgModule({ |
27 | entryComponents: [ | 28 | entryComponents: [ |
28 | EntityViewComponent, | 29 | EntityViewComponent, |
30 | + EntityViewTabsComponent, | ||
29 | EntityViewTableHeaderComponent | 31 | EntityViewTableHeaderComponent |
30 | ], | 32 | ], |
31 | declarations: [ | 33 | declarations: [ |
32 | EntityViewComponent, | 34 | EntityViewComponent, |
35 | + EntityViewTabsComponent, | ||
33 | EntityViewTableHeaderComponent | 36 | EntityViewTableHeaderComponent |
34 | ], | 37 | ], |
35 | imports: [ | 38 | imports: [ |
@@ -55,6 +55,7 @@ import {EntityViewService} from '@core/http/entity-view.service'; | @@ -55,6 +55,7 @@ import {EntityViewService} from '@core/http/entity-view.service'; | ||
55 | import {EntityViewComponent} from '@modules/home/pages/entity-view/entity-view.component'; | 55 | import {EntityViewComponent} from '@modules/home/pages/entity-view/entity-view.component'; |
56 | import {EntityViewTableHeaderComponent} from '@modules/home/pages/entity-view/entity-view-table-header.component'; | 56 | import {EntityViewTableHeaderComponent} from '@modules/home/pages/entity-view/entity-view-table-header.component'; |
57 | import {EntityViewId} from '@shared/models/id/entity-view-id'; | 57 | import {EntityViewId} from '@shared/models/id/entity-view-id'; |
58 | +import { EntityViewTabsComponent } from '@home/pages/entity-view/entity-view-tabs.component'; | ||
58 | 59 | ||
59 | @Injectable() | 60 | @Injectable() |
60 | export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig<EntityViewInfo>> { | 61 | export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig<EntityViewInfo>> { |
@@ -75,6 +76,7 @@ export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig | @@ -75,6 +76,7 @@ export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig | ||
75 | 76 | ||
76 | this.config.entityType = EntityType.ENTITY_VIEW; | 77 | this.config.entityType = EntityType.ENTITY_VIEW; |
77 | this.config.entityComponent = EntityViewComponent; | 78 | this.config.entityComponent = EntityViewComponent; |
79 | + this.config.entityTabsComponent = EntityViewTabsComponent; | ||
78 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.ENTITY_VIEW); | 80 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.ENTITY_VIEW); |
79 | this.config.entityResources = entityTypeResources.get(EntityType.ENTITY_VIEW); | 81 | this.config.entityResources = entityTypeResources.get(EntityType.ENTITY_VIEW); |
80 | 82 |
@@ -21,7 +21,7 @@ import { HomeLinksModule } from './home-links/home-links.module'; | @@ -21,7 +21,7 @@ import { HomeLinksModule } from './home-links/home-links.module'; | ||
21 | import { ProfileModule } from './profile/profile.module'; | 21 | import { ProfileModule } from './profile/profile.module'; |
22 | import { TenantModule } from '@modules/home/pages/tenant/tenant.module'; | 22 | import { TenantModule } from '@modules/home/pages/tenant/tenant.module'; |
23 | import { CustomerModule } from '@modules/home/pages/customer/customer.module'; | 23 | import { CustomerModule } from '@modules/home/pages/customer/customer.module'; |
24 | -// import { AuditLogModule } from '@modules/home/pages/audit-log/audit-log.module'; | 24 | +import { AuditLogModule } from '@modules/home/pages/audit-log/audit-log.module'; |
25 | import { UserModule } from '@modules/home/pages/user/user.module'; | 25 | import { UserModule } from '@modules/home/pages/user/user.module'; |
26 | import {DeviceModule} from '@modules/home/pages/device/device.module'; | 26 | import {DeviceModule} from '@modules/home/pages/device/device.module'; |
27 | import {AssetModule} from '@modules/home/pages/asset/asset.module'; | 27 | import {AssetModule} from '@modules/home/pages/asset/asset.module'; |
@@ -43,7 +43,7 @@ import {DashboardModule} from '@modules/home/pages/dashboard/dashboard.module'; | @@ -43,7 +43,7 @@ import {DashboardModule} from '@modules/home/pages/dashboard/dashboard.module'; | ||
43 | RuleChainModule, | 43 | RuleChainModule, |
44 | WidgetLibraryModule, | 44 | WidgetLibraryModule, |
45 | DashboardModule, | 45 | DashboardModule, |
46 | -// AuditLogModule, | 46 | + AuditLogModule, |
47 | UserModule | 47 | UserModule |
48 | ] | 48 | ] |
49 | }) | 49 | }) |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2019 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" | ||
19 | + label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> | ||
20 | + <tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.ENTITY" [entityId]="entity.id" detailsMode="true"></tb-audit-log-table> | ||
21 | +</mat-tab> |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { Component } from '@angular/core'; | ||
18 | +import { Store } from '@ngrx/store'; | ||
19 | +import { AppState } from '@core/core.state'; | ||
20 | +import { EntityTabsComponent } from '../../components/entity/entity-tabs.component'; | ||
21 | +import { AssetInfo } from '@app/shared/models/asset.models'; | ||
22 | +import { RuleChain } from '@shared/models/rule-chain.models'; | ||
23 | + | ||
24 | +@Component({ | ||
25 | + selector: 'tb-rulechain-tabs', | ||
26 | + templateUrl: './rulechain-tabs.component.html', | ||
27 | + styleUrls: [] | ||
28 | +}) | ||
29 | +export class RuleChainTabsComponent extends EntityTabsComponent<RuleChain> { | ||
30 | + | ||
31 | + constructor(protected store: Store<AppState>) { | ||
32 | + super(store); | ||
33 | + } | ||
34 | + | ||
35 | + ngOnInit() { | ||
36 | + super.ngOnInit(); | ||
37 | + } | ||
38 | + | ||
39 | +} |
@@ -20,13 +20,16 @@ import {SharedModule} from '@shared/shared.module'; | @@ -20,13 +20,16 @@ import {SharedModule} from '@shared/shared.module'; | ||
20 | import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component'; | 20 | import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component'; |
21 | import {RuleChainRoutingModule} from '@modules/home/pages/rulechain/rulechain-routing.module'; | 21 | import {RuleChainRoutingModule} from '@modules/home/pages/rulechain/rulechain-routing.module'; |
22 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; | 22 | import {HomeComponentsModule} from '@modules/home/components/home-components.module'; |
23 | +import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component'; | ||
23 | 24 | ||
24 | @NgModule({ | 25 | @NgModule({ |
25 | entryComponents: [ | 26 | entryComponents: [ |
26 | - RuleChainComponent | 27 | + RuleChainComponent, |
28 | + RuleChainTabsComponent | ||
27 | ], | 29 | ], |
28 | declarations: [ | 30 | declarations: [ |
29 | - RuleChainComponent | 31 | + RuleChainComponent, |
32 | + RuleChainTabsComponent | ||
30 | ], | 33 | ], |
31 | imports: [ | 34 | imports: [ |
32 | CommonModule, | 35 | CommonModule, |
@@ -31,6 +31,7 @@ import {RuleChain} from '@shared/models/rule-chain.models'; | @@ -31,6 +31,7 @@ import {RuleChain} from '@shared/models/rule-chain.models'; | ||
31 | import {RuleChainService} from '@core/http/rule-chain.service'; | 31 | import {RuleChainService} from '@core/http/rule-chain.service'; |
32 | import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component'; | 32 | import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component'; |
33 | import {DialogService} from '@core/services/dialog.service'; | 33 | import {DialogService} from '@core/services/dialog.service'; |
34 | +import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component'; | ||
34 | 35 | ||
35 | @Injectable() | 36 | @Injectable() |
36 | export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> { | 37 | export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> { |
@@ -45,6 +46,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig< | @@ -45,6 +46,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig< | ||
45 | 46 | ||
46 | this.config.entityType = EntityType.RULE_CHAIN; | 47 | this.config.entityType = EntityType.RULE_CHAIN; |
47 | this.config.entityComponent = RuleChainComponent; | 48 | this.config.entityComponent = RuleChainComponent; |
49 | + this.config.entityTabsComponent = RuleChainTabsComponent; | ||
48 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.RULE_CHAIN); | 50 | this.config.entityTranslations = entityTypeTranslations.get(EntityType.RULE_CHAIN); |
49 | this.config.entityResources = entityTypeResources.get(EntityType.RULE_CHAIN); | 51 | this.config.entityResources = entityTypeResources.get(EntityType.RULE_CHAIN); |
50 | 52 |
@@ -105,10 +105,6 @@ export class UserMenuComponent implements OnInit, OnDestroy { | @@ -105,10 +105,6 @@ export class UserMenuComponent implements OnInit, OnDestroy { | ||
105 | this.router.navigate(['profile']); | 105 | this.router.navigate(['profile']); |
106 | } | 106 | } |
107 | 107 | ||
108 | - openCustomerProfile(): void { | ||
109 | - this.router.navigate(['customerProfile']); | ||
110 | - } | ||
111 | - | ||
112 | logout(): void { | 108 | logout(): void { |
113 | this.authService.logout(); | 109 | this.authService.logout(); |
114 | } | 110 | } |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { BaseData } from './base-data'; | ||
18 | +import { AuditLogId } from './id/audit-log-id'; | ||
19 | +import { CustomerId } from './id/customer-id'; | ||
20 | +import { EntityId } from './id/entity-id'; | ||
21 | +import { UserId } from './id/user-id'; | ||
22 | +import { TenantId } from './id/tenant-id'; | ||
23 | + | ||
24 | +export enum AuditLogMode { | ||
25 | + TENANT, | ||
26 | + ENTITY, | ||
27 | + USER, | ||
28 | + CUSTOMER | ||
29 | +} | ||
30 | + | ||
31 | +export enum ActionType { | ||
32 | + ADDED = 'ADDED', | ||
33 | + DELETED = 'DELETED', | ||
34 | + UPDATED = 'UPDATED', | ||
35 | + ATTRIBUTES_UPDATED = 'ATTRIBUTES_UPDATED', | ||
36 | + ATTRIBUTES_DELETED = 'ATTRIBUTES_DELETED', | ||
37 | + RPC_CALL = 'RPC_CALL', | ||
38 | + CREDENTIALS_UPDATED = 'CREDENTIALS_UPDATED', | ||
39 | + ASSIGNED_TO_CUSTOMER = 'ASSIGNED_TO_CUSTOMER', | ||
40 | + UNASSIGNED_FROM_CUSTOMER = 'UNASSIGNED_FROM_CUSTOMER', | ||
41 | + ACTIVATED = 'ACTIVATED', | ||
42 | + SUSPENDED = 'SUSPENDED', | ||
43 | + CREDENTIALS_READ = 'CREDENTIALS_READ', | ||
44 | + ATTRIBUTES_READ = 'ATTRIBUTES_READ', | ||
45 | + RELATION_ADD_OR_UPDATE = 'RELATION_ADD_OR_UPDATE', | ||
46 | + RELATION_DELETED = 'RELATION_DELETED', | ||
47 | + RELATIONS_DELETED = 'RELATIONS_DELETED', | ||
48 | + ALARM_ACK = 'ALARM_ACK', | ||
49 | + ALARM_CLEAR = 'ALARM_CLEAR', | ||
50 | + LOGIN = 'LOGIN', | ||
51 | + LOGOUT = 'LOGOUT' | ||
52 | +} | ||
53 | + | ||
54 | +export enum ActionStatus { | ||
55 | + SUCCESS = 'SUCCESS', | ||
56 | + FAILURE = 'FAILURE' | ||
57 | +} | ||
58 | + | ||
59 | +export const actionTypeTranslations = new Map<ActionType, string>( | ||
60 | + [ | ||
61 | + [ActionType.ADDED, 'audit-log.type-added'], | ||
62 | + [ActionType.DELETED, 'audit-log.type-deleted'], | ||
63 | + [ActionType.UPDATED, 'audit-log.type-updated'], | ||
64 | + [ActionType.ATTRIBUTES_UPDATED, 'audit-log.type-attributes-updated'], | ||
65 | + [ActionType.ATTRIBUTES_DELETED, 'audit-log.type-attributes-deleted'], | ||
66 | + [ActionType.RPC_CALL, 'audit-log.type-rpc-call'], | ||
67 | + [ActionType.CREDENTIALS_UPDATED, 'audit-log.type-credentials-updated'], | ||
68 | + [ActionType.ASSIGNED_TO_CUSTOMER, 'audit-log.type-assigned-to-customer'], | ||
69 | + [ActionType.UNASSIGNED_FROM_CUSTOMER, 'audit-log.type-unassigned-from-customer'], | ||
70 | + [ActionType.ACTIVATED, 'audit-log.type-activated'], | ||
71 | + [ActionType.SUSPENDED, 'audit-log.type-suspended'], | ||
72 | + [ActionType.CREDENTIALS_READ, 'audit-log.type-credentials-read'], | ||
73 | + [ActionType.ATTRIBUTES_READ, 'audit-log.type-attributes-read'], | ||
74 | + [ActionType.RELATION_ADD_OR_UPDATE, 'audit-log.type-relation-add-or-update'], | ||
75 | + [ActionType.RELATION_DELETED, 'audit-log.type-relation-delete'], | ||
76 | + [ActionType.RELATIONS_DELETED, 'audit-log.type-relations-delete'], | ||
77 | + [ActionType.ALARM_ACK, 'audit-log.type-alarm-ack'], | ||
78 | + [ActionType.ALARM_CLEAR, 'audit-log.type-alarm-clear'], | ||
79 | + [ActionType.LOGIN, 'audit-log.type-login'], | ||
80 | + [ActionType.LOGOUT, 'audit-log.type-logout'] | ||
81 | + ] | ||
82 | +); | ||
83 | + | ||
84 | +export const actionStatusTranslations = new Map<ActionStatus, string>( | ||
85 | + [ | ||
86 | + [ActionStatus.SUCCESS, 'audit-log.status-success'], | ||
87 | + [ActionStatus.FAILURE, 'audit-log.status-failure'], | ||
88 | + ] | ||
89 | +); | ||
90 | + | ||
91 | +export interface AuditLog extends BaseData<AuditLogId> { | ||
92 | + tenantId: TenantId; | ||
93 | + customerId: CustomerId; | ||
94 | + entityId: EntityId; | ||
95 | + entityName: string; | ||
96 | + userId: UserId; | ||
97 | + userName: string; | ||
98 | + actionType: ActionType; | ||
99 | + actionData: any; | ||
100 | + actionStatus: ActionStatus; | ||
101 | + actionFailureDetails: string; | ||
102 | +} |
1 | +/// | ||
2 | +/// Copyright © 2016-2019 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { HasUUID } from '@shared/models/id/has-uuid'; | ||
18 | + | ||
19 | +export class AuditLogId implements HasUUID { | ||
20 | + id: string; | ||
21 | + constructor(id: string) { | ||
22 | + this.id = id; | ||
23 | + } | ||
24 | +} |
@@ -62,8 +62,6 @@ import {TranslateModule} from '@ngx-translate/core'; | @@ -62,8 +62,6 @@ import {TranslateModule} from '@ngx-translate/core'; | ||
62 | import {TbCheckboxComponent} from '@shared/components/tb-checkbox.component'; | 62 | import {TbCheckboxComponent} from '@shared/components/tb-checkbox.component'; |
63 | import {HelpComponent} from '@shared/components/help.component'; | 63 | import {HelpComponent} from '@shared/components/help.component'; |
64 | import {TbAnchorComponent} from '@shared/components/tb-anchor.component'; | 64 | import {TbAnchorComponent} from '@shared/components/tb-anchor.component'; |
65 | -// import { AuditLogDetailsDialogComponent } from '@shared/components/audit-log/audit-log-details-dialog.component'; | ||
66 | -// import { AuditLogTableComponent } from '@shared/components/audit-log/audit-log-table.component'; | ||
67 | import {MillisecondsToTimeStringPipe} from '@shared/pipe/milliseconds-to-time-string.pipe'; | 65 | import {MillisecondsToTimeStringPipe} from '@shared/pipe/milliseconds-to-time-string.pipe'; |
68 | import {TimewindowComponent} from '@shared/components/time/timewindow.component'; | 66 | import {TimewindowComponent} from '@shared/components/time/timewindow.component'; |
69 | import {OverlayModule} from '@angular/cdk/overlay'; | 67 | import {OverlayModule} from '@angular/cdk/overlay'; |
@@ -97,7 +95,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen | @@ -97,7 +95,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen | ||
97 | entryComponents: [ | 95 | entryComponents: [ |
98 | TbSnackBarComponent, | 96 | TbSnackBarComponent, |
99 | TbAnchorComponent, | 97 | TbAnchorComponent, |
100 | -// AuditLogDetailsDialogComponent, | ||
101 | TimewindowPanelComponent, | 98 | TimewindowPanelComponent, |
102 | ], | 99 | ], |
103 | declarations: [ | 100 | declarations: [ |
@@ -111,8 +108,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen | @@ -111,8 +108,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen | ||
111 | TbSnackBarComponent, | 108 | TbSnackBarComponent, |
112 | BreadcrumbComponent, | 109 | BreadcrumbComponent, |
113 | UserMenuComponent, | 110 | UserMenuComponent, |
114 | -// AuditLogTableComponent, | ||
115 | -// AuditLogDetailsDialogComponent, | ||
116 | TimewindowComponent, | 111 | TimewindowComponent, |
117 | TimewindowPanelComponent, | 112 | TimewindowPanelComponent, |
118 | TimeintervalComponent, | 113 | TimeintervalComponent, |
@@ -184,7 +179,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen | @@ -184,7 +179,6 @@ import {SocialSharePanelComponent} from './components/socialshare-panel.componen | ||
184 | TbCheckboxComponent, | 179 | TbCheckboxComponent, |
185 | BreadcrumbComponent, | 180 | BreadcrumbComponent, |
186 | UserMenuComponent, | 181 | UserMenuComponent, |
187 | -// AuditLogTableComponent, | ||
188 | TimewindowComponent, | 182 | TimewindowComponent, |
189 | TimewindowPanelComponent, | 183 | TimewindowPanelComponent, |
190 | TimeintervalComponent, | 184 | TimeintervalComponent, |