diff --git a/packages/zapp/console/src/common/constants.ts b/packages/zapp/console/src/common/constants.ts index 634a751fc..46870669e 100644 --- a/packages/zapp/console/src/common/constants.ts +++ b/packages/zapp/console/src/common/constants.ts @@ -6,7 +6,7 @@ export const unknownValueString = '(unknown)'; export const dashedValueString = '----'; export const noneString = '(none)'; export const noExecutionsFoundString = 'No executions found.'; -export const noWorkflowVersionsFoundString = 'No workflow versions found.'; +export const noVersionsFoundString = 'No versions found.'; export const zeroSecondsString = '0s'; export enum KeyCodes { diff --git a/packages/zapp/console/src/components/Entities/EntityDescription.tsx b/packages/zapp/console/src/components/Entities/EntityDescription.tsx index 646af3639..ecbec2db0 100644 --- a/packages/zapp/console/src/components/Entities/EntityDescription.tsx +++ b/packages/zapp/console/src/components/Entities/EntityDescription.tsx @@ -4,20 +4,80 @@ import classnames from 'classnames'; import { useCommonStyles } from 'components/common/styles'; import { WaitForData } from 'components/common/WaitForData'; import { useNamedEntity } from 'components/hooks/useNamedEntity'; -import { NamedEntityMetadata, ResourceIdentifier } from 'models/Common/types'; +import { NamedEntityMetadata, ResourceIdentifier, Variable } from 'models/Common/types'; import * as React from 'react'; import reactLoadingSkeleton from 'react-loading-skeleton'; -import { entityStrings } from './constants'; -import t from './strings'; +import { ReactJsonViewWrapper } from 'components/common/ReactJsonView'; +import { useEntityVersions } from 'components/hooks/Entity/useEntityVersions'; +import { executionSortFields } from 'models/Execution/constants'; +import { SortDirection } from 'models/AdminEntity/types'; +import { TaskClosure } from 'models/Task/types'; +import { executionFilterGenerator } from './generators'; +import { Row } from './Row'; +import t, { patternKey } from './strings'; +import { entityStrings, entitySections } from './constants'; const Skeleton = reactLoadingSkeleton; const useStyles = makeStyles((theme: Theme) => ({ + header: { + marginBottom: theme.spacing(1), + }, description: { marginTop: theme.spacing(1), }, + divider: { + borderBottom: `1px solid ${theme.palette.divider}`, + marginBottom: theme.spacing(1), + }, })); +const InputsAndOuputs: React.FC<{ + id: ResourceIdentifier; +}> = ({ id }) => { + const sort = { + key: executionSortFields.createdAt, + direction: SortDirection.DESCENDING, + }; + + const baseFilters = executionFilterGenerator[id.resourceType](id); + + // to render the input and output, + // need to fetch the latest version and get the input and ouptut data + const versions = useEntityVersions( + { ...id, version: '' }, + { + sort, + filter: baseFilters, + limit: 1, + }, + ); + + let inputs: Record | undefined; + let outputs: Record | undefined; + + if ((versions?.value?.[0]?.closure as TaskClosure)?.compiledTask?.template) { + const template = (versions?.value?.[0]?.closure as TaskClosure)?.compiledTask?.template; + inputs = template?.interface?.inputs?.variables; + outputs = template?.interface?.outputs?.variables; + } + + return ( + + {inputs && ( + + !field?.name} /> + + )} + {outputs && ( + + !field?.name} /> + + )} + + ); +}; + /** Fetches and renders the description for a given Entity (LaunchPlan,Workflow,Task) ID */ export const EntityDescription: React.FC<{ id: ResourceIdentifier; @@ -27,21 +87,29 @@ export const EntityDescription: React.FC<{ const namedEntity = useNamedEntity(id); const { metadata = {} as NamedEntityMetadata } = namedEntity.value; const hasDescription = !!metadata.description; + const sections = entitySections[id.resourceType]; + return ( <> - Description - + + {t('basicInformation')} + +
+ - - {hasDescription - ? metadata.description - : t('noDescription', entityStrings[id.resourceType])} - + + + {hasDescription + ? metadata.description + : t(patternKey('noDescription', entityStrings[id.resourceType]))} + + + {sections?.descriptionInputsAndOutputs && } ); diff --git a/packages/zapp/console/src/components/Entities/EntityDetailsHeader.tsx b/packages/zapp/console/src/components/Entities/EntityDetailsHeader.tsx index ce41b9ce6..c22b16291 100644 --- a/packages/zapp/console/src/components/Entities/EntityDetailsHeader.tsx +++ b/packages/zapp/console/src/components/Entities/EntityDetailsHeader.tsx @@ -8,11 +8,10 @@ import { Project } from 'models/Project/types'; import { getProjectDomain } from 'models/Project/utils'; import * as React from 'react'; import { Link } from 'react-router-dom'; -import { Routes } from 'routes/routes'; import { LaunchForm } from 'components/Launch/LaunchForm/LaunchForm'; -import { backUrlGenerator } from './generators'; +import { backUrlGenerator, backToDetailUrlGenerator } from './generators'; import { entityStrings } from './constants'; -import t from './strings'; +import t, { patternKey } from './strings'; const useStyles = makeStyles((theme: Theme) => ({ headerContainer: { @@ -77,7 +76,7 @@ export const EntityDetailsHeader: React.FC = ({ className={commonStyles.linkUnstyled} to={ backToWorkflow - ? Routes.WorkflowDetails.makeUrl(id.project, id.domain, id.name) + ? backToDetailUrlGenerator[id.resourceType](id) : backUrlGenerator[id.resourceType](id) } > @@ -93,7 +92,7 @@ export const EntityDetailsHeader: React.FC = ({ onClick={() => setShowLaunchForm(true)} variant="contained" > - {t('launchStrings', entityStrings[id.resourceType])} + {t(patternKey('launchStrings', entityStrings[id.resourceType]))} ) : null}
diff --git a/packages/zapp/console/src/components/Entities/EntityExecutions.tsx b/packages/zapp/console/src/components/Entities/EntityExecutions.tsx index b2b3780e8..da2e701b8 100644 --- a/packages/zapp/console/src/components/Entities/EntityExecutions.tsx +++ b/packages/zapp/console/src/components/Entities/EntityExecutions.tsx @@ -15,6 +15,8 @@ import { executionSortFields } from 'models/Execution/constants'; import { compact } from 'lodash'; import { useOnlyMyExecutionsFilterState } from 'components/Executions/filters/useOnlyMyExecutionsFilterState'; import { executionFilterGenerator } from './generators'; +import { entityStrings } from './constants'; +import t, { patternKey } from './strings'; const useStyles = makeStyles((theme: Theme) => ({ filtersContainer: { @@ -76,8 +78,8 @@ export const EntityExecutions: React.FC = ({ return ( <> - - All Executions in the Workflow + + {t(patternKey('allExecutionsChartTitle', entityStrings[id.resourceType]))}
= return ( ({ + header: { + marginBottom: theme.spacing(1), + }, schedulesContainer: { marginTop: theme.spacing(1), }, + divider: { + borderBottom: `1px solid ${theme.palette.divider}`, + marginBottom: theme.spacing(1), + }, })); const RenderSchedules: React.FC<{ @@ -45,13 +52,17 @@ export const EntitySchedules: React.FC<{ return ( <> - {t('schedulesHeader')} + + {t('schedulesHeader')} + +
+
{scheduledLaunchPlans.value.length > 0 ? ( ) : ( - {t('noSchedules', entityStrings[id.resourceType])} + {t(patternKey('noSchedules', entityStrings[id.resourceType]))} )}
diff --git a/packages/zapp/console/src/components/Entities/EntityVersions.tsx b/packages/zapp/console/src/components/Entities/EntityVersions.tsx index 64990f86a..4509f3090 100644 --- a/packages/zapp/console/src/components/Entities/EntityVersions.tsx +++ b/packages/zapp/console/src/components/Entities/EntityVersions.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { Routes } from 'routes/routes'; import { history } from 'routes/history'; import Typography from '@material-ui/core/Typography'; import { IconButton, makeStyles, Theme } from '@material-ui/core'; @@ -7,16 +6,16 @@ import ExpandLess from '@material-ui/icons/ExpandLess'; import ExpandMore from '@material-ui/icons/ExpandMore'; import { LocalCacheItem, useLocalCache } from 'basics/LocalCache'; import { WaitForData } from 'components/common/WaitForData'; -import { WorkflowVersionsTable } from 'components/Executions/Tables/WorkflowVersionsTable'; +import { EntityVersionsTable } from 'components/Executions/Tables/EntityVersionsTable'; import { isLoadingState } from 'components/hooks/fetchMachine'; -import { useWorkflowVersions } from 'components/hooks/useWorkflowVersions'; +import { useEntityVersions } from 'components/hooks/Entity/useEntityVersions'; import { interactiveTextColor } from 'components/Theme/constants'; import { SortDirection } from 'models/AdminEntity/types'; -import { ResourceIdentifier } from 'models/Common/types'; +import { Identifier, ResourceIdentifier } from 'models/Common/types'; import { executionSortFields } from 'models/Execution/constants'; -import { executionFilterGenerator } from './generators'; -import { WorkflowVersionsTablePageSize } from './constants'; -import t from './strings'; +import { executionFilterGenerator, versionDetailsUrlGenerator } from './generators'; +import { WorkflowVersionsTablePageSize, entityStrings } from './constants'; +import t, { patternKey } from './strings'; const useStyles = makeStyles((theme: Theme) => ({ headerContainer: { @@ -64,8 +63,10 @@ export const EntityVersions: React.FC = ({ id, showAll = fa [id, resourceType], ); - const versions = useWorkflowVersions( - { domain, project }, + // we are getting all the versions for this id + // so we don't want to specify which version + const versions = useEntityVersions( + { ...id, version: '' }, { sort, filter: baseFilters, @@ -76,12 +77,10 @@ export const EntityVersions: React.FC = ({ id, showAll = fa const preventDefault = (e) => e.preventDefault(); const handleViewAll = React.useCallback(() => { history.push( - Routes.WorkflowVersionDetails.makeUrl( - project, - domain, - name, - versions.value[0].id.version ?? '', - ), + versionDetailsUrlGenerator({ + ...id, + version: versions.value[0].id.version ?? '', + } as Identifier), ); }, [project, domain, name, versions]); @@ -102,8 +101,8 @@ export const EntityVersions: React.FC = ({ id, showAll = fa > {showTable ? : } - - {t('workflowVersionsTitle')} + + {t(patternKey('versionsTitle', entityStrings[id.resourceType]))} {t('viewAll')} @@ -112,10 +111,11 @@ export const EntityVersions: React.FC = ({ id, showAll = fa )} {showTable || showAll ? ( - ) : (
diff --git a/packages/zapp/console/src/components/Entities/Row.tsx b/packages/zapp/console/src/components/Entities/Row.tsx new file mode 100644 index 000000000..b6fd70c35 --- /dev/null +++ b/packages/zapp/console/src/components/Entities/Row.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; +import { Typography } from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import { COLOR_SPECTRUM } from 'components/Theme/colorSpectrum'; + +const useStyles = makeStyles((theme: Theme) => ({ + row: { + display: 'flex', + marginBottom: theme.spacing(1), + }, + title: { + width: 100, + color: COLOR_SPECTRUM.gray25.color, + }, +})); + +interface MyProps { + children?: React.ReactNode; + title: String; +} +export const Row: React.FC = (props) => { + const styles = useStyles(); + + return ( +
+
+ {props.title} +
+
{props.children}
+
+ ); +}; diff --git a/packages/zapp/console/src/components/Entities/VersionDetails/EntityVersionDetails.tsx b/packages/zapp/console/src/components/Entities/VersionDetails/EntityVersionDetails.tsx new file mode 100644 index 000000000..519b4e13b --- /dev/null +++ b/packages/zapp/console/src/components/Entities/VersionDetails/EntityVersionDetails.tsx @@ -0,0 +1,70 @@ +import * as React from 'react'; +import { Typography } from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import { contentMarginGridUnits } from 'common/layout'; +import { WaitForData } from 'components/common/WaitForData'; +import { useTaskTemplate } from 'components/hooks/useTask'; +import { ResourceIdentifier, Identifier } from 'models/Common/types'; +import { DumpJSON } from 'components/common/DumpJSON'; +import { Row } from '../Row'; +import EnvVarsTable from './EnvVarsTable'; +import t, { patternKey } from '../strings'; +import { entityStrings } from '../constants'; + +const useStyles = makeStyles((theme: Theme) => ({ + header: { + marginBottom: theme.spacing(1), + marginLeft: theme.spacing(contentMarginGridUnits), + }, + table: { + marginLeft: theme.spacing(contentMarginGridUnits), + }, + divider: { + borderBottom: `1px solid ${theme.palette.divider}`, + marginBottom: theme.spacing(1), + }, +})); + +export interface EntityExecutionsProps { + id: ResourceIdentifier; +} + +/** The tab/page content for viewing a workflow's executions */ +export const EntityVersionDetails: React.FC = ({ id }) => { + const styles = useStyles(); + + // NOTE: need to be generic for supporting other type like workflow, etc. + const templateState = useTaskTemplate(id as Identifier); + + const template = templateState?.value?.closure?.compiledTask?.template; + const envVars = template?.container?.env; + const image = template?.container?.image; + + return ( + <> + + {t(patternKey('details', entityStrings[id.resourceType]))} + +
+ +
+ {image && ( + + {image} + + )} + {envVars && ( + + + + )} + {template && ( + + + + )} +
+
+ + ); +}; diff --git a/packages/zapp/console/src/components/Entities/VersionDetails/EntityVersionDetailsContainer.tsx b/packages/zapp/console/src/components/Entities/VersionDetails/EntityVersionDetailsContainer.tsx new file mode 100644 index 000000000..931edeb09 --- /dev/null +++ b/packages/zapp/console/src/components/Entities/VersionDetails/EntityVersionDetailsContainer.tsx @@ -0,0 +1,115 @@ +import * as React from 'react'; +import { withRouteParams } from 'components/common/withRouteParams'; +import { ResourceIdentifier } from 'models/Common/types'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import { WaitForData } from 'components/common/WaitForData'; +import { useProject } from 'components/hooks/useProjects'; +import { StaticGraphContainer } from 'components/Workflow/StaticGraphContainer'; +import { WorkflowId } from 'models/Workflow/types'; +import { entitySections } from 'components/Entities/constants'; +import { EntityDetailsHeader } from 'components/Entities/EntityDetailsHeader'; +import { EntityVersions } from 'components/Entities/EntityVersions'; +import { typeNameToEntityResource } from '../constants'; +import { versionsDetailsSections } from './constants'; +import { EntityVersionDetails } from './EntityVersionDetails'; + +const useStyles = makeStyles((theme: Theme) => ({ + verionDetailsContainer: { + marginTop: theme.spacing(2), + display: 'flex', + flexDirection: 'column', + flexWrap: 'nowrap', + overflow: 'hidden', + height: `calc(100vh - ${theme.spacing(17)}px)`, + }, + staticGraphContainer: { + display: 'flex', + height: '60%', + width: '100%', + flex: '1', + }, + versionDetailsContainer: { + display: 'flex', + flexDirection: 'column', + height: '55%', + width: '100%', + flex: '1', + overflowY: 'scroll', + }, + versionsContainer: { + display: 'flex', + flex: '0 1 auto', + height: '40%', + flexDirection: 'column', + overflowY: 'scroll', + }, +})); + +interface WorkflowVersionDetailsRouteParams { + projectId: string; + domainId: string; + entityType: string; + entityName: string; + entityVersion: string; +} + +/** + * The view component for the Workflow Versions page + * @param projectId + * @param domainId + * @param workflowName + */ +const EntityVersionsDetailsContainerImpl: React.FC = ({ + projectId, + domainId, + entityType, + entityName, + entityVersion, +}) => { + const workflowId = React.useMemo( + () => ({ + resourceType: typeNameToEntityResource[entityType], + project: projectId, + domain: domainId, + name: entityName, + version: entityVersion, + }), + [entityType, projectId, domainId, entityName, entityVersion], + ); + + const id = workflowId as ResourceIdentifier; + const sections = entitySections[id.resourceType]; + const versionsSections = versionsDetailsSections[id.resourceType]; + const project = useProject(workflowId.project); + const styles = useStyles(); + + return ( + + +
+ {versionsSections.details && ( +
+ +
+ )} + {versionsSections.graph && ( +
+ +
+ )} +
+ +
+
+
+ ); +}; + +export const EntityVersionsDetailsContainer = withRouteParams( + EntityVersionsDetailsContainerImpl, +); diff --git a/packages/zapp/console/src/components/Entities/VersionDetails/EnvVarsTable.tsx b/packages/zapp/console/src/components/Entities/VersionDetails/EnvVarsTable.tsx new file mode 100644 index 000000000..17efa7015 --- /dev/null +++ b/packages/zapp/console/src/components/Entities/VersionDetails/EnvVarsTable.tsx @@ -0,0 +1,71 @@ +import * as React from 'react'; +import { + Typography, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, +} from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import { Core } from 'flyteidl'; +import { COLOR_SPECTRUM } from 'components/Theme/colorSpectrum'; +import t from '../strings'; + +const useStyles = makeStyles((theme: Theme) => ({ + container: { + marginBottom: theme.spacing(1), + ['& .MuiTableCell-sizeSmall']: { + paddingLeft: 0, + }, + }, + headerText: { + color: COLOR_SPECTRUM.gray25.color, + }, +})); + +interface EnvVarsTableProps { + rows: Core.IKeyValuePair[]; +} + +export default function EnvVarsTable({ rows }: EnvVarsTableProps) { + const styles = useStyles(); + + if (!rows || rows.length == 0) { + return {t('empty')}; + } + return ( + + + + + + + {t('key')} + + + + + {t('value')} + + + + + + {rows.map((row) => ( + + + {row.key} + + + {row.value} + + + ))} + +
+
+ ); +} diff --git a/packages/zapp/console/src/components/Entities/VersionDetails/VersionDetailsLink.tsx b/packages/zapp/console/src/components/Entities/VersionDetails/VersionDetailsLink.tsx new file mode 100644 index 000000000..480324eba --- /dev/null +++ b/packages/zapp/console/src/components/Entities/VersionDetails/VersionDetailsLink.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import { Identifier } from 'models/Common/types'; +import { NewTargetLink } from 'components/common/NewTargetLink'; +import { versionDetailsUrlGenerator } from 'components/Entities/generators'; +import t from '../strings'; + +const useStyles = makeStyles((theme: Theme) => ({ + link: { + marginBottom: theme.spacing(2), + }, +})); + +interface TaskVersionDetailsLinkProps { + id: Identifier; +} + +export const TaskVersionDetailsLink: React.FC = ({ id }) => { + const styles = useStyles(); + return ( + + {t('details_task')} + + ); +}; diff --git a/packages/zapp/console/src/components/Entities/VersionDetails/constants.ts b/packages/zapp/console/src/components/Entities/VersionDetails/constants.ts new file mode 100644 index 000000000..ad09fb03a --- /dev/null +++ b/packages/zapp/console/src/components/Entities/VersionDetails/constants.ts @@ -0,0 +1,29 @@ +import { ResourceType } from 'models/Common/types'; + +interface VersionsDetailsSectionsFlags { + details: boolean; + graph: boolean; +} + +export const versionsDetailsSections: { [k in ResourceType]: VersionsDetailsSectionsFlags } = { + [ResourceType.DATASET]: { + details: false, + graph: false, + }, + [ResourceType.LAUNCH_PLAN]: { + details: false, + graph: false, + }, + [ResourceType.TASK]: { + details: true, + graph: false, + }, + [ResourceType.UNSPECIFIED]: { + details: false, + graph: false, + }, + [ResourceType.WORKFLOW]: { + details: false, + graph: true, + }, +}; diff --git a/packages/zapp/console/src/components/Entities/constants.ts b/packages/zapp/console/src/components/Entities/constants.ts index 06adada8f..efef36a63 100644 --- a/packages/zapp/console/src/components/Entities/constants.ts +++ b/packages/zapp/console/src/components/Entities/constants.ts @@ -10,12 +10,23 @@ export const entityStrings: EntityStringMap = { [ResourceType.WORKFLOW]: 'workflow', }; +type TypeNameToEntityResourceType = { [key: string]: ResourceType }; + +export const typeNameToEntityResource: TypeNameToEntityResourceType = { + ['dataset']: ResourceType.DATASET, + ['launch plan']: ResourceType.LAUNCH_PLAN, + ['task']: ResourceType.TASK, + ['item']: ResourceType.UNSPECIFIED, + ['workflow']: ResourceType.WORKFLOW, +}; + interface EntitySectionsFlags { description?: boolean; executions?: boolean; launch?: boolean; schedules?: boolean; versions?: boolean; + descriptionInputsAndOutputs?: boolean; } export const entitySections: { [k in ResourceType]: EntitySectionsFlags } = { @@ -26,7 +37,13 @@ export const entitySections: { [k in ResourceType]: EntitySectionsFlags } = { launch: true, schedules: true, }, - [ResourceType.TASK]: { description: true, executions: true, launch: true }, + [ResourceType.TASK]: { + description: true, + executions: true, + launch: true, + versions: true, + descriptionInputsAndOutputs: true, + }, [ResourceType.UNSPECIFIED]: { description: true }, [ResourceType.WORKFLOW]: { description: true, diff --git a/packages/zapp/console/src/components/Entities/generators.ts b/packages/zapp/console/src/components/Entities/generators.ts index 0cc7235e0..f10c41fee 100644 --- a/packages/zapp/console/src/components/Entities/generators.ts +++ b/packages/zapp/console/src/components/Entities/generators.ts @@ -1,6 +1,7 @@ import { FilterOperation, FilterOperationName } from 'models/AdminEntity/types'; -import { ResourceIdentifier, ResourceType } from 'models/Common/types'; +import { ResourceIdentifier, ResourceType, Identifier } from 'models/Common/types'; import { Routes } from 'routes/routes'; +import { entityStrings } from './constants'; const noFilters = () => []; @@ -30,13 +31,66 @@ const workflowListGenerator = ({ project, domain }: ResourceIdentifier) => Routes.ProjectDetails.sections.workflows.makeUrl(project, domain); const taskListGenerator = ({ project, domain }: ResourceIdentifier) => Routes.ProjectDetails.sections.tasks.makeUrl(project, domain); +const unspecifiedGenerator = ({ project, domain }: ResourceIdentifier | Identifier) => { + throw new Error('Unspecified Resourcetype.'); +}; +const unimplementedGenerator = ({ project, domain }: ResourceIdentifier | Identifier) => { + throw new Error('Method not implemented.'); +}; export const backUrlGenerator: { [k in ResourceType]: (id: ResourceIdentifier) => string; } = { - [ResourceType.DATASET]: workflowListGenerator, - [ResourceType.LAUNCH_PLAN]: workflowListGenerator, + [ResourceType.DATASET]: unimplementedGenerator, + [ResourceType.LAUNCH_PLAN]: unimplementedGenerator, [ResourceType.TASK]: taskListGenerator, - [ResourceType.UNSPECIFIED]: workflowListGenerator, + [ResourceType.UNSPECIFIED]: unspecifiedGenerator, [ResourceType.WORKFLOW]: workflowListGenerator, }; + +const workflowDetailGenerator = ({ project, domain, name }: ResourceIdentifier) => + Routes.WorkflowDetails.makeUrl(project, domain, name); +const taskDetailGenerator = ({ project, domain, name }: ResourceIdentifier) => + Routes.TaskDetails.makeUrl(project, domain, name); + +export const backToDetailUrlGenerator: { + [k in ResourceType]: (id: ResourceIdentifier) => string; +} = { + [ResourceType.DATASET]: unimplementedGenerator, + [ResourceType.LAUNCH_PLAN]: unimplementedGenerator, + [ResourceType.TASK]: taskDetailGenerator, + [ResourceType.UNSPECIFIED]: unspecifiedGenerator, + [ResourceType.WORKFLOW]: workflowDetailGenerator, +}; + +const workflowVersopmDetailsGenerator = ({ project, domain, name, version }: Identifier) => + Routes.EntityVersionDetails.makeUrl( + project, + domain, + name, + entityStrings[ResourceType.WORKFLOW], + version, + ); +const taskVersionDetailsGenerator = ({ project, domain, name, version }: Identifier) => + Routes.EntityVersionDetails.makeUrl( + project, + domain, + name, + entityStrings[ResourceType.TASK], + version, + ); + +const entityMapVersionDetailsUrl: { + [k in ResourceType]: (id: Identifier) => string; +} = { + [ResourceType.DATASET]: unimplementedGenerator, + [ResourceType.LAUNCH_PLAN]: unimplementedGenerator, + [ResourceType.TASK]: taskVersionDetailsGenerator, + [ResourceType.UNSPECIFIED]: unspecifiedGenerator, + [ResourceType.WORKFLOW]: workflowVersopmDetailsGenerator, +}; + +export const versionDetailsUrlGenerator = (id: Identifier): string => { + if (id?.resourceType) return entityMapVersionDetailsUrl[id?.resourceType](id); + return ''; +}; diff --git a/packages/zapp/console/src/components/Entities/strings.ts b/packages/zapp/console/src/components/Entities/strings.ts index 9c44f0f79..e12b28fd3 100644 --- a/packages/zapp/console/src/components/Entities/strings.ts +++ b/packages/zapp/console/src/components/Entities/strings.ts @@ -1,15 +1,30 @@ import { createLocalizedString } from '@flyteconsole/locale'; -import { startCase } from 'lodash'; const str = { - allExecutionsChartTitle: 'All Executions in the Workflow', - workflowVersionsTitle: 'Recent Workflow Versions', viewAll: 'View All', schedulesHeader: 'Schedules', collapseButton: (showAll: boolean) => (showAll ? 'Collapse' : 'Expand'), - launchStrings: (typeString: string) => `Launch ${startCase(typeString)}`, - noDescription: (typeString: string) => `This ${typeString} has no description.`, - noSchedules: (typeString: string) => `This ${typeString} has no schedules.`, + launchStrings_workflow: 'Launch Workflow', + launchStrings_task: 'Launch Task', + noDescription_workflow: 'This workflow has no description.', + noDescription_task: 'This task has no description.', + noSchedules_workflow: 'This workflow has no schedules.', + noSchedules_task: 'This task has no schedules.', + allExecutionsChartTitle_workflow: 'All Executions in the Workflow', + allExecutionsChartTitle_task: 'All Execuations in the Task', + versionsTitle_workflow: 'Recent Workflow Versions', + versionsTitle_task: 'Recent Task Versions', + details_task: 'Task Details', + inputsFieldName: 'Inputs', + outputsFieldName: 'Outputs', + imageFieldName: 'Image', + envVarsFieldName: 'Env Vars', + commandsFieldName: 'Commands', + empty: 'Empty', + key: 'Key', + value: 'Value', + basicInformation: 'Basic Information', + description: 'Description', }; export { patternKey } from '@flyteconsole/locale'; diff --git a/packages/zapp/console/src/components/Entities/test/EntityDetails.test.tsx b/packages/zapp/console/src/components/Entities/test/EntityDetails.test.tsx new file mode 100644 index 000000000..179c1d747 --- /dev/null +++ b/packages/zapp/console/src/components/Entities/test/EntityDetails.test.tsx @@ -0,0 +1,72 @@ +import { render, waitFor, screen } from '@testing-library/react'; +import { ResourceIdentifier } from 'models/Common/types'; +import * as React from 'react'; +import { createMockTask } from 'models/__mocks__/taskData'; +import { createMockWorkflow } from 'models/__mocks__/workflowData'; +import { Task } from 'models/Task/types'; +import { Workflow } from 'models/Workflow/types'; +import { projects } from 'mocks/data/projects'; +import * as projectApi from 'models/Project/api'; +import { MemoryRouter } from 'react-router'; +import { EntityDetails } from '../EntityDetails'; + +jest.mock('models/Project/api'); + +describe('EntityDetails', () => { + let mockWorkflow: Workflow; + let mockTask: Task; + + // mock api for listProjects + const mockListProjects = jest.spyOn(projectApi, 'listProjects'); + mockListProjects.mockResolvedValue([projects['flyteTest']]); + + const createMocks = () => { + mockWorkflow = createMockWorkflow('MyWorkflow'); + mockTask = createMockTask('MyTask'); + }; + + const renderDetails = (id: ResourceIdentifier) => { + return render( + + + , + ); + }; + + beforeEach(() => { + createMocks(); + }); + + const checkTextInDetailPage = async ( + id: ResourceIdentifier, + versionsString: string, + executionsString: string, + ) => { + // check text for header + await waitFor(() => { + expect(screen.getByText(`${id.domain} / ${id.name}`)).toBeInTheDocument(); + }); + + // check text for versions + await waitFor(() => { + expect(screen.getByText(versionsString)).toBeInTheDocument(); + }); + + // check text for executions + await waitFor(() => { + expect(screen.getByText(executionsString)).toBeInTheDocument(); + }); + }; + + it('renders Task Details Page', async () => { + const id: ResourceIdentifier = mockTask.id as ResourceIdentifier; + renderDetails(id); + checkTextInDetailPage(id, 'Recent Task Versions', 'All Executions in the Task'); + }); + + it('renders Workflow Details Page', async () => { + const id: ResourceIdentifier = mockWorkflow.id as ResourceIdentifier; + renderDetails(id); + checkTextInDetailPage(id, 'Recent Workflow Versions', 'All Executions in the Workflow'); + }); +}); diff --git a/packages/zapp/console/src/components/Entities/test/EntityVersionDetails.test.tsx b/packages/zapp/console/src/components/Entities/test/EntityVersionDetails.test.tsx new file mode 100644 index 000000000..147a002cf --- /dev/null +++ b/packages/zapp/console/src/components/Entities/test/EntityVersionDetails.test.tsx @@ -0,0 +1,69 @@ +import { render, waitFor, screen } from '@testing-library/react'; +import { ThemeProvider } from '@material-ui/styles'; +import { muiTheme } from 'components/Theme/muiTheme'; +import { ResourceIdentifier } from 'models/Common/types'; +import * as React from 'react'; +import { createMockTask } from 'models/__mocks__/taskData'; +import { Task } from 'models/Task/types'; +import { getTask } from 'models/Task/api'; +import { APIContext } from 'components/data/apiContext'; +import { mockAPIContextValue } from 'components/data/__mocks__/apiContext'; +import { EntityVersionDetails } from '../VersionDetails/EntityVersionDetails'; + +describe('EntityVersionDetails', () => { + let mockTask: Task; + let mockGetTask: jest.Mock>; + + const createMocks = () => { + mockTask = createMockTask('MyTask'); + mockGetTask = jest.fn().mockImplementation(() => Promise.resolve(mockTask)); + }; + + const renderDetails = (id: ResourceIdentifier) => { + return render( + + + + + , + ); + }; + + describe('Task Version Details', () => { + beforeEach(() => { + createMocks(); + }); + + it('renders and checks text', async () => { + const id: ResourceIdentifier = mockTask.id as ResourceIdentifier; + renderDetails(id); + + // check text for Task Details + await waitFor(() => { + expect(screen.getByText('Task Details')).toBeInTheDocument(); + }); + + // check text for image + await waitFor(() => { + expect( + screen.getByText(mockTask.closure.compiledTask.template?.container?.image || ''), + ).toBeInTheDocument(); + }); + + // check for env vars + if (mockTask.closure.compiledTask.template?.container?.env) { + const envVars = mockTask.closure.compiledTask.template?.container?.env; + for (let i = 0; i < envVars.length; i++) { + await waitFor(() => { + expect(screen.getByText(envVars[i].key || '')).toBeInTheDocument(); + expect(screen.getByText(envVars[i].value || '')).toBeInTheDocument(); + }); + } + } + }); + }); +}); diff --git a/packages/zapp/console/src/components/Entities/test/TaskVersionDetailsLink.test.tsx b/packages/zapp/console/src/components/Entities/test/TaskVersionDetailsLink.test.tsx new file mode 100644 index 000000000..19c89cc46 --- /dev/null +++ b/packages/zapp/console/src/components/Entities/test/TaskVersionDetailsLink.test.tsx @@ -0,0 +1,43 @@ +import { render, waitFor, screen } from '@testing-library/react'; +import * as React from 'react'; +import { createMockTask } from 'models/__mocks__/taskData'; +import { Task } from 'models/Task/types'; +import { Identifier } from 'models/Common/types'; +import { versionDetailsUrlGenerator } from 'components/Entities/generators'; +import { TaskVersionDetailsLink } from '../VersionDetails/VersionDetailsLink'; + +describe('TaskVersionDetailsLink', () => { + let mockTask: Task; + + const createMocks = () => { + mockTask = createMockTask('MyTask'); + }; + + const renderLink = (id: Identifier) => { + return render(); + }; + + beforeEach(() => { + createMocks(); + }); + + it('renders and checks text', async () => { + const id: Identifier = mockTask.id; + renderLink(id); + await waitFor(() => { + expect(screen.getByText('Task Details')).toBeInTheDocument(); + }); + }); + + it('renders and checks containing icon', () => { + const id: Identifier = mockTask.id; + const { container } = renderLink(id); + expect(container.querySelector('svg')).not.toBeNull(); + }); + + it('renders and checks url', () => { + const id: Identifier = mockTask.id; + const { container } = renderLink(id); + expect(container.firstElementChild).toHaveAttribute('href', versionDetailsUrlGenerator(id)); + }); +}); diff --git a/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionDetailsPanelContent.tsx b/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionDetailsPanelContent.tsx index 09ad0f06f..8a11e802c 100644 --- a/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionDetailsPanelContent.tsx +++ b/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionDetailsPanelContent.tsx @@ -26,6 +26,8 @@ import { DumpJSON } from 'components/common/DumpJSON'; import { dNode } from 'models/Graph/types'; import { NodeExecutionPhase, TaskExecutionPhase } from 'models/Execution/enums'; import { transformWorkflowToKeyedDag, getNodeNameFromDag } from 'components/WorkflowGraph/utils'; +import { TaskVersionDetailsLink } from 'components/Entities/VersionDetails/VersionDetailsLink'; +import { Identifier } from 'models/Common/types'; import { NodeExecutionCacheStatus } from '../NodeExecutionCacheStatus'; import { makeListTaskExecutionsQuery, makeNodeExecutionQuery } from '../nodeExecutionQueries'; import { NodeExecutionDetails } from '../types'; @@ -186,7 +188,6 @@ const WorkflowTabs: React.FC<{ let tabContent: JSX.Element | null = null; const id = nodeId.slice(nodeId.lastIndexOf('-') + 1); const taskTemplate = dagData[id]?.value.template; - switch (tabState.value) { case tabIds.inputs: { tabContent = taskTemplate ? ( @@ -199,6 +200,7 @@ const WorkflowTabs: React.FC<{ case tabIds.task: { tabContent = taskTemplate ? ( + ) : null; diff --git a/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionTabs/index.tsx b/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionTabs/index.tsx index ec1761afc..0fceb1331 100644 --- a/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionTabs/index.tsx +++ b/packages/zapp/console/src/components/Executions/ExecutionDetails/NodeExecutionTabs/index.tsx @@ -8,6 +8,8 @@ import { PanelSection } from 'components/common/PanelSection'; import { DumpJSON } from 'components/common/DumpJSON'; import { isMapTaskType } from 'models/Task/utils'; import { TaskExecutionPhase } from 'models/Execution/enums'; +import { TaskVersionDetailsLink } from 'components/Entities/VersionDetails/VersionDetailsLink'; +import { Identifier } from 'models/Common/types'; import { TaskExecutionsList } from '../../TaskExecutionsList/TaskExecutionsList'; import { NodeExecutionInputs } from './NodeExecutionInputs'; import { NodeExecutionOutputs } from './NodeExecutionOutputs'; @@ -72,6 +74,7 @@ export const NodeExecutionTabs: React.FC<{ case tabIds.task: { tabContent = taskTemplate ? ( + ) : null; diff --git a/packages/zapp/console/src/components/Executions/Tables/WorkflowVersionsTable.tsx b/packages/zapp/console/src/components/Executions/Tables/EntityVersionsTable.tsx similarity index 59% rename from packages/zapp/console/src/components/Executions/Tables/WorkflowVersionsTable.tsx rename to packages/zapp/console/src/components/Executions/Tables/EntityVersionsTable.tsx index cfb1cc20d..64e96baff 100644 --- a/packages/zapp/console/src/components/Executions/Tables/WorkflowVersionsTable.tsx +++ b/packages/zapp/console/src/components/Executions/Tables/EntityVersionsTable.tsx @@ -1,25 +1,27 @@ import classnames from 'classnames'; -import { noWorkflowVersionsFoundString } from 'common/constants'; +import { noVersionsFoundString } from 'common/constants'; import { useCommonStyles } from 'components/common/styles'; import { ListProps } from 'components/common/types'; import PaginatedDataList from 'components/Tables/PaginatedDataList'; import { Workflow } from 'models/Workflow/types'; -import { Identifier } from 'models/Common/types'; +import { Identifier, ResourceType } from 'models/Common/types'; import * as React from 'react'; import { useParams } from 'react-router'; import { history } from 'routes/history'; import { Routes } from 'routes/routes'; +import { entityStrings } from 'components/Entities/constants'; import { useExecutionTableStyles } from './styles'; import { useWorkflowExecutionsTableState } from './useWorkflowExecutionTableState'; import { useWorkflowVersionsTableColumns } from './useWorkflowVersionsTableColumns'; import { WorkflowVersionRow } from './WorkflowVersionRow'; -interface WorkflowVersionsTableProps extends ListProps { +interface EntityVersionsTableProps extends ListProps { versionView?: boolean; + resourceType: ResourceType; } -interface WorkflowVersionRouteParams { - workflowVersion: string; +interface EntityVersionRouteParams { + entityVersion: string; } /** @@ -27,21 +29,27 @@ interface WorkflowVersionRouteParams { * @param props * @constructor */ -export const WorkflowVersionsTable: React.FC = (props) => { - const { value: workflows, versionView } = props; +export const EntityVersionsTable: React.FC = (props) => { + const { value: versions, versionView, resourceType } = props; const state = useWorkflowExecutionsTableState(); const commonStyles = useCommonStyles(); const tableStyles = useExecutionTableStyles(); - const { workflowVersion } = useParams(); + const { entityVersion } = useParams(); const columns = useWorkflowVersionsTableColumns(); - const retry = () => props.fetch(); - const handleClickRow = React.useCallback( - ({ project, name, domain, version }: Identifier) => + ({ project, name, domain, version, resourceType = ResourceType.UNSPECIFIED }: Identifier) => () => { - history.push(Routes.WorkflowVersionDetails.makeUrl(project, domain, name, version)); + history.push( + Routes.EntityVersionDetails.makeUrl( + project, + domain, + name, + entityStrings[resourceType], + version, + ), + ); }, [], ); @@ -52,8 +60,8 @@ export const WorkflowVersionsTable: React.FC = (prop workflow={row} state={state} versionView={versionView} - onClick={versionView ? handleClickRow(row.id) : undefined} - isChecked={workflowVersion === row.id.version} + onClick={handleClickRow({ ...row.id, resourceType })} + isChecked={entityVersion === row.id.version} key={`workflow-version-row-${row.id.version}`} /> ); @@ -62,11 +70,11 @@ export const WorkflowVersionsTable: React.FC = (prop
diff --git a/packages/zapp/console/src/components/Theme/muiTheme.ts b/packages/zapp/console/src/components/Theme/muiTheme.ts index f959163dd..44ab78f9b 100644 --- a/packages/zapp/console/src/components/Theme/muiTheme.ts +++ b/packages/zapp/console/src/components/Theme/muiTheme.ts @@ -71,9 +71,14 @@ const theme = createMuiTheme({ fontFamily: bodyFontFamily, }, h3: { - fontSize: '1.25rem', + fontSize: '16px', fontWeight: 'bold', - lineHeight: 1.35, + lineHeight: '22px', + }, + h4: { + fontSize: '14px', + fontWeight: 'bold', + lineHeight: '20px', }, h6: { fontSize: '.875rem', diff --git a/packages/zapp/console/src/components/common/BarChart.tsx b/packages/zapp/console/src/components/common/BarChart.tsx index 6e6768af5..380e333a3 100644 --- a/packages/zapp/console/src/components/common/BarChart.tsx +++ b/packages/zapp/console/src/components/common/BarChart.tsx @@ -146,7 +146,7 @@ export const BarChart: React.FC = ({ return (
- + {title}
diff --git a/packages/zapp/console/src/components/common/DumpJSON.tsx b/packages/zapp/console/src/components/common/DumpJSON.tsx index 57349eefb..9fc0676ef 100644 --- a/packages/zapp/console/src/components/common/DumpJSON.tsx +++ b/packages/zapp/console/src/components/common/DumpJSON.tsx @@ -2,7 +2,5 @@ import * as React from 'react'; import { ReactJsonViewWrapper } from 'components/common/ReactJsonView'; export const DumpJSON: React.FC<{ value: any }> = ({ value }) => { - return ( - - ); + return ; }; diff --git a/packages/zapp/console/src/components/common/NewTargetLink.tsx b/packages/zapp/console/src/components/common/NewTargetLink.tsx index 176a7f2db..df2cbfe1a 100644 --- a/packages/zapp/console/src/components/common/NewTargetLink.tsx +++ b/packages/zapp/console/src/components/common/NewTargetLink.tsx @@ -27,22 +27,21 @@ export const NewTargetLink: React.FC = (props) => { const commonStyles = useCommonStyles(); const styles = useStyles(); - const link = ( + const icon = external ? : null; + + return ( - {children} + {inline ? ( + + {children} + {icon} + + ) : ( +
+ {children} + {icon} +
+ )} ); - - const icon = external ? : null; - return inline ? ( - - {link} - {icon} - - ) : ( -
- {link} - {icon} -
- ); }; diff --git a/packages/zapp/console/src/components/common/ReactJsonView.tsx b/packages/zapp/console/src/components/common/ReactJsonView.tsx index ea7e9d1a1..c90618ab0 100644 --- a/packages/zapp/console/src/components/common/ReactJsonView.tsx +++ b/packages/zapp/console/src/components/common/ReactJsonView.tsx @@ -32,6 +32,9 @@ const useStyles = makeStyles((theme: Theme) => ({ '& .object-key': { color: `${theme.palette.grey[500]} !important`, }, + '& .node-ellipsis': { + color: `${theme.palette.grey[500]} !important`, + }, }, })); diff --git a/packages/zapp/console/src/components/common/test/NewTargetLink.spec.tsx b/packages/zapp/console/src/components/common/test/NewTargetLink.spec.tsx index 319200494..ca4a1fbf6 100644 --- a/packages/zapp/console/src/components/common/test/NewTargetLink.spec.tsx +++ b/packages/zapp/console/src/components/common/test/NewTargetLink.spec.tsx @@ -14,9 +14,8 @@ const renderExternalLink = () => ); test('renders a blank target link', () => { - const { getByText } = renderLink(); - const anchor = getByText(linkText); - expect(anchor).toHaveAttribute('target', '_blank'); + const { container } = renderLink(); + expect(container.firstElementChild).toHaveAttribute('target', '_blank'); }); test('renders with additional icon for external links', () => { diff --git a/packages/zapp/console/src/components/hooks/Entity/constants.ts b/packages/zapp/console/src/components/hooks/Entity/constants.ts new file mode 100644 index 000000000..6086866a3 --- /dev/null +++ b/packages/zapp/console/src/components/hooks/Entity/constants.ts @@ -0,0 +1,41 @@ +import { ResourceType } from 'models/Common/types'; +import { listTasks } from 'models/Task/api'; +import { listWorkflows } from 'models/Workflow/api'; +import { listLaunchPlans } from 'models/Launch/api'; +import { Workflow } from 'models/Workflow/types'; +import { Task } from 'models/Task/types'; +import { LaunchPlan } from 'models/Launch/types'; + +interface EntityFunctions { + description?: boolean; + executions?: boolean; + launch?: boolean; + listEntity?: any; +} + +export type EntityType = Workflow | Task | LaunchPlan; + +const unspecifiedFn = () => { + throw new Error('Unspecified Resourcetype.'); +}; +const unimplementedFn = () => { + throw new Error('Method not implemented.'); +}; + +export const entityFunctions: { [k in ResourceType]: EntityFunctions } = { + [ResourceType.DATASET]: { + listEntity: unimplementedFn, + }, + [ResourceType.LAUNCH_PLAN]: { + listEntity: listLaunchPlans, + }, + [ResourceType.TASK]: { + listEntity: listTasks, + }, + [ResourceType.UNSPECIFIED]: { + listEntity: unspecifiedFn, + }, + [ResourceType.WORKFLOW]: { + listEntity: listWorkflows, + }, +}; diff --git a/packages/zapp/console/src/components/hooks/Entity/useEntityVersions.ts b/packages/zapp/console/src/components/hooks/Entity/useEntityVersions.ts new file mode 100644 index 000000000..df2eb9ee3 --- /dev/null +++ b/packages/zapp/console/src/components/hooks/Entity/useEntityVersions.ts @@ -0,0 +1,20 @@ +import { IdentifierScope, Identifier, ResourceIdentifier } from 'models/Common/types'; +import { RequestConfig } from 'models/AdminEntity/types'; +import { entityStrings } from 'components/Entities/constants'; +import { usePagination } from '../usePagination'; +import { EntityType, entityFunctions } from './constants'; + +/** + * A hook for fetching a paginated list of entity versions. + * @param scope + * @param config + */ +export function useEntityVersions(scope: IdentifierScope, config: RequestConfig) { + const id = scope as ResourceIdentifier; + const listEntity = entityFunctions[id.resourceType]?.listEntity; + + return usePagination( + { ...config, cacheItems: true, fetchArg: scope }, + listEntity, + ); +} diff --git a/packages/zapp/console/src/components/hooks/useTask.ts b/packages/zapp/console/src/components/hooks/useTask.ts index 022cbf076..d602ad29c 100644 --- a/packages/zapp/console/src/components/hooks/useTask.ts +++ b/packages/zapp/console/src/components/hooks/useTask.ts @@ -18,7 +18,7 @@ export function useTaskTemplate(id: Identifier): FetchableData { useCache: true, debugName: 'TaskTemplate', defaultValue: {} as TaskTemplate, - doFetch: async (taskId) => (await getTask(taskId)).closure.compiledTask.template, + doFetch: async (taskId) => (await getTask(taskId)) as TaskTemplate, }, id, ); diff --git a/packages/zapp/console/src/components/hooks/useWorkflowVersions.ts b/packages/zapp/console/src/components/hooks/useWorkflowVersions.ts deleted file mode 100644 index a356ee2b0..000000000 --- a/packages/zapp/console/src/components/hooks/useWorkflowVersions.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { IdentifierScope } from 'models/Common/types'; -import { RequestConfig } from 'models/AdminEntity/types'; -import { listWorkflows } from 'models/Workflow/api'; -import { Workflow } from 'models/Workflow/types'; -import { usePagination } from './usePagination'; - -/** - * A hook for fetching a paginated list of workflow versions. - * @param scope - * @param config - */ -export function useWorkflowVersions(scope: IdentifierScope, config: RequestConfig) { - return usePagination( - { ...config, cacheItems: true, fetchArg: scope }, - listWorkflows, - ); -} diff --git a/packages/zapp/console/src/models/Task/types.ts b/packages/zapp/console/src/models/Task/types.ts index bfccb67d0..e4d53af75 100644 --- a/packages/zapp/console/src/models/Task/types.ts +++ b/packages/zapp/console/src/models/Task/types.ts @@ -26,6 +26,7 @@ export interface TaskTemplate extends Core.ITaskTemplate { id: Identifier; interface?: TypedInterface; metadata?: TaskMetadata; + closure?: TaskClosure; type: string; } diff --git a/packages/zapp/console/src/models/__mocks__/taskData.ts b/packages/zapp/console/src/models/__mocks__/taskData.ts index 2f4d1e02c..e044f9a66 100644 --- a/packages/zapp/console/src/models/__mocks__/taskData.ts +++ b/packages/zapp/console/src/models/__mocks__/taskData.ts @@ -1,8 +1,9 @@ import { getCacheKey } from 'components/Cache/utils'; import { Admin } from 'flyteidl'; import { cloneDeep } from 'lodash'; -import { Identifier } from 'models/Common/types'; +import { Identifier, ResourceType } from 'models/Common/types'; import { Task, TaskClosure } from 'models/Task/types'; +import { testDomain, testProject } from 'mocks/data/constants'; import * as simpleClosure from './simpleTaskClosure.json'; const decodedClosure = Admin.TaskClosure.create( @@ -12,8 +13,9 @@ const decodedClosure = Admin.TaskClosure.create( const taskId: (name: string, version: string) => Identifier = (name, version) => ({ name, version, - project: 'flyte', - domain: 'development', + project: testProject, + domain: testDomain, + resourceType: ResourceType.TASK, }); export const createMockTask: (name: string, version?: string) => Task = ( diff --git a/packages/zapp/console/src/models/__mocks__/workflowData.ts b/packages/zapp/console/src/models/__mocks__/workflowData.ts index 6f09c6b38..a7d5ad264 100644 --- a/packages/zapp/console/src/models/__mocks__/workflowData.ts +++ b/packages/zapp/console/src/models/__mocks__/workflowData.ts @@ -1,8 +1,9 @@ import { getCacheKey } from 'components/Cache/utils'; import { Admin } from 'flyteidl'; import { cloneDeep } from 'lodash'; -import { Identifier } from 'models/Common/types'; +import { Identifier, ResourceType } from 'models/Common/types'; import { Workflow, WorkflowClosure } from 'models/Workflow/types'; +import { testDomain, testProject } from 'mocks/data/constants'; import * as simpleClosure from './simpleWorkflowClosure.json'; const decodedClosure = Admin.WorkflowClosure.create( @@ -12,8 +13,9 @@ const decodedClosure = Admin.WorkflowClosure.create( const workflowId: (name: string, version: string) => Identifier = (name, version) => ({ name, version, - project: 'flyte', - domain: 'development', + project: testProject, + domain: testDomain, + resourceType: ResourceType.WORKFLOW, }); export const createMockWorkflow: (name: string, version?: string) => Workflow = ( diff --git a/packages/zapp/console/src/routes/ApplicationRouter.tsx b/packages/zapp/console/src/routes/ApplicationRouter.tsx index 6840edaa3..0336daf18 100644 --- a/packages/zapp/console/src/routes/ApplicationRouter.tsx +++ b/packages/zapp/console/src/routes/ApplicationRouter.tsx @@ -36,8 +36,8 @@ export const ApplicationRouter: React.FC = () => ( component={withSideNavigation(components.workflowDetails)} /> - makeProjectDomainBoundPath(project, domain, `/workflows/${workflowName}/version/${version}`), - path: `${projectDomainBasePath}/workflows/:workflowName/version/:workflowVersion`, + // Entity Version Details + static EntityVersionDetails = { + makeUrl: ( + project: string, + domain: string, + entityName: string, + entityType: string, + version: string, + ) => + makeProjectDomainBoundPath( + project, + domain, + `/${entityType}/${entityName}/version/${version}`, + ), + path: `${projectDomainBasePath}/:entityType/:entityName/version/:entityVersion`, }; // Tasks