From: Lisa Knox Date: Thu, 24 Nov 2022 18:36:04 +0000 (-0500) Subject: 19690: metadata and portabledatahash columns up X-Git-Tag: 2.5.0~15^2~18 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/f8f6c21d5162f38e6e644a628b9caae6e1e23f88 19690: metadata and portabledatahash columns up Arvados-DCO-1.1-Signed-off-by: Lisa Knox --- diff --git a/src/common/formatters.ts b/src/common/formatters.ts index 1fbf1710..c03bf04b 100644 --- a/src/common/formatters.ts +++ b/src/common/formatters.ts @@ -2,114 +2,139 @@ // // SPDX-License-Identifier: AGPL-3.0 -import { PropertyValue } from "models/search-bar"; -import { Vocabulary, getTagKeyLabel, getTagValueLabel } from "models/vocabulary"; +import { PropertyValue } from 'models/search-bar'; +import { + Vocabulary, + getTagKeyLabel, + getTagValueLabel, +} from 'models/vocabulary'; export const formatDate = (isoDate?: string | null, utc: boolean = false) => { - if (isoDate) { - const date = new Date(isoDate); - let text: string; - if (utc) { - text = date.toUTCString(); - } - else { - text = date.toLocaleString(); - } - return text === 'Invalid Date' ? "(none)" : text; + if (isoDate) { + const date = new Date(isoDate); + let text: string; + if (utc) { + text = date.toUTCString(); + } else { + text = date.toLocaleString(); } - return "(none)"; + return text === 'Invalid Date' ? '(none)' : text; + } + return '(none)'; }; export const formatFileSize = (size?: number | string) => { - if (typeof size === "number") { - if (size === 0) { return "0 B"; } - - for (const { base, unit } of FILE_SIZES) { - if (size >= base) { - return `${(size / base).toFixed()} ${unit}`; - } - } + if (typeof size === 'number') { + if (size === 0) { + return '0 B'; } - if ((typeof size === "string" && size === '') || size === undefined) { - return ''; + + for (const { base, unit } of FILE_SIZES) { + if (size >= base) { + return `${(size / base).toFixed()} ${unit}`; + } } - return "0 B"; + } + if ((typeof size === 'string' && size === '') || size === undefined) { + return ''; + } + return '0 B'; }; export const formatTime = (time: number, seconds?: boolean) => { - const minutes = Math.floor(time / (1000 * 60) % 60).toFixed(0); - const hours = Math.floor(time / (1000 * 60 * 60)).toFixed(0); + const minutes = Math.floor((time / (1000 * 60)) % 60).toFixed(0); + const hours = Math.floor(time / (1000 * 60 * 60)).toFixed(0); - if (seconds) { - const seconds = Math.floor(time / (1000) % 60).toFixed(0); - return hours + "h " + minutes + "m " + seconds + "s"; - } + if (seconds) { + const seconds = Math.floor((time / 1000) % 60).toFixed(0); + return hours + 'h ' + minutes + 'm ' + seconds + 's'; + } - return hours + "h " + minutes + "m"; + return hours + 'h ' + minutes + 'm'; }; export const getTimeDiff = (endTime: string, startTime: string) => { - return new Date(endTime).getTime() - new Date(startTime).getTime(); + return new Date(endTime).getTime() - new Date(startTime).getTime(); }; export const formatProgress = (loaded: number, total: number) => { - const progress = loaded >= 0 && total > 0 ? loaded * 100 / total : 0; - return `${progress.toFixed(2)}%`; + const progress = loaded >= 0 && total > 0 ? (loaded * 100) / total : 0; + return `${progress.toFixed(2)}%`; }; -export function formatUploadSpeed(prevLoaded: number, loaded: number, prevTime: number, currentTime: number) { - const speed = loaded > prevLoaded && currentTime > prevTime - ? (loaded - prevLoaded) / (currentTime - prevTime) - : 0; +export function formatUploadSpeed( + prevLoaded: number, + loaded: number, + prevTime: number, + currentTime: number +) { + const speed = + loaded > prevLoaded && currentTime > prevTime + ? (loaded - prevLoaded) / (currentTime - prevTime) + : 0; - return `${(speed / 1000).toFixed(2)} MB/s`; + return `${(speed / 1000).toFixed(2)} MB/s`; } const FILE_SIZES = [ - { - base: 1099511627776, - unit: "TB" - }, - { - base: 1073741824, - unit: "GB" - }, - { - base: 1048576, - unit: "MB" - }, - { - base: 1024, - unit: "KB" - }, - { - base: 1, - unit: "B" - } + { + base: 1099511627776, + unit: 'TB', + }, + { + base: 1073741824, + unit: 'GB', + }, + { + base: 1048576, + unit: 'MB', + }, + { + base: 1024, + unit: 'KB', + }, + { + base: 1, + unit: 'B', + }, ]; -export const formatPropertyValue = (pv: PropertyValue, vocabulary?: Vocabulary) => { - if (vocabulary && pv.keyID && pv.valueID) { - return `${getTagKeyLabel(pv.keyID, vocabulary)}: ${getTagValueLabel(pv.keyID, pv.valueID!, vocabulary)}`; - } - if (pv.key) { - return pv.value - ? `${pv.key}: ${pv.value}` - : pv.key; - } - return ""; +export const formatPropertyValue = ( + pv: PropertyValue, + vocabulary?: Vocabulary +) => { + if (vocabulary && pv.keyID && pv.valueID) { + return `${getTagKeyLabel(pv.keyID, vocabulary)}: ${getTagValueLabel( + pv.keyID, + pv.valueID!, + vocabulary + )}`; + } + if (pv.key) { + return pv.value ? `${pv.key}: ${pv.value}` : pv.key; + } + return ''; }; export const formatContainerCost = (cost: number): string => { - const decimalPlaces = 3; + const decimalPlaces = 3; - const factor = Math.pow(10, decimalPlaces); - const rounded = Math.round(cost*factor)/factor; - if (cost > 0 && rounded === 0) { - // Display min value of 0.001 - return `$${1/factor}`; - } else { - // Otherwise use rounded value to proper decimal places - return `$${rounded}`; - } + const factor = Math.pow(10, decimalPlaces); + const rounded = Math.round(cost * factor) / factor; + if (cost > 0 && rounded === 0) { + // Display min value of 0.001 + return `$${1 / factor}`; + } else { + // Otherwise use rounded value to proper decimal places + return `$${rounded}`; + } +}; + +export const formatObjectProperties = (untypedObj: Object) => { + type kVPair = [string, string]; + let formattedObject: Array = []; + for (const key in untypedObj) { + formattedObject.push([key, untypedObj[key]]); + } + return formattedObject; }; diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx index dc19ff65..9c0bccb0 100644 --- a/src/views-components/data-explorer/renderers.tsx +++ b/src/views-components/data-explorer/renderers.tsx @@ -30,7 +30,7 @@ import { SetupIcon, InactiveIcon, } from 'components/icon/icon'; -import { formatDate, formatFileSize, formatTime } from 'common/formatters'; +import { formatDate, formatFileSize, formatTime, formatObjectProperties} from 'common/formatters'; import { resourceLabel } from 'common/labels'; import { connect, DispatchProp } from 'react-redux'; import { RootState } from 'store/store'; @@ -723,13 +723,25 @@ export const ResourceOwnerName = connect( return { owner: ownerName ? ownerName!.name : resource!.ownerUuid }; })((props: { owner: string }) => renderOwner(props.owner)); -const renderUUID = (uuid:string) => {uuid} - export const ResourceUUID = connect( (state: RootState, props: { uuid: string }) => { - const resource = getResource(props.uuid)(state.resources); + const resource = getResource(props.uuid)(state.resources); return { uuid: resource ? resource.uuid : '' }; - })((props: { uuid: string }) => renderUUID(props.uuid)); + })((props: { uuid: string }) => renderUuid({uuid: props.uuid})); + +const renderMetadata = (metadata:any) => { + return <>{formatObjectProperties(metadata).map((property, i)=> + {property[0]}: {property[1]} + )} +} + +export const ResourceMetadata = connect( + (state: RootState, props: { uuid: string }) => { + const resource = getResource(props.uuid)(state.resources); + const metadata = resource && Object.keys(resource.properties).length ? {...resource.properties} : {} + if(resource && resource.portableDataHash) metadata['Portable Data Hash'] = resource.portableDataHash + return { properties: metadata }; + })((props: { properties: string }) => renderMetadata(props.properties)); const renderDescription = (description: string)=>{ const truncatedDescription = description ? description.slice(0, 18) + '...' : '-' diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx index 2958271e..ef9fdc9e 100644 --- a/src/views/project-panel/project-panel.tsx +++ b/src/views/project-panel/project-panel.tsx @@ -24,6 +24,7 @@ import { ProcessStatus, ResourceType, ResourceUUID, + ResourceMetadata, ResourceDescription, ResourceOwnerWithName } from 'views-components/data-explorer/renderers'; @@ -74,7 +75,8 @@ export enum ProjectPanelColumnNames { LAST_MODIFIED = "Last modified", TRASH_AT = "Trash at", DELETE_AT = "Delete at", - DESCRIPTION = "Description" + DESCRIPTION = "Description", + METADATA = "Metadata" } export interface ProjectPanelFilter extends DataTableFilterItem { @@ -121,21 +123,28 @@ export const projectPanelColumns: DataColumns = [ }, { name: ProjectPanelColumnNames.UUID, - selected: false, + selected: true, configurable: true, filters: createTree(), render: uuid => }, { - name: ProjectPanelColumnNames.CREATED_AT, + name: ProjectPanelColumnNames.METADATA, selected: true, configurable: true, filters: createTree(), + render: uuid => + }, + { + name: ProjectPanelColumnNames.CREATED_AT, + selected: false, + configurable: true, + filters: createTree(), render: uuid => }, { name: ProjectPanelColumnNames.LAST_MODIFIED, - selected: true, + selected: false, configurable: true, sortDirection: SortDirection.DESC, filters: createTree(),