20454: Consolidate cost display to a single 'Cost' field 20454-cost-display
authorPeter Amstutz <peter.amstutz@curii.com>
Wed, 9 Aug 2023 20:27:51 +0000 (16:27 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Wed, 9 Aug 2023 20:27:51 +0000 (16:27 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

src/models/container-request.ts
src/store/processes/processes-actions.ts
src/views/process-panel/process-details-attributes.tsx

index 02a8ea7017b54d6ff099aa9903ca2962a0722a8a..d3adb03a92a435019f3a368cd36f0a822773f999 100644 (file)
@@ -53,6 +53,7 @@ export const containerRequestFieldsNoMounts = [
     "container_image",
     "container_uuid",
     "created_at",
+    "cumulative_cost",
     "cwd",
     "description",
     "environment",
index 4a27cba6da89b4cd8a1b3ea1705cd5f646dff1fc..b6ff4b71acd55e25ee854421440203014971e8b6 100644 (file)
@@ -40,7 +40,7 @@ export const loadProcess = (containerRequestUuid: string) =>
             try {
                 const collection = await services.collectionService.get(containerRequest.outputUuid, false);
                 dispatch<any>(updateResources([collection]));
-            } catch {}
+            } catch { }
         }
 
         if (containerRequest.containerUuid) {
@@ -48,14 +48,14 @@ export const loadProcess = (containerRequestUuid: string) =>
             try {
                 container = await services.containerService.get(containerRequest.containerUuid, false);
                 dispatch<any>(updateResources([container]));
-            } catch {}
+            } catch { }
 
-            try{
+            try {
                 if (container && container.runtimeUserUuid) {
                     const runtimeUser = await services.userService.get(container.runtimeUserUuid, false);
                     dispatch<any>(updateResources([runtimeUser]));
                 }
-            } catch {}
+            } catch { }
 
             return { containerRequest, container };
         }
@@ -67,7 +67,7 @@ export const loadContainers = (containerUuids: string[], loadMounts: boolean = t
         let args: any = {
             filters: new FilterBuilder().addIn('uuid', containerUuids).getFilters(),
             limit: containerUuids.length,
-         };
+        };
         if (!loadMounts) {
             args.select = containerFieldsNoMounts;
         }
@@ -112,6 +112,7 @@ const containerFieldsNoMounts = [
     "scheduling_parameters",
     "started_at",
     "state",
+    "subrequests_cost",
     "uuid",
 ]
 
@@ -210,7 +211,7 @@ export const getRawInputs = (data: any): WorkflowInputsData | undefined => {
 export const getInputs = (data: any): CommandInputParameter[] => {
     // Definitions from mounts are needed so we return early if missing
     if (!data || !data.mounts || !data.mounts[MOUNT_PATH_CWL_WORKFLOW]) { return []; }
-    const content  = getRawInputs(data) as any;
+    const content = getRawInputs(data) as any;
     // Only escape if content is falsy to allow displaying definitions if no inputs are present
     // (Don't check raw content length)
     if (!content) { return []; }
@@ -252,8 +253,8 @@ export const getInputCollectionMounts = (data: any): InputCollectionMount[] => {
             path: key,
         }))
         .filter(mount => mount.kind === 'collection' &&
-                mount.portable_data_hash &&
-                mount.path)
+            mount.portable_data_hash &&
+            mount.path)
         .map(mount => ({
             path: mount.path,
             pdh: mount.portable_data_hash,
@@ -297,7 +298,7 @@ export const removeProcessPermanently = (uuid: string) =>
             await services.containerRequestService.delete(uuid, false);
             dispatch(projectPanelActions.REQUEST_ITEMS());
             dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removed.', hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
-        } catch(e) {
+        } catch (e) {
             const error = getCommonResourceServiceError(e);
             if (error === CommonResourceServiceError.PERMISSION_ERROR_FORBIDDEN) {
                 dispatch(snackbarActions.OPEN_SNACKBAR({ message: `Access denied`, hideDuration: 2000, kind: SnackbarKind.ERROR }));
index 7bdf889797babf88d816a17935d3848388ddb2d5..b0d8039f93d14e506aaee8c3ac840b518fdb84ff 100644 (file)
@@ -68,7 +68,9 @@ export const ProcessDetailsAttributes = withStyles(styles, { withTheme: true })(
             const classes = props.classes;
             const mdSize = props.twoCol ? 6 : 12;
             const filteredPropertyKeys = Object.keys(containerRequest.properties)
-                                            .filter(k => (typeof containerRequest.properties[k] !== 'object'));
+                .filter(k => (typeof containerRequest.properties[k] !== 'object'));
+            const hasTotalCost = containerRequest && containerRequest.cumulativeCost > 0;
+            const totalCostNotReady = container && container.cost > 0 && container.state === "Running" && containerRequest && containerRequest.cumulativeCost === 0 && subprocesses.length > 0;
             return <Grid container>
                 <Grid item xs={12}>
                     <ProcessRuntimeStatus runtimeStatus={container?.runtimeStatus} containerCount={containerRequest.containerCount} />
@@ -127,11 +129,10 @@ export const ProcessDetailsAttributes = withStyles(styles, { withTheme: true })(
                         <CollectionName className={classes.link} uuid={containerRequest.outputUuid} />
                     </span>}
                 </Grid>
-                {container && container.cost > 0 && <Grid item xs={12} md={mdSize}>
-                        <DetailsAttribute label='Cost ' value={formatContainerCost(container.cost)} />
-                </Grid>}
-                {containerRequest && containerRequest.cumulativeCost > 0 && subprocesses.length > 0 && <Grid item xs={12} md={mdSize}>
-                    <DetailsAttribute label='Container &amp; subprocess cost' value={formatContainerCost(containerRequest.cumulativeCost)} />
+                {container && <Grid item xs={12} md={mdSize}>
+                    <DetailsAttribute label='Cost' value={
+                        `${hasTotalCost ? formatContainerCost(containerRequest.cumulativeCost) + ' total, ' : (totalCostNotReady ? 'total pending completion, ' : '')}${container.cost > 0 ? formatContainerCost(container.cost) : 'not available'} for this container`
+                    } />
                 </Grid>}
                 {containerRequest.properties.template_uuid &&
                     <Grid item xs={12} md={mdSize}>
@@ -144,9 +145,9 @@ export const ProcessDetailsAttributes = withStyles(styles, { withTheme: true })(
                     <DetailsAttribute label='Priority' value={containerRequest.priority} />
                 </Grid>
                 {/*
-                    NOTE: The property list should be kept at the bottom, because it spans
-                    the entire available width, without regards of the twoCol prop.
-                */}
+                       NOTE: The property list should be kept at the bottom, because it spans
+                       the entire available width, without regards of the twoCol prop.
+                       */}
                 <Grid item xs={12} md={12}>
                     <DetailsAttribute label='Properties' />
                     {filteredPropertyKeys.length > 0