blob: 9244e820e0b5bf284699495f139fe587ed34add4 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001// Copyright 2019 The Chromium Authors
Copybara854996b2021-09-07 19:36:02 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {LitElement, html, css} from 'lit-element';
6import './mr-comment-content.js';
7import './mr-attachment.js';
8
9import {relativeTime} from
10 'elements/chops/chops-timestamp/chops-timestamp-helpers';
11
12
13/**
14 * `<mr-description>`
15 *
16 * Element for displaying a description or survey.
17 *
18 */
19export class MrDescription extends LitElement {
20 /** @override */
21 constructor() {
22 super();
23
24 this.descriptionList = [];
25 this.selectedIndex = 0;
26 }
27
28 /** @override */
29 static get properties() {
30 return {
31 descriptionList: {type: Array},
32 selectedIndex: {type: Number},
33 };
34 }
35
36 /** @override */
37 updated(changedProperties) {
38 super.updated(changedProperties);
39
40 if (changedProperties.has('descriptionList')) {
41 if (!this.descriptionList || !this.descriptionList.length) return;
42 this.selectedIndex = this.descriptionList.length - 1;
43 }
44 }
45
46 /** @override */
47 static get styles() {
48 return css`
49 .select-container {
50 text-align: right;
51 }
52 `;
53 }
54
55 /** @override */
56 render() {
57 const selectedDescription = this.selectedDescription;
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010058 const author = selectedDescription.commenter ? selectedDescription.commenter.displayName: '';
Copybara854996b2021-09-07 19:36:02 +000059
60 return html`
61 <div class="select-container">
62 <select
63 @change=${this._selectChanged}
64 ?hidden=${!this.descriptionList || this.descriptionList.length <= 1}
65 aria-label="Description history menu">
66 ${this.descriptionList.map((desc, i) => this._renderDescriptionOption(desc, i))}
67 </select>
68 </div>
69 <mr-comment-content
70 .content=${selectedDescription.content}
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010071 .author=${author}
Copybara854996b2021-09-07 19:36:02 +000072 ></mr-comment-content>
73 <div>
74 ${(selectedDescription.attachments || []).map((attachment) => html`
75 <mr-attachment
76 .attachment=${attachment}
77 .projectName=${selectedDescription.projectName}
78 .localId=${selectedDescription.localId}
79 .sequenceNum=${selectedDescription.sequenceNum}
80 .canDelete=${selectedDescription.canDelete}
81 ></mr-attachment>
82 `)}
83 </div>
84 `;
85 }
86
87 /**
88 * Getter for the currently viewed description.
89 * @return {Comment} The description object.
90 */
91 get selectedDescription() {
92 const descriptions = this.descriptionList || [];
93 const index = Math.max(
94 Math.min(this.selectedIndex, descriptions.length - 1),
95 0);
96 return descriptions[index] || {};
97 }
98
99 /**
100 * Helper to render a <select> <option> for a single description, for our
101 * description selector.
102 * @param {Comment} description
103 * @param {Number} index
104 * @return {TemplateResult}
105 * @private
106 */
107 _renderDescriptionOption(description, index) {
108 const {commenter, timestamp} = description || {};
109 const byLine = commenter ? `by ${commenter.displayName}` : '';
110 return html`
111 <option value=${index} ?selected=${index === this.selectedIndex}>
112 Description #${index + 1} ${byLine} (${_relativeTime(timestamp)})
113 </option>
114 `;
115 }
116
117 /**
118 * Updates the element's selectedIndex when the user changes the select menu.
119 * @param {Event} evt
120 */
121 _selectChanged(evt) {
122 if (!evt || !evt.target) return;
123 this.selectedIndex = Number.parseInt(evt.target.value);
124 }
125}
126
127/**
128 * Template helper for rendering relative time.
129 * @param {number} unixTime Unix timestamp in seconds.
130 * @return {string} human readable timestamp.
131 */
132function _relativeTime(unixTime) {
133 unixTime = Number.parseInt(unixTime);
134 if (Number.isNaN(unixTime)) return;
135 return relativeTime(new Date(unixTime * 1000));
136}
137
138customElements.define('mr-description', MrDescription);