blob: f46af38c1eae5c54e251f891d239ed7aa59acd0a [file] [log] [blame]
/**
* @license
* Copyright 2018 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {DashboardId, DashboardInfo, RepoName} from '../../../types/common';
import {firePageError} 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 {css, html, LitElement, PropertyValues} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {
createDashboardUrl,
DashboardType,
} from '../../../models/views/dashboard';
import {when} from 'lit/directives/when.js';
import '../../shared/gr-list-view/gr-list-view';
import {
createRepoUrl,
RepoDetailView,
RepoViewState,
} from '../../../models/views/repo';
interface DashboardRef {
section: string;
dashboards: DashboardInfo[];
}
@customElement('gr-repo-dashboards')
export class GrRepoDashboards extends LitElement {
@property({type: String})
repo?: RepoName;
@property({type: Object})
params?: RepoViewState;
@state()
loading = true;
@state()
dashboards?: DashboardRef[];
@state() offset = 0;
@state() filter = '';
@state() itemsPerPage = 25;
private readonly restApiService = getAppContext().restApiService;
static override get styles() {
return [
sharedStyles,
tableStyles,
css`
:host {
display: block;
margin-bottom: var(--spacing-xxl);
}
`,
];
}
override render() {
return html` <gr-list-view
.filter=${this.filter}
.itemsPerPage=${this.itemsPerPage}
.items=${this.dashboards}
.loading=${this.loading}
.offset=${this.offset}
.path=${createRepoUrl({
repo: this.repo,
detail: RepoDetailView.DASHBOARDS,
})}
>
<table id="list" class="genericList">
<tbody id="dashboards">
<tr class="headerRow">
<th class="topHeader">Dashboard name</th>
<th class="topHeader">Dashboard title</th>
<th class="topHeader">Dashboard description</th>
<th class="topHeader">Inherited from</th>
<th class="topHeader">Default</th>
</tr>
${when(
this.loading,
() => html`<tr id="loadingContainer">
<td>Loading...</td>
</tr>`,
() => html`
${(this.dashboards ?? []).map(
item => html`
<tr class="groupHeader">
<td colspan="5">${item.section}</td>
</tr>
${(item.dashboards ?? []).map(
info => html`
<tr class="table">
<td class="name">
<a href=${this.getUrl(info.project, info.id)}
>${info.path}</a
>
</td>
<td class="title">${info.title}</td>
<td class="desc">${info.description}</td>
<td class="inherited">
${this.computeInheritedFrom(
info.project,
info.defining_project
)}
</td>
<td class="default">
${this.computeIsDefault(info.is_default)}
</td>
</tr>
`
)}
`
)}
`
)}
</tbody>
</table>
</gr-list-view>`;
}
override updated(changedProperties: PropertyValues) {
if (changedProperties.has('repo')) {
this.repoChanged();
}
}
override willUpdate(changedProperties: PropertyValues) {
if (changedProperties.has('params')) {
this.paramsChanged();
}
}
async paramsChanged() {
const params = this.params;
this.loading = true;
this.filter = params?.filter ?? '';
this.offset = Number(params?.offset ?? 0);
await this.repoChanged(this.filter, this.offset);
}
private repoChanged(filter?: string, offset?: number) {
const repo = this.repo;
this.loading = true;
if (!repo) {
return Promise.resolve();
}
const errFn: ErrorCallback = response => {
firePageError(response);
};
return this.restApiService
.getRepoDashboards(repo, errFn)
.then((res?: DashboardInfo[]) => {
if (!res) {
return;
}
let dashboards = res.concat
.apply([], res)
.sort((a, b) => (a.id < b.id ? -1 : 1));
dashboards = dashboards
.filter(item =>
filter === undefined
? true
: item.path.toLowerCase().includes(filter.toLowerCase())
)
.slice(offset ?? 0, (offset ?? 0) + this.itemsPerPage);
const dashboardsByRef: Record<string, DashboardInfo[]> = {};
dashboards.forEach(d => {
if (!dashboardsByRef[d.ref]) {
dashboardsByRef[d.ref] = [];
}
dashboardsByRef[d.ref].push(d);
});
const dashboardBuilder: DashboardRef[] = [];
Object.keys(dashboardsByRef)
.sort()
.forEach(ref => {
dashboardBuilder.push({
section: ref,
dashboards: dashboardsByRef[ref],
});
});
this.dashboards = dashboardBuilder;
this.loading = false;
});
}
private getUrl(project?: RepoName, dashboard?: DashboardId) {
if (!project || !dashboard) return '';
return createDashboardUrl({project, type: DashboardType.REPO, dashboard});
}
private computeInheritedFrom(project: RepoName, definingProject: RepoName) {
return project === definingProject ? '' : definingProject;
}
private computeIsDefault(isDefault?: boolean) {
return isDefault ? '✓' : '';
}
}
declare global {
interface HTMLElementTagNameMap {
'gr-repo-dashboards': GrRepoDashboards;
}
}