From e717580eb32b880891b8090f076a4d8a3d2e104e Mon Sep 17 00:00:00 2001 From: EMaslowskiQ <118929649+EMaslowskiQ@users.noreply.github.com> Date: Wed, 14 Aug 2024 17:18:26 -0400 Subject: [PATCH] (0.9.21f2) Hot Fix: Invalid scenes failing and UX improvements (#621) * DPO3DPKRT-844/Display Media Group in Batch Generation Table (#618) * DPO3DPKRT-840/UX Improvements to Batch Generation (#619) * DPO3DPKRT-843/invalid Scenes Crash Batch Download (#620) --- client/src/api/index.ts | 5 +- .../pages/Admin/components/AdminToolsView.tsx | 147 ++++++++++++------ server/http/routes/api/generateDownloads.ts | 126 ++++----------- server/http/routes/api/project.ts | 3 +- .../workflow/impl/Packrat/WorkflowEngine.ts | 2 +- 5 files changed, 135 insertions(+), 148 deletions(-) diff --git a/client/src/api/index.ts b/client/src/api/index.ts index e4fe2c00..8eb03c99 100644 --- a/client/src/api/index.ts +++ b/client/src/api/index.ts @@ -46,7 +46,6 @@ export default class API { const body = JSON.stringify({ statusOnly, rePublish, idSystemObject }); let uri: string = API_ROUTES.GEN_DOWNLOADS; console.log('[PACKRAT:DEBUG] body: ',body); - console.trace('API.generateDownloads'); let options; if(statusOnly) { @@ -82,8 +81,10 @@ export default class API { return fetch(`${serverEndpoint}/${route}`, defaultOptions) .then(response => { // Check if the response returned a successful status code - if (!response.ok) + if (!response.ok) { + console.log('response: ',response); return { success: false, message: response.statusText }; + } return response.json(); // Assuming the server responds with JSON }) .catch(error => { diff --git a/client/src/pages/Admin/components/AdminToolsView.tsx b/client/src/pages/Admin/components/AdminToolsView.tsx index 7671b9f8..b5d91b32 100644 --- a/client/src/pages/Admin/components/AdminToolsView.tsx +++ b/client/src/pages/Admin/components/AdminToolsView.tsx @@ -213,7 +213,7 @@ const SelectScenesTable = ({ onUpdateSelection, data, col const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; }; - const resolveProperty = (obj: T, path: string): string | undefined => { + const resolveProperty = (obj: T, path: string): string => { if(!obj || path.length<=0) { console.log(`[Packrat:ERROR] invalid inputs for resolveProperty (obj: ${obj ? 'true':'false'} | path: ${path})`); @@ -400,26 +400,27 @@ const SelectScenesTable = ({ onUpdateSelection, data, col /> { columns.map((columnHeading) => ( - - + - {columnHeading.label} - {orderBy === columnHeading.key ? ( - - {order === 'desc' ? 'sorted descending' : 'sorted ascending'} - - ) : null} - - + + {columnHeading.label} + {orderBy === columnHeading.key ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ))} @@ -454,17 +455,25 @@ const SelectScenesTable = ({ onUpdateSelection, data, col {columns.map((column) => ( // we do 'id' above so we can flag the entire row for accessibility (column.key!=='id') && ( - - { (column.link && column.link===true) ? ( - <> - - {resolveProperty(row,column.key)} - - - ) : ( - resolveProperty(row, column.key) - )} - + + + { (column.link && column.link===true) ? ( + <> + + {resolveProperty(row,column.key)} + + + ) : ( + resolveProperty(row, column.key) + )} + + ) ))} @@ -590,11 +599,12 @@ const AdminToolsBatchGeneration = (): React.ReactElement => { }, []); const getColumnHeader = (): ColumnHeader[] => { return [ - { key: 'id', label: 'ID', align: 'center' }, - { key: 'name', label: 'Scene Name', align: 'center', link: true }, - { key: 'subject.name', label: 'Subject Name', align: 'center' }, - { key: 'downloads.status', label: 'Downloads', align: 'center' }, - { key: 'publishedState', label: 'Published', align: 'center' }, + { key: 'id', label: 'ID', align: 'center', tooltip: 'idSystemObject for the scene' }, + { key: 'name', label: 'Scene', align: 'center', tooltip: 'Name of the scene', link: true }, + { key: 'mediaGroup.name', label: 'Media Group', align: 'center', tooltip: 'What MediaGroup the scene belongs to. Includes the the subtitle (if any).' }, + { key: 'subject.name', label: 'Subject', align: 'center', tooltip: 'The official subject name for the object' }, + { key: 'downloads.status', label: 'Downloads', align: 'center', tooltip: 'Are downloads in good standing (GOOD), available but contain errors (ERROR), or are not available (MISSING).' }, + { key: 'publishedState', label: 'Published', align: 'center', tooltip: 'Is the scene published and with what accessibility' }, // { key: 'datePublished', label: 'Published (Date)', align: 'center' }, // { key: 'isReviewed', label: 'Reviewed', align: 'center' } ]; @@ -628,15 +638,43 @@ const AdminToolsBatchGeneration = (): React.ReactElement => { const response: RequestResponse = await API.generateDownloads(sceneIDs,false,republishScenes); if(response.success === false) { - // if the job is running then handle differently - if(response.message && response.message.includes('already running')) { - console.log(`[Packrat:WARN] cannot do ${BatchOperations[operation]}. (${response.message})`); - toast.warn(`Not running ${BatchOperations[operation]}. Job already running. Please wait for it to finish.`); - } else { - console.log(`[Packrat:ERROR] cannot run ${BatchOperations[operation]}. (${response.message})`); - toast.error(`Cannot ${BatchOperations[operation]}. Check the report.`); + // make sure we have data and responses + if(!response.data || !Array.isArray(response.data)) { + console.log(`[Packrat:ERROR] cannot run ${BatchOperations[operation]}. invalid response data.`,response); + toast.error(`${BatchOperations[operation]} failed. Got unexpected data from server.`); + return; } - return; + + // get our unique error messages + const uniqueMessages = Array.from( + new Set( + response.data + .filter(response => !response.success && response.message) // Ensure there is a message + .map(response => `${response.id}: ${response.message}`) // Extract the messages + ) + ); + const toastErrorMsg: string = (uniqueMessages.length>1) ? 'Check the console.' : uniqueMessages[0]; + + // see if we have nuance to the response (i.e. some failed/some passed) + const allFailed: boolean = response.data.every( response => response.succcess===false ); + if(allFailed===true) { + const errorMsg: string = (response.data.length>1) + ? `All ${response.data.length} scenes failed during ${BatchOperations[operation]} run.` + : `${BatchOperations[operation]} cannot run. ${uniqueMessages[0]}`; + + console.log(`[Packrat:ERROR] ${errorMsg}`,response.data); + toast.error(`${BatchOperations[operation]} failed. (${toastErrorMsg})`); + return; + } + + // only some failed so we need to handle this + const failedCount: number = response.data.filter(response => !response.success).length; + console.log(`[Packrat:ERROR] ${response.data.length}/${selectedList.length} scenes failed. (${uniqueMessages.join(' |')})`,response.data); + toast.warn(`${BatchOperations[operation]} had issues. ${failedCount} scenes failed. (${toastErrorMsg})`); + + // we bail early so the selection is maintained on failure + // TODO: deselect those that were successful. + return false; } // clear selection on succcess @@ -688,7 +726,22 @@ const AdminToolsBatchGeneration = (): React.ReactElement => { - + + + This tool allows you to batch download and generate scenes with ease. + + {/* + To get started, select your intended project from the dropdown menu. (Note: You can only select one project at a time.) + + + If needed, you can filter the results by scene name. Once you have made your selections, click the Submit button to begin processing. Progress can be monitored in the Workflow Tab. + */} + + Please remember, the process is limited to 10 items at a time to prevent overloading the system. + + + + @@ -737,7 +790,7 @@ const AdminToolsBatchGeneration = (): React.ReactElement => { - + Filter: Project @@ -797,7 +850,7 @@ const AdminToolsBatchGeneration = (): React.ReactElement => { disableElevation disabled={!isListValid} > - Go + Submit