mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[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:
@@ -464,16 +464,14 @@ export class EventService {
|
|||||||
private formatGroupId(ev: EventResponse) {
|
private formatGroupId(ev: EventResponse) {
|
||||||
const shortId = this.getShortId(ev.groupId);
|
const shortId = this.getShortId(ev.groupId);
|
||||||
const a = this.makeAnchor(shortId);
|
const a = this.makeAnchor(shortId);
|
||||||
a.setAttribute(
|
a.setAttribute("href", "#/organizations/" + ev.organizationId + "/groups?search=" + shortId);
|
||||||
"href",
|
|
||||||
"#/organizations/" + ev.organizationId + "/manage/groups?search=" + shortId
|
|
||||||
);
|
|
||||||
return a.outerHTML;
|
return a.outerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
private formatCollectionId(ev: EventResponse) {
|
private formatCollectionId(ev: EventResponse) {
|
||||||
const shortId = this.getShortId(ev.collectionId);
|
const shortId = this.getShortId(ev.collectionId);
|
||||||
const a = this.makeAnchor(shortId);
|
const a = this.makeAnchor(shortId);
|
||||||
|
// TODO: Update view/edit collection link after EC-14 is completed
|
||||||
a.setAttribute(
|
a.setAttribute(
|
||||||
"href",
|
"href",
|
||||||
"#/organizations/" + ev.organizationId + "/manage/collections?search=" + shortId
|
"#/organizations/" + ev.organizationId + "/manage/collections?search=" + shortId
|
||||||
@@ -488,7 +486,7 @@ export class EventService {
|
|||||||
"href",
|
"href",
|
||||||
"#/organizations/" +
|
"#/organizations/" +
|
||||||
ev.organizationId +
|
ev.organizationId +
|
||||||
"/manage/people?search=" +
|
"/members?search=" +
|
||||||
shortId +
|
shortId +
|
||||||
"&viewEvents=" +
|
"&viewEvents=" +
|
||||||
ev.organizationUserId
|
ev.organizationUserId
|
||||||
|
|||||||
@@ -1,54 +1,57 @@
|
|||||||
<div class="page-header d-flex">
|
<div class="tw-mb-4">
|
||||||
<h1>{{ "eventLogs" | i18n }}</h1>
|
<h1>{{ "eventLogs" | i18n }}</h1>
|
||||||
<div class="ml-auto d-flex">
|
<div class="tw-mt-4 tw-flex tw-items-center">
|
||||||
<div class="form-inline">
|
<bit-form-field>
|
||||||
<label class="sr-only" for="start">{{ "startDate" | i18n }}</label>
|
<bit-label>{{ "from" | i18n }}</bit-label>
|
||||||
<input
|
<input
|
||||||
|
bitInput
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
class="form-control form-control-sm"
|
|
||||||
id="start"
|
|
||||||
placeholder="{{ 'startDate' | i18n }}"
|
placeholder="{{ 'startDate' | i18n }}"
|
||||||
[(ngModel)]="start"
|
[(ngModel)]="start"
|
||||||
placeholder="YYYY-MM-DDTHH:MM"
|
|
||||||
(change)="dirtyDates = true"
|
(change)="dirtyDates = true"
|
||||||
/>
|
/>
|
||||||
<span class="mx-2">-</span>
|
</bit-form-field>
|
||||||
<label class="sr-only" for="end">{{ "endDate" | i18n }}</label>
|
<span class="tw-mx-2">-</span>
|
||||||
|
<bit-form-field>
|
||||||
|
<bit-label>{{ "to" | i18n }}</bit-label>
|
||||||
<input
|
<input
|
||||||
|
bitInput
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
class="form-control form-control-sm"
|
|
||||||
id="end"
|
|
||||||
placeholder="{{ 'endDate' | i18n }}"
|
placeholder="{{ 'endDate' | i18n }}"
|
||||||
[(ngModel)]="end"
|
[(ngModel)]="end"
|
||||||
placeholder="YYYY-MM-DDTHH:MM"
|
|
||||||
(change)="dirtyDates = true"
|
(change)="dirtyDates = true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</bit-form-field>
|
||||||
<form #refreshForm [appApiAction]="refreshPromise" class="d-inline">
|
<form #refreshForm [appApiAction]="refreshPromise">
|
||||||
<button
|
<button
|
||||||
|
class="tw-mx-3 tw-mt-1"
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm btn-outline-primary ml-3"
|
bitButton
|
||||||
|
buttonType="primary"
|
||||||
(click)="loadEvents(true)"
|
(click)="loadEvents(true)"
|
||||||
[disabled]="loaded && refreshForm.loading"
|
[disabled]="loaded && refreshForm.loading"
|
||||||
>
|
>
|
||||||
<i
|
{{ "update" | i18n }}
|
||||||
class="bwi bwi-refresh bwi-fw"
|
|
||||||
aria-hidden="true"
|
|
||||||
[ngClass]="{ 'bwi-spin': loaded && refreshForm.loading }"
|
|
||||||
></i>
|
|
||||||
{{ "refresh" | i18n }}
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<form #exportForm [appApiAction]="exportPromise" class="d-inline">
|
<form #exportForm [appApiAction]="exportPromise">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm btn-outline-primary btn-submit manual ml-3"
|
class="tw-mt-1"
|
||||||
|
bitButton
|
||||||
[ngClass]="{ loading: exportForm.loading }"
|
[ngClass]="{ loading: exportForm.loading }"
|
||||||
(click)="exportEvents()"
|
(click)="exportEvents()"
|
||||||
[disabled]="(loaded && exportForm.loading) || dirtyDates"
|
[disabled]="(loaded && exportForm.loading) || dirtyDates"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-spinner bwi-spin" aria-hidden="true"></i>
|
|
||||||
<span>{{ "export" | i18n }}</span>
|
<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>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,45 +66,44 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="loaded">
|
<ng-container *ngIf="loaded">
|
||||||
<p *ngIf="!events || !events.length">{{ "noEventsInList" | i18n }}</p>
|
<p *ngIf="!events || !events.length">{{ "noEventsInList" | i18n }}</p>
|
||||||
<table class="table table-hover" *ngIf="events && events.length">
|
<bit-table *ngIf="events && events.length">
|
||||||
<thead>
|
<ng-container header>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="border-top-0" width="210">{{ "timestamp" | i18n }}</th>
|
<th bitCell style="width: 210px">{{ "timestamp" | i18n }}</th>
|
||||||
<th class="border-top-0" width="40">
|
<th bitCell style="width: 100px">{{ "client" | i18n }}</th>
|
||||||
<span class="sr-only">{{ "device" | i18n }}</span>
|
<th bitCell style="width: 150px">{{ "member" | i18n }}</th>
|
||||||
</th>
|
<th bitCell>{{ "event" | i18n }}</th>
|
||||||
<th class="border-top-0" width="150">{{ "user" | i18n }}</th>
|
|
||||||
<th class="border-top-0">{{ "event" | i18n }}</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</ng-container>
|
||||||
<tbody>
|
<ng-container body>
|
||||||
<tr *ngFor="let e of events">
|
<tr bitRow *ngFor="let e of events">
|
||||||
<td>{{ e.date | date: "medium" }}</td>
|
<td bitCell>{{ e.date | date: "medium" }}</td>
|
||||||
<td>
|
<td bitCell>
|
||||||
<i
|
<span title="{{ e.appName }}, {{ e.ip }}">{{ e.appName }}</span>
|
||||||
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>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td bitCell>
|
||||||
<span title="{{ e.userEmail }}">{{ e.userName }}</span>
|
<span title="{{ e.userEmail }}">{{ e.userName }}</span>
|
||||||
</td>
|
</td>
|
||||||
<td [innerHTML]="e.message"></td>
|
<td bitCell [innerHTML]="e.message"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</ng-container>
|
||||||
</table>
|
</bit-table>
|
||||||
<button
|
<button
|
||||||
#moreBtn
|
#moreBtn
|
||||||
[appApiAction]="morePromise"
|
[appApiAction]="morePromise"
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-block btn-link btn-submit"
|
bitButton
|
||||||
|
buttonType="primary"
|
||||||
(click)="loadEvents(false)"
|
(click)="loadEvents(false)"
|
||||||
[disabled]="loaded && moreBtn.loading"
|
[disabled]="loaded && moreBtn.loading"
|
||||||
*ngIf="continuationToken"
|
*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>
|
<span>{{ "loadMore" | i18n }}</span>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</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 { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
import { concatMap, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
@@ -20,13 +21,13 @@ import { EventService } from "../../core";
|
|||||||
selector: "app-org-events",
|
selector: "app-org-events",
|
||||||
templateUrl: "events.component.html",
|
templateUrl: "events.component.html",
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
export class EventsComponent extends BaseEventsComponent implements OnInit, OnDestroy {
|
||||||
export class EventsComponent extends BaseEventsComponent implements OnInit {
|
|
||||||
exportFileName = "org-events";
|
exportFileName = "org-events";
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
organization: Organization;
|
organization: Organization;
|
||||||
|
|
||||||
private orgUsersUserIdMap = new Map<string, any>();
|
private orgUsersUserIdMap = new Map<string, any>();
|
||||||
|
private destroy$ = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
@@ -53,17 +54,20 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
this.route.params
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
.pipe(
|
||||||
this.organizationId = params.organizationId;
|
concatMap(async (params) => {
|
||||||
this.organization = await this.organizationService.get(this.organizationId);
|
this.organizationId = params.organizationId;
|
||||||
if (this.organization == null || !this.organization.useEvents) {
|
this.organization = await this.organizationService.get(this.organizationId);
|
||||||
this.router.navigate(["/organizations", this.organizationId]);
|
if (this.organization == null || !this.organization.useEvents) {
|
||||||
return;
|
await this.router.navigate(["/organizations", this.organizationId]);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
await this.load();
|
await this.load();
|
||||||
});
|
}),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
@@ -126,4 +130,9 @@ export class EventsComponent extends BaseEventsComponent implements OnInit {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DragDropModule } from "@angular/cdk/drag-drop";
|
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 { NgModule } from "@angular/core";
|
||||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||||
import { RouterModule } from "@angular/router";
|
import { RouterModule } from "@angular/router";
|
||||||
@@ -12,9 +12,10 @@ import {
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
CalloutModule,
|
CalloutModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
MenuModule,
|
|
||||||
TabsModule,
|
|
||||||
IconModule,
|
IconModule,
|
||||||
|
MenuModule,
|
||||||
|
TableModule,
|
||||||
|
TabsModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
// Register the locales for the application
|
// Register the locales for the application
|
||||||
@@ -46,6 +47,7 @@ import "./locales";
|
|||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
IconModule,
|
IconModule,
|
||||||
TabsModule,
|
TabsModule,
|
||||||
|
TableModule,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -65,6 +67,7 @@ import "./locales";
|
|||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
IconModule,
|
IconModule,
|
||||||
TabsModule,
|
TabsModule,
|
||||||
|
TableModule,
|
||||||
],
|
],
|
||||||
providers: [DatePipe],
|
providers: [DatePipe],
|
||||||
bootstrap: [],
|
bootstrap: [],
|
||||||
|
|||||||
@@ -4512,6 +4512,10 @@
|
|||||||
"clients": {
|
"clients": {
|
||||||
"message": "Clients"
|
"message": "Clients"
|
||||||
},
|
},
|
||||||
|
"client": {
|
||||||
|
"message": "Client",
|
||||||
|
"description": "This is used as a table header to describe which client application created an event log."
|
||||||
|
},
|
||||||
"providerAdmin": {
|
"providerAdmin": {
|
||||||
"message": "Provider Admin"
|
"message": "Provider Admin"
|
||||||
},
|
},
|
||||||
@@ -5431,5 +5435,17 @@
|
|||||||
},
|
},
|
||||||
"numberOfUsers": {
|
"numberOfUsers": {
|
||||||
"message": "Number of users"
|
"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 "./dialog";
|
||||||
export * from "./link";
|
export * from "./link";
|
||||||
export * from "./tabs";
|
export * from "./tabs";
|
||||||
|
export * from "./table";
|
||||||
export * from "./toggle-group";
|
export * from "./toggle-group";
|
||||||
export * from "./utils/i18n-mock.service";
|
export * from "./utils/i18n-mock.service";
|
||||||
|
|||||||
Reference in New Issue
Block a user