Skip to content

Commit

Permalink
MWPW-146263 - [Bulk Publish v2] Job Info UI (#2158)
Browse files Browse the repository at this point in the history
* add job info to job processes

* add job info updates

* ui dialing

* finish up UI and refactored a little

* update label

* unit tests to support new functionality

* package index jobs into one

* feedback from demo

* fix unit test

* code cov

* get full code cov

* can test copy to clipboard in process component

* fix tabs test
  • Loading branch information
Sartxi authored May 1, 2024
1 parent 0df7b33 commit c65ad98
Show file tree
Hide file tree
Showing 16 changed files with 634 additions and 130 deletions.
9 changes: 2 additions & 7 deletions libs/blocks/bulk-publish-v2/components/bulk-publisher.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
--success: #3b853b;
--error: #db4437;
--panel-bg: rgba(255 255 255 / 60%);
--meta-width: 30%;

display: flex;
flex-direction: column;
Expand Down Expand Up @@ -372,12 +371,8 @@ label[for='urls'] i {

.job-meta {
display: flex;
justify-content: space-between;
min-width: var(--meta-width);
}

.job-meta>*:last-child {
text-align: right;
flex-direction: row;
justify-content: end;
}

.process {
Expand Down
21 changes: 18 additions & 3 deletions libs/blocks/bulk-publish-v2/components/bulk-publisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,22 @@ class BulkPublish2 extends LitElement {
if (this.mode === 'full') this.openJobs = false;
};

/* c8 ignore next 14 */
async reworkErrors(job) {
if (this.mode === 'full') {
this.openJobs = false;
await delay(300);
}
const { data, name } = job;
const { origin } = this.jobs.find((item) => item.result.job.name === name);
const errored = data.resources?.filter((path) => path.status !== 200);
if (errored.length) {
const textarea = this.renderRoot.querySelector('#Urls');
textarea.focus();
textarea.value = errored.map((error) => (`${origin}${error.path}`)).join('\r\n');
}
}

renderResults() {
const { showList, showClear, loading, count } = this.getJobState();
const handleToggle = () => {
Expand All @@ -307,7 +323,6 @@ class BulkPublish2 extends LitElement {
class="panel-title"
@click=${handleToggle}>
<span class="title">
${count ? html`<strong>${count}</strong>` : ''}
Job Results
</span>
<div class="jobs-tools${showList}">
Expand All @@ -326,16 +341,16 @@ class BulkPublish2 extends LitElement {
</div>
<div class="job${showList}">
<div class="job-head">
<div class="job-url">JOB</div>
<div class="job-url">JOB${this.jobs.length > 1 ? 'S' : ''}</div>
<div class="job-meta">
<span>STATUS</span>
<span>DATE/TIME</span>
</div>
</div>
<div class="job-list">
${this.jobs.map((job) => html`
<job-process
.job=${job}
.reworkErrors=${(errors) => this.reworkErrors(errors)}
@progress="${this.setJobProgress}"
@stopped="${this.setJobStopped}">
</job-process>
Expand Down
155 changes: 155 additions & 0 deletions libs/blocks/bulk-publish-v2/components/job-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { LitElement, html, nothing } from '../../../deps/lit-all.min.js';
import { getSheet } from '../../../../tools/utils/utils.js';
import { getConfig } from '../../../utils/utils.js';
import { delay, displayDate, setJobTime } from '../utils.js';

const { miloLibs, codeRoot } = getConfig();
const base = miloLibs || codeRoot;
const styleSheet = await getSheet(`${base}/blocks/bulk-publish-v2/components/job-process.css`);
const reworkIcon = `${base}/blocks/bulk-publish-v2/img/rework.svg`;
const closeIcon = `${base}/blocks/bulk-publish-v2/img/close.svg`;
const copyIcon = `${base}/blocks/bulk-publish-v2/img/copy.svg`;

class JobInfo extends LitElement {
static get properties() {
return {
status: { type: Object },
reworkErrors: { type: Function },
errFilter: { state: true },
timer: { state: true },
showTimes: { state: true },
copiedInvocationId: { state: true },
};
}

async connectedCallback() {
super.connectedCallback();
this.renderRoot.adoptedStyleSheets = [styleSheet];
}

async updated() {
if (this.errFilter) {
this.parentElement.classList.add('filter-errors');
this.showTimes = false;
this.scrollIntoView();
} else {
this.parentElement.classList.remove('filter-errors');
}
}

async copyInvocationId() {
await navigator.clipboard.writeText(this.status.invocationId);
this.copiedInvocationId = true;
await delay(3000);
this.copiedInvocationId = false;
}

renderStatus() {
const { progress, data, state } = this.status;
const complete = progress ? progress.processed - progress.failed : 0;
const error = progress ? progress.failed : 0;
const total = progress ? progress.total : data.paths.length;
const hasErrors = error > 0;
if (state === 'created') return html`<span class="job-totals">Waiting</span>`;
return html`
<div class="progress${this.errFilter ? ' filtered' : ''}">
${!this.errFilter ? html`
<div class="job-totals${hasErrors ? ' errors' : ''}">
<span class="${complete > 0 ? 'success' : ''}" title="Completed Pages">
${complete}</span> / <span title="Total Pages">${total}</span>
</div>
` : nothing}
${hasErrors ? html`
<span class="error-tools">
${this.errFilter ? html`
<span class="tools">
${error}
<span class="rework" title="Rework Errors" @click=${this.reworkErrors}>
<img src=${reworkIcon} alt="Rework Errors Icon" title="Rework Errors" />
</span>
<span @click=${() => { this.errFilter = false; }} class="close">
<img src=${closeIcon} alt="Remove Filter Icon" title="Remove Error Filter" />
</span>
</span>
` : html`
<span class="count" title="Filter Errors" @click=${() => { this.errFilter = true; }}>
${error}
</span>
`}
</span>
` : nothing}
</div>
`;
}

renderTimer() {
const { state, createTime, startTime, stopTime } = this.status;
let timerText = null;
this.updateComplete.then(() => { setJobTime(this); });
/* c8 ignore next 3 */
if (state === 'running') {
timerText = html`Working <strong id="TimerTime"></strong>`;
}
if (state === 'stopped') {
timerText = html`Done in <strong id="TimerTime"></strong>`;
}
if (!timerText) return nothing;
const toggleTimes = () => { this.showTimes = !this.showTimes; };
return html`
<div class="timer${this.showTimes ? ' show-times' : ''}" @click=${toggleTimes}>
${timerText}
${this.showTimes ? html`
<div class="job-timing">
<div class="stat">
Created
<strong>${displayDate(createTime)}</strong>
</div>
${startTime ? html`
<div class="stat">
Started
<strong>${displayDate(startTime)}</strong>
</div>
` : nothing}
${stopTime ? html`
<div class="stat">
Finished
<strong>${displayDate(stopTime)}</strong>
</div>
` : nothing}
</div>
` : nothing}
</div>
`;
}

render() {
const { topic, invocationId } = this.status;
return html`
<div class="job-info">
<div class="process">
<span class="topic">${topic}</span>
${invocationId ? html`
<img
title="Copy Job Invocation Id"
src="${copyIcon}"
class="job-id-link"
@click=${this.copyInvocationId} />
` : nothing}
${this.copiedInvocationId ? html`
<div class="job-id-copied">
Copied to clipboard!
</div>
` : nothing}
</div>
<div class="meta">
<span class="status">
${this.renderTimer()}
${this.renderStatus()}
</span>
</div>
</div>
`;
}
}

customElements.define('job-info', JobInfo);
Loading

0 comments on commit c65ad98

Please sign in to comment.