diff --git a/.github/workflows/dispatch.yml b/.github/workflows/dispatch.yml index 78a396b37a..3267848caa 100644 --- a/.github/workflows/dispatch.yml +++ b/.github/workflows/dispatch.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - stage jobs: dispatch-dc: @@ -29,5 +30,8 @@ jobs: owner: 'adobecom', repo: 'dc', workflow_id: 'test-milo.yml', - ref: 'main', + ref: 'stage', + inputs: { + miloBranch: '${{ github.ref_name }}' + }, }) diff --git a/libs/blocks/bulk-publish-v2/components/bulk-publisher.css b/libs/blocks/bulk-publish-v2/components/bulk-publisher.css index 9dfd39355d..0620e63303 100644 --- a/libs/blocks/bulk-publish-v2/components/bulk-publisher.css +++ b/libs/blocks/bulk-publish-v2/components/bulk-publisher.css @@ -39,6 +39,10 @@ right: 0; } +.error-btns { + display: flex; +} + .prompt .load-indicator { display: inline-flex; gap: 22px; @@ -238,7 +242,8 @@ label[for='urls'] i { justify-content: space-between; } -.error-bar .fix-btn { +.error-bar .fix-btn, +.error-bar .clear-btn { background-color: white; color: var(--error); padding: 3px 8px; @@ -248,7 +253,8 @@ label[for='urls'] i { font-size: 0.8em; } -.error-bar .fix-btn:hover { +.error-bar .fix-btn:hover, +.error-bar .clear-btn:hover { background-color: #f9f9f9; } @@ -370,7 +376,7 @@ label[for='urls'] i { min-width: var(--meta-width); } -.job-meta > *:last-child { +.job-meta>*:last-child { text-align: right; } @@ -485,4 +491,4 @@ label[for='urls'] i { .processor { width: auto; } -} +} \ No newline at end of file diff --git a/libs/blocks/bulk-publish-v2/components/bulk-publisher.js b/libs/blocks/bulk-publish-v2/components/bulk-publisher.js index fb3a71f132..2e4175c777 100644 --- a/libs/blocks/bulk-publish-v2/components/bulk-publisher.js +++ b/libs/blocks/bulk-publish-v2/components/bulk-publisher.js @@ -8,6 +8,7 @@ import { editEntry, FORM_MODES, getJobErrorText, + getProcessedCount, isValidUrl, processJobResult, PROCESS_TYPES, @@ -164,8 +165,14 @@ class BulkPublish2 extends LitElement { return html`
Error: ${text} -
startEdit(true)}> - ${count === 1 ? 'Done' : btnText} +
+ ${count >= 1 ? html` +
startEdit(true)}> + ${btnText} +
` : ''} +
this.reset()}> + Clear +
`; @@ -269,6 +276,8 @@ class BulkPublish2 extends LitElement { if (this.jobs.filter((job) => !job.status).length === 0) { this.processing = false; sticky().set('resume', []); + const progressCount = this.renderRoot.querySelector('#progress'); + if (progressCount) progressCount.innerHTML = 0; } } @@ -276,15 +285,8 @@ class BulkPublish2 extends LitElement { const { name, progress } = event.detail; const jobProcess = this.jobs.find(({ result }) => result.job.name === name); if (jobProcess) jobProcess.progress = progress; - this.requestUpdate(); - } - - renderProgress(done) { - if (!done) return ''; - return `${this.jobs.reduce((count, { progress }) => { - const processed = progress?.processed ?? 0; - return count + processed; - }, 0)}/${done}`; + const progressCount = this.renderRoot.querySelector('#progress'); + if (progressCount) progressCount.innerHTML = getProcessedCount(this.jobs); } clearJobs = () => { @@ -315,7 +317,7 @@ class BulkPublish2 extends LitElement { Clear List Icon
- ${this.renderProgress(count)} + 0/${count}
diff --git a/libs/blocks/bulk-publish-v2/components/job-process.css b/libs/blocks/bulk-publish-v2/components/job-process.css index ab7e4e3a26..1f5b703e83 100644 --- a/libs/blocks/bulk-publish-v2/components/job-process.css +++ b/libs/blocks/bulk-publish-v2/components/job-process.css @@ -42,6 +42,10 @@ color: black; } +.status[has-update] { + display: none; +} + .result.success.link .url { color: var(--link-color); } diff --git a/libs/blocks/bulk-publish-v2/components/job-process.js b/libs/blocks/bulk-publish-v2/components/job-process.js index e686650fc7..fde3f72551 100644 --- a/libs/blocks/bulk-publish-v2/components/job-process.js +++ b/libs/blocks/bulk-publish-v2/components/job-process.js @@ -1,6 +1,6 @@ import { LitElement, html } from '../../../deps/lit-all.min.js'; import { getSheet } from '../../../../tools/utils/utils.js'; -import { displayDate, getStatusText, delay } from '../utils.js'; +import { displayDate, getStatusText, delay, updateItemProgress } from '../utils.js'; import { pollJobStatus, updateRetry } from '../services.js'; import { getConfig } from '../../../utils/utils.js'; @@ -30,7 +30,12 @@ class JobProcess extends LitElement { this.renderRoot.adoptedStyleSheets = [styleSheet]; if (this.job?.useBulk) { await pollJobStatus(this.job, (detail) => { - this.jobStatus = detail; + if (detail.state === 'stopped') { + this.jobStatus = detail; + /* c8 ignore next 3 */ + } else { + updateItemProgress(detail, this); + } this.dispatchEvent(new CustomEvent('progress', { detail })); }); } else { @@ -39,10 +44,11 @@ class JobProcess extends LitElement { } async updated() { - if (this.jobStatus?.state === 'stopped') { + const stopped = this.jobStatus?.state === 'stopped'; + if (stopped) { this.dispatchEvent(new CustomEvent('stopped', { detail: this.jobStatus })); } - if (this.jobStatus?.progress?.failed !== 0) { + if (stopped && this.jobStatus?.progress?.failed !== 0) { const timeouts = this.jobStatus?.data?.resources?.filter((job) => job.status === 503) ?? []; this.retry(timeouts); } @@ -118,30 +124,33 @@ class JobProcess extends LitElement { }; } + renderJobItem(path, pathIndex) { + const jobPath = typeof path === 'object' ? path.path : path; + const { style, status, topic, url, time } = this.getJob(jobPath); + return html` +
this.onClick({ url, code: status.code, topic }, pathIndex)}> +
+ ${topic} ${url} +
+
+ ${status.text} + { this.expandDate = url; }} + @mouseleave=${() => { this.expandDate = false; }}> + ${this.expandDate === url ? time.label : ''} ${displayDate(time.stamp)} + +
+
+ `; + } + render() { const { job } = this.job.result; - return job.data.paths.map((path, pathIndex) => { - const jobPath = typeof path === 'object' ? path.path : path; - const { style, status, topic, url, time } = this.getJob(jobPath); - return html` -
this.onClick({ url, code: status.code, topic }, pathIndex)}> -
- ${topic} ${url} -
-
- ${status.text} - { this.expandDate = url; }} - @mouseleave=${() => { this.expandDate = false; }}> - ${this.expandDate === url ? time.label : ''} ${displayDate(time.stamp)} - -
-
- `; - }); + return job.data.paths.map((path, pathIndex) => this.renderJobItem(path, pathIndex)); } } diff --git a/libs/blocks/bulk-publish-v2/services.js b/libs/blocks/bulk-publish-v2/services.js index e239bbb687..24210b4b27 100644 --- a/libs/blocks/bulk-publish-v2/services.js +++ b/libs/blocks/bulk-publish-v2/services.js @@ -159,12 +159,22 @@ const startJob = async (details) => { }; } }); - const results = await Promise.all(requests); + // batch to limit concurrency + const results = []; + while (requests.length) { + if (requests.length > 5) await delay(5000); + const result = await Promise.all(requests.splice(0, 4)); + results.push(...result); + } return results; }; +// fetch one job status at a time +const statusQueue = []; const getJobStatus = async (link) => { - await delay(); + await delay(5000); + if (!statusQueue.includes(link)) statusQueue.push(link); + if (statusQueue.indexOf(link) !== 0) return null; try { const status = await fetch(link, { headers }); const result = await status.json(); @@ -181,11 +191,12 @@ const pollJobStatus = async (job, setProgress) => { let stopped = false; while (!stopped) { const status = await getJobStatus(`${result.links.self}/details`); - if (status.stopTime) { + if (status?.stopTime) { jobStatus = status; stopped = true; + statusQueue.shift(); } - setProgress(status); + if (status) setProgress(status); } return jobStatus; }; diff --git a/libs/blocks/bulk-publish-v2/utils.js b/libs/blocks/bulk-publish-v2/utils.js index b839644609..225153c483 100644 --- a/libs/blocks/bulk-publish-v2/utils.js +++ b/libs/blocks/bulk-publish-v2/utils.js @@ -1,3 +1,5 @@ +import { createTag } from '../../utils/utils.js'; + const PREFS = 'bulk-pub-prefs'; const FORM_MODES = ['full', 'half']; const DEFAULT_PREFS = { mode: FORM_MODES[0], resume: [] }; @@ -97,6 +99,24 @@ const getStatusText = (status, state, count) => { return { code, text, color }; }; +/* c8 ignore next 16 */ +const updateItemProgress = (detail, tool) => { + const resources = detail.data?.resources?.filter((res) => res.status !== 0); + if (resources) { + resources.forEach(({ path, status }) => { + const item = tool.renderRoot.querySelector(`[job-item='${path}']`); + if (item && !item?.hasAttribute('updated')) { + const { text, color } = getStatusText(status, null); + const newStatus = createTag('span', { class: `status ${color}` }, text); + const display = item.querySelector('.status'); + display.insertAdjacentElement('afterend', newStatus); + display.setAttribute('has-update', ''); + item.setAttribute('updated', ''); + } + }); + } +}; + const displayDate = (newDate) => { const date = new Date(newDate); const today = new Date(); @@ -109,6 +129,11 @@ const processJobResult = (jobs) => jobs.reduce((result, job) => { return result; }, { complete: [], error: [] }); +const getProcessedCount = (jobs) => jobs.reduce((count, { progress }) => { + const processed = progress?.processed ?? 0; + return count + processed; +}, 0); + export { frisk, displayDate, @@ -117,10 +142,12 @@ export { getErrorText, getJobErrorText, getAemUrl, + getProcessedCount, isDelete, PROCESS_TYPES, processJobResult, getStatusText, + updateItemProgress, sticky, isValidUrl, delay, diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index 2c651274ce..57ed96bb92 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -64,7 +64,7 @@ export const normalizePath = (p) => { if (path.startsWith(config.codeRoot) || path.includes('.hlx.') - || path.startsWith(`https://${config.productionDomain}`)) { + || path.includes('.adobe.')) { try { const url = new URL(path); const firstFolder = url.pathname.split('/')[1]; @@ -86,14 +86,13 @@ export const preloadManifests = ({ targetManifests = [], persManifests = [] }) = manifests = manifests.concat( persManifests.map((manifest) => ({ ...manifest, - manifestPath: appendJsonExt(manifest.manifestPath), + manifestPath: normalizePath(appendJsonExt(manifest.manifestPath)), manifestUrl: manifest.manifestPath, })), ); for (const manifest of manifests) { if (!manifest.manifestData && manifest.manifestPath && !manifest.disabled) { - manifest.manifestPath = normalizePath(manifest.manifestPath); loadLink( manifest.manifestPath, { as: 'fetch', crossorigin: 'anonymous', rel: 'preload' },