[EC-551] Update Event Logs Client Column (#3572)

* [EC-551] Fix RxJS warnings

* [EC-551] Update page to use CL components and Tailwind classes

* [EC-551] Update Client column to use text instead of icon. Update language and i18n.
This commit is contained in:
Shane Melton 2022-10-03 11:51:17 -07:00 committed by GitHub
parent efc68a7613
commit 5f5cd47474
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 71 deletions

View File

@ -464,16 +464,14 @@ export class EventService {
private formatGroupId(ev: EventResponse) {
const shortId = this.getShortId(ev.groupId);
const a = this.makeAnchor(shortId);
a.setAttribute(
"href",
"#/organizations/" + ev.organizationId + "/manage/groups?search=" + shortId
);
a.setAttribute("href", "#/organizations/" + ev.organizationId + "/groups?search=" + shortId);
return a.outerHTML;
}
private formatCollectionId(ev: EventResponse) {
const shortId = this.getShortId(ev.collectionId);
const a = this.makeAnchor(shortId);
// TODO: Update view/edit collection link after EC-14 is completed
a.setAttribute(
"href",
"#/organizations/" + ev.organizationId + "/manage/collections?search=" + shortId
@ -488,7 +486,7 @@ export class EventService {
"href",
"#/organizations/" +
ev.organizationId +
"/manage/people?search=" +
"/members?search=" +
shortId +
"&viewEvents=" +
ev.organizationUserId

View File

@ -1,54 +1,57 @@
<div class="page-header d-flex">
<div class="tw-mb-4">
<h1>{{ "eventLogs" | i18n }}</h1>
<div class="ml-auto d-flex">
<div class="form-inline">
<label class="sr-only" for="start">{{ "startDate" | i18n }}</label>
<div class="tw-mt-4 tw-flex tw-items-center">
<bit-form-field>
<bit-label>{{ "from" | i18n }}</bit-label>
<input
bitInput
type="datetime-local"
class="form-control form-control-sm"
id="start"
placeholder="{{ 'startDate' | i18n }}"
[(ngModel)]="start"
placeholder="YYYY-MM-DDTHH:MM"
(change)="dirtyDates = true"
/>
<span class="mx-2">-</span>
<label class="sr-only" for="end">{{ "endDate" | i18n }}</label>
</bit-form-field>
<span class="tw-mx-2">-</span>
<bit-form-field>
<bit-label>{{ "to" | i18n }}</bit-label>
<input
bitInput
type="datetime-local"
class="form-control form-control-sm"
id="end"
placeholder="{{ 'endDate' | i18n }}"
[(ngModel)]="end"
placeholder="YYYY-MM-DDTHH:MM"
(change)="dirtyDates = true"
/>
</div>
<form #refreshForm [appApiAction]="refreshPromise" class="d-inline">
</bit-form-field>
<form #refreshForm [appApiAction]="refreshPromise">
<button
class="tw-mx-3 tw-mt-1"
type="button"
class="btn btn-sm btn-outline-primary ml-3"
bitButton
buttonType="primary"
(click)="loadEvents(true)"
[disabled]="loaded && refreshForm.loading"
>
<i
class="bwi bwi-refresh bwi-fw"
aria-hidden="true"
[ngClass]="{ 'bwi-spin': loaded && refreshForm.loading }"
></i>
{{ "refresh" | i18n }}
{{ "update" | i18n }}
</button>
</form>
<form #exportForm [appApiAction]="exportPromise" class="d-inline">
<form #exportForm [appApiAction]="exportPromise">
<button
type="button"
class="btn btn-sm btn-outline-primary btn-submit manual ml-3"
class="tw-mt-1"
bitButton
[ngClass]="{ loading: exportForm.loading }"
(click)="exportEvents()"
[disabled]="(loaded && exportForm.loading) || dirtyDates"
>
<i class="bwi bwi-spinner bwi-spin" aria-hidden="true"></i>
<span>{{ "export" | i18n }}</span>
<i
class="bwi bwi-fw"
aria-hidden="true"
[ngClass]="{
'bwi-sign-in': !exportForm.loading,
'bwi-spinner bwi-spin': exportForm.loading
}"
></i>
</button>
</form>
</div>
@ -63,45 +66,44 @@
</ng-container>
<ng-container *ngIf="loaded">
<p *ngIf="!events || !events.length">{{ "noEventsInList" | i18n }}</p>
<table class="table table-hover" *ngIf="events && events.length">
<thead>
<bit-table *ngIf="events && events.length">
<ng-container header>
<tr>
<th class="border-top-0" width="210">{{ "timestamp" | i18n }}</th>
<th class="border-top-0" width="40">
<span class="sr-only">{{ "device" | i18n }}</span>
</th>
<th class="border-top-0" width="150">{{ "user" | i18n }}</th>
<th class="border-top-0">{{ "event" | i18n }}</th>
<th bitCell style="width: 210px">{{ "timestamp" | i18n }}</th>
<th bitCell style="width: 100px">{{ "client" | i18n }}</th>
<th bitCell style="width: 150px">{{ "member" | i18n }}</th>
<th bitCell>{{ "event" | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let e of events">
<td>{{ e.date | date: "medium" }}</td>
<td>
<i
class="text-muted bwi bwi-lg {{ e.appIcon }}"
title="{{ e.appName }}, {{ e.ip }}"
aria-hidden="true"
></i>
<span class="sr-only">{{ e.appName }}, {{ e.ip }}</span>
</ng-container>
<ng-container body>
<tr bitRow *ngFor="let e of events">
<td bitCell>{{ e.date | date: "medium" }}</td>
<td bitCell>
<span title="{{ e.appName }}, {{ e.ip }}">{{ e.appName }}</span>
</td>
<td>
<td bitCell>
<span title="{{ e.userEmail }}">{{ e.userName }}</span>
</td>
<td [innerHTML]="e.message"></td>
<td bitCell [innerHTML]="e.message"></td>
</tr>
</tbody>
</table>
</ng-container>
</bit-table>
<button
#moreBtn
[appApiAction]="morePromise"
type="button"
class="btn btn-block btn-link btn-submit"
bitButton
buttonType="primary"
(click)="loadEvents(false)"
[disabled]="loaded && moreBtn.loading"
*ngIf="continuationToken"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<i
class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
*ngIf="moreBtn.loading"
></i>
<span>{{ "loadMore" | i18n }}</span>
</button>
</ng-container>

View File

@ -1,5 +1,6 @@
import { Component, OnInit } from "@angular/core";
import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { concatMap, Subject, takeUntil } from "rxjs";
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
@ -20,13 +21,13 @@ import { EventService } from "../../core";
selector: "app-org-events",
templateUrl: "events.component.html",
})
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class EventsComponent extends BaseEventsComponent implements OnInit {
export class EventsComponent extends BaseEventsComponent implements OnInit, OnDestroy {
exportFileName = "org-events";
organizationId: string;
organization: Organization;
private orgUsersUserIdMap = new Map<string, any>();
private destroy$ = new Subject<void>();
constructor(
private apiService: ApiService,
@ -53,17 +54,20 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
}
async ngOnInit() {
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
this.route.parent.parent.params.subscribe(async (params) => {
this.organizationId = params.organizationId;
this.organization = await this.organizationService.get(this.organizationId);
if (this.organization == null || !this.organization.useEvents) {
this.router.navigate(["/organizations", this.organizationId]);
return;
}
await this.load();
});
this.route.params
.pipe(
concatMap(async (params) => {
this.organizationId = params.organizationId;
this.organization = await this.organizationService.get(this.organizationId);
if (this.organization == null || !this.organization.useEvents) {
await this.router.navigate(["/organizations", this.organizationId]);
return;
}
await this.load();
}),
takeUntil(this.destroy$)
)
.subscribe();
}
async load() {
@ -126,4 +130,9 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
return null;
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}

View File

@ -1,5 +1,5 @@
import { DragDropModule } from "@angular/cdk/drag-drop";
import { DatePipe, CommonModule } from "@angular/common";
import { CommonModule, DatePipe } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { RouterModule } from "@angular/router";
@ -12,9 +12,10 @@ import {
ButtonModule,
CalloutModule,
FormFieldModule,
MenuModule,
TabsModule,
IconModule,
MenuModule,
TableModule,
TabsModule,
} from "@bitwarden/components";
// Register the locales for the application
@ -46,6 +47,7 @@ import "./locales";
FormFieldModule,
IconModule,
TabsModule,
TableModule,
],
exports: [
CommonModule,
@ -65,6 +67,7 @@ import "./locales";
FormFieldModule,
IconModule,
TabsModule,
TableModule,
],
providers: [DatePipe],
bootstrap: [],

View File

@ -4512,6 +4512,10 @@
"clients": {
"message": "Clients"
},
"client": {
"message": "Client",
"description": "This is used as a table header to describe which client application created an event log."
},
"providerAdmin": {
"message": "Provider Admin"
},
@ -5431,5 +5435,17 @@
},
"numberOfUsers": {
"message": "Number of users"
},
"from": {
"message": "From"
},
"to": {
"message": "To"
},
"member": {
"message": "Member"
},
"update": {
"message": "Update"
}
}

View File

@ -9,5 +9,6 @@ export * from "./menu";
export * from "./dialog";
export * from "./link";
export * from "./tabs";
export * from "./table";
export * from "./toggle-group";
export * from "./utils/i18n-mock.service";