| /** |
| * @license |
| * Copyright 2021 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| import '../gr-trigger-vote/gr-trigger-vote'; |
| import {LitElement, css, html} from 'lit'; |
| import {customElement, property} from 'lit/decorators.js'; |
| import {ChangeInfo} from '../../../api/rest-api'; |
| import { |
| LabelExtreme, |
| PATCH_SET_PREFIX_PATTERN, |
| } from '../../../utils/comment-util'; |
| import {hasOwnProperty} from '../../../utils/common-util'; |
| import {getTriggerVotes} from '../../../utils/label-util'; |
| import {ChangeMessage} from '../../../types/common'; |
| |
| const VOTE_RESET_TEXT = '0 (vote reset)'; |
| |
| interface Score { |
| label?: string; |
| value?: string; |
| } |
| |
| export const LABEL_TITLE_SCORE_PATTERN = |
| /^(-?)([A-Za-z0-9-]+?)([+-]\d+)?[.:]?$/; |
| |
| @customElement('gr-message-scores') |
| export class GrMessageScores extends LitElement { |
| @property() |
| labelExtremes?: LabelExtreme; |
| |
| @property({type: Object}) |
| message?: ChangeMessage; |
| |
| @property({type: Object}) |
| change?: ChangeInfo; |
| |
| static override get styles() { |
| return css` |
| .score, |
| gr-trigger-vote { |
| padding: 0 var(--spacing-s); |
| margin-right: var(--spacing-s); |
| display: inline-block; |
| } |
| .score { |
| box-sizing: border-box; |
| border-radius: var(--border-radius); |
| color: var(--vote-text-color); |
| text-align: center; |
| min-width: 115px; |
| } |
| .score.removed { |
| background-color: var(--vote-color-neutral); |
| } |
| .score.negative { |
| background-color: var(--vote-color-disliked); |
| border: 1px solid var(--vote-outline-disliked); |
| line-height: calc(var(--line-height-normal) - 2px); |
| color: var(--chip-color); |
| } |
| .score.negative.min { |
| background-color: var(--vote-color-rejected); |
| border: none; |
| padding-top: 1px; |
| padding-bottom: 1px; |
| color: var(--vote-text-color); |
| } |
| .score.positive { |
| background-color: var(--vote-color-recommended); |
| border: 1px solid var(--vote-outline-recommended); |
| line-height: calc(var(--line-height-normal) - 2px); |
| color: var(--chip-color); |
| } |
| .score.positive.max { |
| background-color: var(--vote-color-approved); |
| border: none; |
| padding-top: 1px; |
| padding-bottom: 1px; |
| color: var(--vote-text-color); |
| } |
| |
| @media screen and (max-width: 50em) { |
| .score { |
| min-width: 0px; |
| } |
| } |
| `; |
| } |
| |
| override render() { |
| const scores = this._getScores(this.message, this.labelExtremes); |
| const triggerVotes = getTriggerVotes(this.change); |
| return scores.map(score => this.renderScore(score, triggerVotes)); |
| } |
| |
| private renderScore(score: Score, triggerVotes: string[]) { |
| if ( |
| score.label && |
| triggerVotes.includes(score.label) && |
| !score.value?.includes(VOTE_RESET_TEXT) |
| ) { |
| const labels = this.change?.labels ?? {}; |
| return html`<gr-trigger-vote |
| .label=${score.label} |
| .displayValue=${score.value} |
| .labelInfo=${labels[score.label]} |
| .change=${this.change} |
| .mutable=${false} |
| disable-hovercards |
| > |
| </gr-trigger-vote>`; |
| } |
| return html`<span |
| class="score ${this._computeScoreClass(score, this.labelExtremes)}" |
| > |
| ${score.label} ${score.value} |
| </span>`; |
| } |
| |
| _computeScoreClass(score?: Score, labelExtremes?: LabelExtreme) { |
| if (score === undefined || labelExtremes === undefined) { |
| return ''; |
| } |
| if (!score.value) { |
| return ''; |
| } |
| if (score.value.includes(VOTE_RESET_TEXT)) { |
| return 'removed'; |
| } |
| const classes = []; |
| if (Number(score.value) > 0) { |
| classes.push('positive'); |
| } else if (Number(score.value) < 0) { |
| classes.push('negative'); |
| } |
| if (score.label) { |
| const extremes = labelExtremes[score.label]; |
| if (extremes) { |
| const intScore = Number(score.value); |
| if (intScore === extremes.max) { |
| classes.push('max'); |
| } else if (intScore === extremes.min) { |
| classes.push('min'); |
| } |
| } |
| } |
| return classes.join(' '); |
| } |
| |
| _getScores(message?: ChangeMessage, labelExtremes?: LabelExtreme): Score[] { |
| if (!message || !message.message || !labelExtremes) { |
| return []; |
| } |
| const line = message.message.split('\n', 1)[0]; |
| const patchSetPrefix = PATCH_SET_PREFIX_PATTERN; |
| if (!line.match(patchSetPrefix)) { |
| return []; |
| } |
| const scoresRaw = line.split(patchSetPrefix)[1]; |
| if (!scoresRaw) { |
| return []; |
| } |
| return scoresRaw |
| .split(' ') |
| .map(s => s.match(LABEL_TITLE_SCORE_PATTERN)) |
| .filter( |
| ms => ms && ms.length === 4 && hasOwnProperty(labelExtremes, ms[2]) |
| ) |
| .map(ms => { |
| const label = ms?.[2]; |
| const value = ms?.[1] === '-' ? VOTE_RESET_TEXT : ms?.[3]; |
| return {label, value}; |
| }); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'gr-message-scores': GrMessageScores; |
| } |
| } |