blob: 47f6e855f852f49abc8f6f89a15d2e4cff18d40f [file] [log] [blame]
/**
* @license
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {GrLitElement} from '../../lit/gr-lit-element';
import {css, customElement, html, property} from 'lit-element';
import {ParsedChangeInfo} from '../../../types/types';
import {
AccountInfo,
SubmitRequirementResultInfo,
SubmitRequirementStatus,
} from '../../../api/rest-api';
import {assertNever} from '../../../utils/common-util';
import {extractAssociatedLabels} from '../../../utils/change-metadata-util';
import {Label} from '../gr-change-requirements/gr-change-requirements';
@customElement('gr-submit-requirements')
export class GrSubmitRequirements extends GrLitElement {
@property({type: Object})
change?: ParsedChangeInfo;
@property({type: Object})
account?: AccountInfo;
@property({type: Boolean})
mutable?: boolean;
static override get styles() {
return [
css`
:host {
display: table;
width: 100%;
}
.metadata-title {
font-size: 100%;
font-weight: var(--font-weight-bold);
color: var(--deemphasized-text-color);
padding-left: var(--metadata-horizontal-padding);
}
section {
display: table-row;
}
.title {
min-width: 10em;
padding: var(--spacing-s) 0 0 0;
}
.value {
padding: var(--spacing-s) 0 0 0;
}
.title,
.value,
.status {
display: table-cell;
vertical-align: top;
}
.status {
width: var(--line-height-small);
padding: var(--spacing-s) var(--spacing-m) 0
var(--requirements-horizontal-padding);
}
iron-icon {
width: var(--line-height-small);
height: var(--line-height-small);
}
iron-icon.satisfied {
color: var(--success-foreground);
}
iron-icon.unsatisfied {
color: var(--warning-foreground);
}
.testing {
margin-top: var(--spacing-xxl);
padding-left: var(--metadata-horizontal-padding);
color: var(--deemphasized-text-color);
}
.testing gr-button {
min-width: 25px;
}
.testing * {
visibility: hidden;
}
.testing:hover * {
visibility: visible;
}
`,
];
}
override render() {
const submit_requirements = (this.change?.submit_requirements ?? []).filter(
req => req.status !== SubmitRequirementStatus.NOT_APPLICABLE
);
return html`<h3 class="metadata-title">Submit Requirements</h3>
${submit_requirements.map(
requirement => html`<section>
<div class="status">${this.renderStatus(requirement.status)}</div>
<div class="title">
<gr-limited-text
class="name"
limit="25"
text="${requirement.name}"
></gr-limited-text>
</div>
<div class="value">${this.renderLabels(requirement)}</div>
</section>`
)}${this.renderFakeControls()}`;
}
renderStatus(status: SubmitRequirementStatus) {
let grIcon: string;
switch (status) {
case SubmitRequirementStatus.SATISFIED:
grIcon = 'gr-icons:check';
break;
case SubmitRequirementStatus.UNSATISFIED:
grIcon = 'gr-icons:close';
break;
case SubmitRequirementStatus.OVERRIDDEN:
grIcon = 'gr-icons:warning';
break;
case SubmitRequirementStatus.NOT_APPLICABLE:
grIcon = 'gr-icons:info';
break;
default:
assertNever(status, `Unsupported status: ${status}`);
}
return html`<iron-icon
class=${status.toLowerCase()}
icon="${grIcon}"
></iron-icon>`;
}
renderLabels(requirement: SubmitRequirementResultInfo) {
const requirementLabels = extractAssociatedLabels(requirement);
const labels = this.change?.labels ?? {};
const allLabels: Label[] = [];
for (const label of Object.keys(labels)) {
if (requirementLabels.includes(label)) {
allLabels.push({
labelName: label,
icon: '',
style: '',
labelInfo: labels[label],
});
}
}
return allLabels.map(
label => html`<gr-label-info
.change="${this.change}"
.account="${this.account}"
.mutable="${this.mutable}"
label="${label.labelName}"
.labelInfo="${label.labelInfo}"
></gr-label-info>`
);
}
renderFakeControls() {
return html`
<div class="testing">
<div>Toggle fake data:</div>
<gr-button link @click="${() => this.renderFakeSubmitRequirements()}"
>G</gr-button
>
</div>
`;
}
renderFakeSubmitRequirements() {
if (!this.change) return;
this.change = {
...this.change,
submit_requirements: [
{
name: 'Code-Review',
status: SubmitRequirementStatus.SATISFIED,
description:
"At least one maximum vote for label 'Code-Review' is required",
submittability_expression_result: {
expression: 'label:Code-Review=MAX -label:Code-Review=MIN',
fulfilled: true,
passing_atoms: [],
failing_atoms: [],
},
},
{
name: 'Verified',
status: SubmitRequirementStatus.UNSATISFIED,
description: 'CI build and tests results are verified',
submittability_expression_result: {
expression: 'label:Verified=MAX -label:Verified=MIN',
fulfilled: false,
passing_atoms: [],
failing_atoms: [],
},
},
],
};
}
}
declare global {
interface HTMLElementTagNameMap {
'gr-submit-requirements': GrSubmitRequirements;
}
}