| /** |
| * @module modules/changelists-page-sk |
| * @description <h2><code>changelists-page-sk</code></h2> |
| * |
| * Allows the user to page through the ChangeLists for which Gold has seen |
| * data uploaded via TryJobs. |
| * |
| */ |
| import * as human from 'common-sk/modules/human'; |
| |
| import { define } from 'elements-sk/define'; |
| import { html } from 'lit-html'; |
| import { jsonOrThrow } from 'common-sk/modules/jsonOrThrow'; |
| import { stateReflector } from 'common-sk/modules/stateReflector'; |
| import { ElementSk } from '../../../infra-sk/modules/ElementSk'; |
| |
| import 'elements-sk/checkbox-sk'; |
| import 'elements-sk/icon/block-icon-sk'; |
| import 'elements-sk/icon/cached-icon-sk'; |
| import 'elements-sk/icon/done-icon-sk'; |
| |
| import '../pagination-sk'; |
| import { sendBeginTask, sendEndTask, sendFetchError } from '../common'; |
| |
| const _statusIcon = (cl) => { |
| if (cl.status === 'Open') { |
| return html`<cached-icon-sk title="ChangeList is open"></cached-icon-sk>`; |
| } if (cl.status === 'Landed') { |
| return html`<done-icon-sk title="ChangeList was landed"></done-icon-sk>`; |
| } |
| return html`<block-icon-sk title="ChangeList was abandoned"></block-icon-sk>`; |
| }; |
| |
| const changelist = (cl) => html` |
| <tr> |
| <td class=id> |
| <a title="See codereview in a new window" target=_blank rel=noopener href=${cl.url} |
| >${cl.id}</a> |
| ${_statusIcon(cl)} |
| </td> |
| <td> |
| <a href="/cl/${cl.system}/${cl.id}" |
| target="_blank" rel="noopener">Triage</a> |
| </td> |
| <td class=owner>${cl.owner}</td> |
| <td title=${cl.updated}>${human.diffDate(cl.updated)} ago</td> |
| <td>${cl.subject}</td> |
| </tr>`; |
| |
| const template = (ele) => html` |
| <div class=controls> |
| <pagination-sk page_size=${ele._page_size} offset=${ele._offset} |
| total=${ele._total} @page-changed=${ele._pageChanged}> |
| </pagination-sk> |
| |
| <checkbox-sk label="show all" ?checked=${ele._showAll} |
| @click=${ele._toggleShowAll}></checkbox-sk> |
| </div> |
| |
| <table> |
| <thead> |
| <tr> |
| <th colspan=2>ChangeList</th> |
| <th>Owner</th> |
| <th>Updated</th> |
| <th>Subject</th> |
| </tr> |
| </thead> |
| <tbody> |
| ${ele._cls.map(changelist)} |
| </tbody>`; |
| |
| define('changelists-page-sk', class extends ElementSk { |
| constructor() { |
| super(template); |
| |
| // Set empty values to allow empty rendering while we wait for |
| // stateReflector (which triggers on DomReady). Additionally, these values |
| // help stateReflector with types. |
| this._cls = []; |
| this._offset = 0; |
| this._page_size = 0; |
| this._total = 0; |
| this._showAll = false; |
| |
| this._stateChanged = stateReflector( |
| /* getState */() => ({ |
| // provide empty values |
| offset: this._offset, |
| page_size: this._page_size, |
| show_all: this._showAll, |
| }), /* setState */(newState) => { |
| if (!this._connected) { |
| return; |
| } |
| |
| // default values if not specified. |
| this._offset = newState.offset || 0; |
| this._page_size = newState.page_size || +this.getAttribute('page_size') || 50; |
| this._showAll = newState.show_all || false; |
| this._fetch(); |
| this._render(); |
| }, |
| ); |
| |
| // Allows us to abort fetches if a user pages. |
| this._fetchController = null; |
| } |
| |
| connectedCallback() { |
| super.connectedCallback(); |
| this._render(); |
| } |
| |
| // Returns a promise that resolves when all outstanding requests resolve |
| // or null if none were made. This promise makes unit tests a little more concise. |
| _fetch() { |
| if (this._fetchController) { |
| // Kill any outstanding requests |
| this._fetchController.abort(); |
| } |
| |
| // Make a fresh abort controller for each set of fetches. |
| // They cannot be re-used once aborted. |
| this._fetchController = new AbortController(); |
| const extra = { |
| signal: this._fetchController.signal, |
| }; |
| |
| sendBeginTask(this); |
| let u = `/json/v1/changelists?offset=${this._offset}&size=${this._page_size}`; |
| if (!this._showAll) { |
| u += '&active=true'; |
| } |
| return fetch(u, extra) |
| .then(jsonOrThrow) |
| .then((json) => { |
| this._cls = json.data || []; |
| this._offset = json.pagination.offset; |
| this._total = json.pagination.total; |
| this._render(); |
| sendEndTask(this); |
| }) |
| .catch((e) => sendFetchError(this, e, 'changelists')); |
| } |
| |
| _pageChanged(e) { |
| const d = e.detail; |
| this._offset += d.delta * this._page_size; |
| if (this._offset < 0) { |
| this._offset = 0; |
| } |
| this._stateChanged(); |
| this._render(); |
| this._fetch(); |
| } |
| |
| _toggleShowAll(e) { |
| e.preventDefault(); |
| this._showAll = !this._showAll; |
| this._stateChanged(); |
| this._render(); |
| this._fetch(); |
| } |
| }); |