blob: 578eda4091a1ad9286ef262084b8408f6f9f615d [file] [log] [blame]
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {FileInfoStatus} from '../../../constants/constants';
import {LitElement, css, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {assertNever} from '../../../utils/common-util';
import '../gr-tooltip-content/gr-tooltip-content';
import '../gr-icon/gr-icon';
function statusString(status: FileInfoStatus) {
if (!status) return '';
switch (status) {
case FileInfoStatus.ADDED:
return 'Added';
case FileInfoStatus.COPIED:
return 'Copied';
case FileInfoStatus.DELETED:
return 'Deleted';
case FileInfoStatus.MODIFIED:
return 'Modified';
case FileInfoStatus.RENAMED:
return 'Renamed';
case FileInfoStatus.REWRITTEN:
return 'Rewritten';
case FileInfoStatus.UNMODIFIED:
return 'Unchanged';
case FileInfoStatus.REVERTED:
return 'Reverted';
default:
assertNever(status, `Unsupported status: ${status}`);
}
}
/**
* This is a square colored box with a single letter, which can be used as a
* prefix column before file names.
*
* It can also show an additional "new" icon for indicating that a file was
* newly changed in a patchset.
*/
@customElement('gr-file-status')
export class GrFileStatus extends LitElement {
@property({type: String})
status?: FileInfoStatus;
/**
* Show an additional "new" icon for indicating that a file was newly changed
* in a patchset.
*/
@property({type: Boolean})
newlyChanged = false;
/**
* What postfix should the tooltip have? For example you can set
* ' in ps 5', such that the 'Added' tooltip becomes 'Added in ps 5'.
*/
@property({type: String})
labelPostfix = '';
static override get styles() {
return [
css`
:host {
display: inline-block;
}
div.status {
display: inline-block;
line-height: var(--line-height-normal);
width: var(--line-height-normal);
text-align: center;
border-radius: var(--border-radius);
background-color: transparent;
color: var(--file-status-font-color);
}
div.status gr-icon {
color: var(--file-status-font-color);
}
div.status.M {
border: 1px solid var(--border-color);
line-height: calc(var(--line-height-normal) - 2px);
width: calc(var(--line-height-normal) - 2px);
color: var(--deemphasized-text-color);
}
div.status.A {
background-color: var(--file-status-added);
}
div.status.D {
background-color: var(--file-status-deleted);
}
div.status.R,
div.status.W {
background-color: var(--file-status-renamed);
}
div.status.U {
background-color: var(--file-status-unchanged);
}
div.status.X {
background-color: var(--file-status-reverted);
}
.size-16 {
font-size: 16px;
position: relative;
top: 2px;
}
`,
];
}
override render() {
return html`${this.renderNewlyChanged()}${this.renderStatus()}`;
}
private renderStatus() {
const classes = ['status', this.status];
return html`<gr-tooltip-content title=${this.computeLabel()} has-tooltip>
<div
class=${classes.join(' ')}
tabindex="0"
aria-label=${this.computeLabel()}
>
${this.renderIconOrLetter()}
</div>
</gr-tooltip-content>`;
}
private renderIconOrLetter() {
if (this.status === FileInfoStatus.REVERTED) {
return html`<gr-icon small icon="undo"></gr-icon>`;
}
return html`<span>${this.status ?? ''}</span>`;
}
private renderNewlyChanged() {
if (!this.newlyChanged) return;
return html`<gr-tooltip-content title=${this.computeLabel()} has-tooltip>
<gr-icon
icon="new_releases"
class="size-16"
aria-label=${this.computeLabel()}
></gr-icon>
</gr-tooltip-content>`;
}
private computeLabel() {
if (!this.status) return '';
const prefix = this.newlyChanged ? 'Newly ' : '';
return `${prefix}${statusString(this.status)}${this.labelPostfix}`;
}
}
declare global {
interface HTMLElementTagNameMap {
'gr-file-status': GrFileStatus;
}
}