[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:
parent
efc68a7613
commit
5f5cd47474
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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: [],
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in New Issue