diff --git a/assets/src/bundles/save/index.js b/assets/src/bundles/save/index.js --- a/assets/src/bundles/save/index.js +++ b/assets/src/bundles/save/index.js @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018-2020 The Software Heritage developers + * Copyright (C) 2018-2021 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information @@ -336,6 +336,18 @@ }); } +export function formatValuePerType(type, value) { + // Given some typed value, format and return accordingly formatted value + const mapFormatPerTypeFn = { + 'json': (v) => JSON.stringify(v, null, 2), + 'date': (v) => new Date(v).toLocaleString(), + 'raw': (v) => v, + 'duration': (v) => v + ' seconds' + }; + + return mapFormatPerTypeFn[type](value); +} + export function displaySaveRequestInfo(event, saveRequestId) { event.stopPropagation(); const saveRequestTaskInfoUrl = Urls.origin_save_task_info(saveRequestId); @@ -379,65 +391,26 @@ content = 'Not available'; } else { let saveRequestInfo = []; - if (saveRequestTaskInfo.type) { - saveRequestInfo.push({ - key: 'Task type', - value: saveRequestTaskInfo.type - }); - } - if (saveRequestTaskInfo.arguments) { - saveRequestInfo.push({ - key: 'Task arguments', - value: JSON.stringify(saveRequestTaskInfo.arguments, null, 2) - }); - } - if (saveRequestTaskInfo.id) { - saveRequestInfo.push({ - key: 'Task id', - value: saveRequestTaskInfo.id - }); - } - if (saveRequestTaskInfo.backend_id) { - saveRequestInfo.push({ - key: 'Task backend id', - value: saveRequestTaskInfo.backend_id - }); - } - if (saveRequestTaskInfo.scheduled) { - saveRequestInfo.push({ - key: 'Task scheduling date', - value: new Date(saveRequestTaskInfo.scheduled).toLocaleString() - }); - } - if (saveRequestTaskInfo.started) { - saveRequestInfo.push({ - key: 'Task start date', - value: new Date(saveRequestTaskInfo.started).toLocaleString() - }); - } - if (saveRequestTaskInfo.ended) { - saveRequestInfo.push({ - key: 'Task termination date', - value: new Date(saveRequestTaskInfo.ended).toLocaleString() - }); - } - if (saveRequestTaskInfo.duration) { - saveRequestInfo.push({ - key: 'Task duration', - value: saveRequestTaskInfo.duration + ' seconds' - }); - } - if (saveRequestTaskInfo.worker) { - saveRequestInfo.push({ - key: 'Task executor', - value: saveRequestTaskInfo.worker - }); - } - if (saveRequestTaskInfo.message) { - saveRequestInfo.push({ - key: 'Task log', - value: saveRequestTaskInfo.message - }); + const taskData = { + 'Type': ['raw', 'type'], + 'Visit status': ['raw', 'visit_status'], + 'Arguments': ['json', 'arguments'], + 'Id': ['raw', 'id'], + 'Backend id': ['raw', 'backend_id'], + 'Scheduling date': ['date', 'scheduled'], + 'Start date': ['date', 'started'], + 'Termination date': ['date', 'ended'], + 'Duration': ['duration', 'duration'], + 'Executor': ['raw', 'worker'], + 'Log': ['raw', 'message'] + }; + for (const [title, [type, property]] of Object.entries(taskData)) { + if (saveRequestTaskInfo.hasOwnProperty(property)) { + saveRequestInfo.push({ + key: title, + value: formatValuePerType(type, saveRequestTaskInfo[property]) + }); + } } content = ''; for (let info of saveRequestInfo) { diff --git a/cypress/integration/origin-save.spec.js b/cypress/integration/origin-save.spec.js --- a/cypress/integration/origin-save.spec.js +++ b/cypress/integration/origin-save.spec.js @@ -45,7 +45,8 @@ responseStatus = 200, errorMessage = '', saveRequestDate = new Date(), - visitDate = new Date() + visitDate = new Date(), + visitStatus = null } = {}) { let response; if (responseStatus !== 200 && errorMessage) { @@ -58,7 +59,9 @@ originUrl: originUrl, saveRequestDate: saveRequestDate, saveTaskStatus: saveTaskStatus, - visitDate: visitDate}); + visitDate: visitDate, + visitStatus: visitStatus + }); } cy.intercept('POST', requestUrl, {body: response, statusCode: responseStatus}) .as('saveRequest'); @@ -72,7 +75,8 @@ originUrl, saveRequestDate = new Date(), saveTaskStatus, - visitDate = new Date() + visitDate = new Date(), + visitStatus } = {}) { return { 'visit_type': visitType, @@ -81,7 +85,8 @@ 'id': 1, 'save_request_date': saveRequestDate ? saveRequestDate.toISOString() : null, 'save_task_status': saveTaskStatus, - 'visit_date': visitDate ? visitDate.toISOString() : null + 'visit_date': visitDate ? visitDate.toISOString() : null, + 'visit_status': visitStatus }; }; @@ -249,7 +254,8 @@ saveRequestStatus: 'accepted', originUrl: originUrl, saveTaskStatus: 'succeeded', - visitDate: null + visitDate: null, + visitStatus: 'full' }); const saveRequestsListData = { 'recordsTotal': 1, @@ -335,6 +341,7 @@ saveRequestStatus: 'accepted', originUrl: originUrl, saveTaskStatus: 'failed', + visitStatus: 'failed', responseStatus: 200, errorMessage: saveCodeMsg['accepted']}); diff --git a/swh/web/common/origin_save.py b/swh/web/common/origin_save.py --- a/swh/web/common/origin_save.py +++ b/swh/web/common/origin_save.py @@ -529,6 +529,7 @@ - **scheduled**: loading task scheduling date - **ended**: loading task termination date - **status**: loading task execution status + - **visit_status**: Actual visit status Depending on the availability of the task logs in the elasticsearch cluster of Software Heritage, the returned dictionary may also @@ -558,6 +559,8 @@ task_run["id"] = task_run["task"] del task_run["task"] del task_run["metadata"] + # Enrich the task run with the loading visit status + task_run["visit_status"] = save_request.visit_status es_workers_index_url = config.get_config()["es_workers_index_url"] if not es_workers_index_url: diff --git a/swh/web/tests/common/test_origin_save.py b/swh/web/tests/common/test_origin_save.py --- a/swh/web/tests/common/test_origin_save.py +++ b/swh/web/tests/common/test_origin_save.py @@ -132,6 +132,7 @@ "started": task_run["started"], "ended": task_run["ended"], "status": task_run["status"], + "visit_status": sor.visit_status, } if not task_archived else {}