Skip to content

Commit

Permalink
feat: add task version info (#485)
Browse files Browse the repository at this point in the history
made the entities component become more generic that can support Workflow, Task, and others
added the inputs and outputs to task details page
added the versions table in task details page
added the version details page
added task details link in node side panel

Signed-off-by: eugenejahn <[email protected]>

Co-authored-by: Eugene Jahn <[email protected]>
  • Loading branch information
apTalya and eugenejahn authored May 19, 2022
1 parent 42d2632 commit 324b4f5
Show file tree
Hide file tree
Showing 38 changed files with 900 additions and 131 deletions.
2 changes: 1 addition & 1 deletion packages/zapp/console/src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
96 changes: 82 additions & 14 deletions packages/zapp/console/src/components/Entities/EntityDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, Variable> | undefined;
let outputs: Record<string, Variable> | 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 (
<WaitForData {...versions}>
{inputs && (
<Row title={t('inputsFieldName')}>
<ReactJsonViewWrapper src={inputs} shouldCollapse={(field) => !field?.name} />
</Row>
)}
{outputs && (
<Row title={t('outputsFieldName')}>
<ReactJsonViewWrapper src={outputs} shouldCollapse={(field) => !field?.name} />
</Row>
)}
</WaitForData>
);
};

/** Fetches and renders the description for a given Entity (LaunchPlan,Workflow,Task) ID */
export const EntityDescription: React.FC<{
id: ResourceIdentifier;
Expand All @@ -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 (
<>
<Typography variant="h6">Description</Typography>
<Typography variant="body2" className={styles.description}>
<Typography className={styles.header} variant="h3">
{t('basicInformation')}
</Typography>
<div className={styles.divider} />
<Typography variant="body2" component="span" className={styles.description}>
<WaitForData {...namedEntity} spinnerVariant="none" loadingComponent={Skeleton}>
<span
className={classnames({
[commonStyles.hintText]: !hasDescription,
})}
>
{hasDescription
? metadata.description
: t('noDescription', entityStrings[id.resourceType])}
</span>
<Row title={t('description')}>
<span
className={classnames({
[commonStyles.hintText]: !hasDescription,
})}
>
{hasDescription
? metadata.description
: t(patternKey('noDescription', entityStrings[id.resourceType]))}
</span>
</Row>
</WaitForData>
{sections?.descriptionInputsAndOutputs && <InputsAndOuputs id={id} />}
</Typography>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -77,7 +76,7 @@ export const EntityDetailsHeader: React.FC<EntityDetailsHeaderProps> = ({
className={commonStyles.linkUnstyled}
to={
backToWorkflow
? Routes.WorkflowDetails.makeUrl(id.project, id.domain, id.name)
? backToDetailUrlGenerator[id.resourceType](id)
: backUrlGenerator[id.resourceType](id)
}
>
Expand All @@ -93,7 +92,7 @@ export const EntityDetailsHeader: React.FC<EntityDetailsHeaderProps> = ({
onClick={() => setShowLaunchForm(true)}
variant="contained"
>
{t('launchStrings', entityStrings[id.resourceType])}
{t(patternKey('launchStrings', entityStrings[id.resourceType]))}
</Button>
) : null}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -76,8 +78,8 @@ export const EntityExecutions: React.FC<EntityExecutionsProps> = ({

return (
<>
<Typography className={styles.header} variant="h6">
All Executions in the Workflow
<Typography className={styles.header} variant="h3">
{t(patternKey('allExecutionsChartTitle', entityStrings[id.resourceType]))}
</Typography>
<div className={styles.filtersContainer}>
<ExecutionFilters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
getWorkflowExecutionPhaseConstants,
getWorkflowExecutionTimingMS,
} from '../Executions/utils';
import t from './strings';
import t, { patternKey } from './strings';
import { entityStrings } from './constants';

export interface EntityExecutionsBarChartProps {
id: ResourceIdentifier;
Expand Down Expand Up @@ -110,7 +111,7 @@ export const EntityExecutionsBarChart: React.FC<EntityExecutionsBarChartProps> =
return (
<WaitForData {...executions}>
<BarChart
title={t('allExecutionsChartTitle')}
title={t(patternKey('allExecutionsChartTitle', entityStrings[id.resourceType]))}
chartIds={chartIds}
data={getExecutionTimeData(executions.value)}
startDate={getStartExecutionTime(executions.value)}
Expand Down
17 changes: 14 additions & 3 deletions packages/zapp/console/src/components/Entities/EntitySchedules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@ import { identifierToString } from 'models/Common/utils';
import { LaunchPlan } from 'models/Launch/types';
import * as React from 'react';
import { entityStrings } from './constants';
import t from './strings';
import t, { patternKey } from './strings';

const useStyles = makeStyles((theme: Theme) => ({
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<{
Expand Down Expand Up @@ -45,13 +52,17 @@ export const EntitySchedules: React.FC<{
return (
<>
<WaitForData {...scheduledLaunchPlans} spinnerVariant="none">
<Typography variant="h6">{t('schedulesHeader')}</Typography>
<Typography className={styles.header} variant="h3">
{t('schedulesHeader')}
</Typography>
<div className={styles.divider} />

<div className={styles.schedulesContainer}>
{scheduledLaunchPlans.value.length > 0 ? (
<RenderSchedules launchPlans={scheduledLaunchPlans.value} />
) : (
<Typography variant="body2" className={commonStyles.hintText}>
{t('noSchedules', entityStrings[id.resourceType])}
{t(patternKey('noSchedules', entityStrings[id.resourceType]))}
</Typography>
)}
</div>
Expand Down
36 changes: 18 additions & 18 deletions packages/zapp/console/src/components/Entities/EntityVersions.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
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';
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: {
Expand Down Expand Up @@ -64,8 +63,10 @@ export const EntityVersions: React.FC<EntityVersionsProps> = ({ 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,
Expand All @@ -76,12 +77,10 @@ export const EntityVersions: React.FC<EntityVersionsProps> = ({ 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]);

Expand All @@ -102,8 +101,8 @@ export const EntityVersions: React.FC<EntityVersionsProps> = ({ id, showAll = fa
>
{showTable ? <ExpandLess /> : <ExpandMore />}
</IconButton>
<Typography className={styles.header} variant="h6">
{t('workflowVersionsTitle')}
<Typography className={styles.header} variant="h3">
{t(patternKey('versionsTitle', entityStrings[id.resourceType]))}
</Typography>
<Typography className={styles.viewAll} variant="body1" onClick={handleViewAll}>
{t('viewAll')}
Expand All @@ -112,10 +111,11 @@ export const EntityVersions: React.FC<EntityVersionsProps> = ({ id, showAll = fa
)}
<WaitForData {...versions}>
{showTable || showAll ? (
<WorkflowVersionsTable
<EntityVersionsTable
{...versions}
isFetching={isLoadingState(versions.state)}
versionView={showAll}
resourceType={resourceType}
/>
) : (
<div className={styles.divider} />
Expand Down
32 changes: 32 additions & 0 deletions packages/zapp/console/src/components/Entities/Row.tsx
Original file line number Diff line number Diff line change
@@ -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<MyProps> = (props) => {
const styles = useStyles();

return (
<div className={styles.row}>
<div className={styles.title}>
<Typography>{props.title}</Typography>
</div>
<div>{props.children}</div>
</div>
);
};
Loading

0 comments on commit 324b4f5

Please sign in to comment.