| /** |
| * @license |
| * Copyright 2017 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| import '../../shared/gr-account-label/gr-account-label'; |
| import { |
| GroupInfo, |
| AccountInfo, |
| EncodedGroupId, |
| GroupAuditEventInfo, |
| GroupAuditGroupEventInfo, |
| isGroupAuditGroupEventInfo, |
| } from '../../../types/common'; |
| import {firePageError, fireTitleChange} from '../../../utils/event-util'; |
| import {getAppContext} from '../../../services/app-context'; |
| import {ErrorCallback} from '../../../api/rest'; |
| import {sharedStyles} from '../../../styles/shared-styles'; |
| import {tableStyles} from '../../../styles/gr-table-styles'; |
| import {LitElement, PropertyValues, css, html} from 'lit'; |
| import {customElement, property, state} from 'lit/decorators.js'; |
| import {createGroupUrl} from '../../../models/views/group'; |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'gr-group-audit-log': GrGroupAuditLog; |
| } |
| } |
| |
| @customElement('gr-group-audit-log') |
| export class GrGroupAuditLog extends LitElement { |
| @property({type: String}) |
| groupId?: EncodedGroupId; |
| |
| @state() private auditLog?: GroupAuditEventInfo[]; |
| |
| @state() private loading = true; |
| |
| private readonly restApiService = getAppContext().restApiService; |
| |
| override connectedCallback() { |
| super.connectedCallback(); |
| fireTitleChange('Audit Log'); |
| } |
| |
| static override get styles() { |
| return [ |
| sharedStyles, |
| tableStyles, |
| css` |
| /* GenericList style centers the last column, but we don't want that here. */ |
| .genericList tr th:last-of-type, |
| .genericList tr td:last-of-type { |
| text-align: left; |
| } |
| `, |
| ]; |
| } |
| |
| override render() { |
| return html` |
| <table id="list" class="genericList"> |
| <tbody> |
| <tr class="headerRow"> |
| <th class="date topHeader">Date</th> |
| <th class="type topHeader">Type</th> |
| <th class="member topHeader">Member</th> |
| <th class="by-user topHeader">By User</th> |
| </tr> |
| ${this.renderLoading()} |
| </tbody> |
| ${this.renderAuditLogTable()} |
| </table> |
| `; |
| } |
| |
| private renderLoading() { |
| if (!this.loading) return; |
| |
| return html` |
| <tr id="loading" class="loadingMsg loading"> |
| <td>Loading...</td> |
| </tr> |
| `; |
| } |
| |
| private renderAuditLogTable() { |
| if (this.loading) return; |
| |
| return html` |
| <tbody> |
| ${this.auditLog?.map(audit => this.renderAuditLog(audit))} |
| </tbody> |
| `; |
| } |
| |
| private renderAuditLog(audit: GroupAuditEventInfo) { |
| return html` |
| <tr class="table"> |
| <td class="date"> |
| <gr-date-formatter withTooltip .dateStr=${audit.date}> |
| </gr-date-formatter> |
| </td> |
| <td class="type">${this.itemType(audit.type)}</td> |
| <td class="member"> |
| ${this.isGroupEvent(audit) |
| ? html`<a href=${this.computeGroupUrl(audit.member)} |
| >${this.getNameForGroup(audit.member)}</a |
| >` |
| : html`<gr-account-label |
| .account=${audit.member} |
| clickable |
| ></gr-account-label |
| >${this.getIdForUser(audit.member)}`} |
| </td> |
| <td class="by-user"> |
| <gr-account-label clickable .account=${audit.user}></gr-account-label> |
| ${this.getIdForUser(audit.user)} |
| </td> |
| </tr> |
| `; |
| } |
| |
| override willUpdate(changedProperties: PropertyValues) { |
| if (changedProperties.has('groupId')) { |
| this.getAuditLogs(); |
| } |
| } |
| |
| // private but used in test |
| getAuditLogs() { |
| if (!this.groupId) return; |
| |
| const errFn: ErrorCallback = response => { |
| firePageError(response); |
| }; |
| |
| this.loading = true; |
| return this.restApiService |
| .getGroupAuditLog(this.groupId, errFn) |
| .then(auditLog => { |
| this.auditLog = auditLog ?? []; |
| }) |
| .finally(() => { |
| this.loading = false; |
| }); |
| } |
| |
| private itemType(type: string) { |
| let item; |
| switch (type) { |
| case 'ADD_GROUP': |
| case 'ADD_USER': |
| item = 'Added'; |
| break; |
| case 'REMOVE_GROUP': |
| case 'REMOVE_USER': |
| item = 'Removed'; |
| break; |
| default: |
| item = ''; |
| } |
| return item; |
| } |
| |
| // private but used in test |
| isGroupEvent(event: GroupAuditEventInfo): event is GroupAuditGroupEventInfo { |
| return isGroupAuditGroupEventInfo(event); |
| } |
| |
| private computeGroupUrl(group?: GroupInfo) { |
| if (!group?.id) return ''; |
| return createGroupUrl({groupId: group.id}); |
| } |
| |
| // private but used in test |
| getIdForUser(account: AccountInfo) { |
| return account._account_id ? ` (${account._account_id})` : ''; |
| } |
| |
| // private but used in test |
| getNameForGroup(group: GroupInfo) { |
| if (group && group.name) { |
| return group.name; |
| } else if (group && group.id) { |
| // The URL encoded id of the member |
| return decodeURIComponent(group.id); |
| } |
| |
| return ''; |
| } |
| } |