Skip to content

Commit

Permalink
Add new view for workflows in basic visibility clusters (#754)
Browse files Browse the repository at this point in the history
Add new view for workflows in Basic Visibility clusters
Add filters for basic visibility workflows
Add new type for basic visibility workflow status (which also includes all closed workflows)
Add new query params for workflowId, workflowType and basic visibility workflow status
  • Loading branch information
adhityamamallan authored Dec 6, 2024
1 parent 987ccfc commit fe91339
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/views/domain-page/config/domain-page-query-params.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { type PageQueryParam } from '@/hooks/use-page-query-params/use-page-quer
import parseDateQueryParam from '@/utils/datetime/parse-date-query-param';
import { type SortOrder } from '@/utils/sort-by';
import { type DomainWorkflowsHeaderInputType } from '@/views/domain-workflows/domain-workflows-header/domain-workflows-header.types';
import { type WorkflowStatusBasicVisibility } from '@/views/domain-workflows-basic/domain-workflows-basic-filters-status/domain-workflows-basic-filters-status.types';
import isWorkflowStatusBasicVisibility from '@/views/domain-workflows-basic/domain-workflows-basic-filters-status/helpers/is-workflow-status-basic-visibility';
import isWorkflowStatus from '@/views/shared/workflow-status-tag/helpers/is-workflow-status';
import { type WorkflowStatus } from '@/views/shared/workflow-status-tag/workflow-status-tag.types';

Expand All @@ -16,6 +18,10 @@ const domainPageQueryParamsConfig: [
PageQueryParam<'sortOrder', SortOrder>,
// Query input
PageQueryParam<'query', string>,
// Basic Visibility inputs
PageQueryParam<'workflowId', string>,
PageQueryParam<'workflowType', string>,
PageQueryParam<'statusBasic', WorkflowStatusBasicVisibility | undefined>,
] = [
{
key: 'inputType',
Expand Down Expand Up @@ -57,6 +63,20 @@ const domainPageQueryParamsConfig: [
key: 'query',
defaultValue: '',
},
{
key: 'workflowId',
defaultValue: '',
},
{
key: 'workflowType',
defaultValue: '',
},
{
key: 'statusBasic',
queryParamKey: 'status',
parseValue: (value: string) =>
isWorkflowStatusBasicVisibility(value) ? value : undefined,
},
] as const;

export default domainPageQueryParamsConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { type PageFilterConfig } from '@/components/page-filters/page-filters.types';
import type domainPageQueryParamsConfig from '@/views/domain-page/config/domain-page-query-params.config';
import DomainWorkflowsFiltersDates from '@/views/domain-workflows/domain-workflows-filters-dates/domain-workflows-filters-dates';
import { type DomainWorkflowsFiltersDatesValue } from '@/views/domain-workflows/domain-workflows-filters-dates/domain-workflows-filters-dates.types';

import DomainWorkflowsBasicFiltersStatus from '../domain-workflows-basic-filters-status/domain-workflows-basic-filters-status';
import { type DomainWorkflowsBasicFiltersStatusValue } from '../domain-workflows-basic-filters-status/domain-workflows-basic-filters-status.types';

const domainWorkflowsBasicFiltersConfig: [
PageFilterConfig<
typeof domainPageQueryParamsConfig,
DomainWorkflowsBasicFiltersStatusValue
>,
PageFilterConfig<
typeof domainPageQueryParamsConfig,
DomainWorkflowsFiltersDatesValue
>,
] = [
{
id: 'status',
getValue: (v) => ({ statusBasic: v.statusBasic }),
formatValue: (v) => v,
component: DomainWorkflowsBasicFiltersStatus,
},
{
id: 'dates',
getValue: (v) => ({
timeRangeStart: v.timeRangeStart,
timeRangeEnd: v.timeRangeEnd,
}),
formatValue: (v) => ({
timeRangeStart: v.timeRangeStart?.toISOString(),
timeRangeEnd: v.timeRangeEnd?.toISOString(),
}),
component: DomainWorkflowsFiltersDates,
},
] as const;

export default domainWorkflowsBasicFiltersConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const DOMAIN_WORKFLOWS_BASIC_SEARCH_DEBOUNCE_MS = 250;

export default DOMAIN_WORKFLOWS_BASIC_SEARCH_DEBOUNCE_MS;
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';

import { render, screen, fireEvent, act } from '@/test-utils/rtl';

import { mockDomainWorkflowsQueryParamsValues } from '@/views/domain-workflows/__fixtures__/domain-workflows-query-params';

import DomainWorkflowsBasicFiltersStatus from '../domain-workflows-basic-filters-status';
import { WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY } from '../domain-workflows-basic-filters-status.constants';
import { type DomainWorkflowsBasicFiltersStatusValue } from '../domain-workflows-basic-filters-status.types';

describe(DomainWorkflowsBasicFiltersStatus.name, () => {
it('renders without errors', () => {
setup({});
expect(screen.getByRole('combobox')).toBeInTheDocument();
});

it('displays all the options in the select component', () => {
setup({});
const selectFilter = screen.getByRole('combobox');
act(() => {
fireEvent.click(selectFilter);
});
Object.entries(WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY).forEach(
([_, value]) => expect(screen.getByText(value)).toBeInTheDocument()
);
});

it('calls the setQueryParams function when an option is selected', () => {
const { mockSetValue } = setup({});
const selectFilter = screen.getByRole('combobox');
act(() => {
fireEvent.click(selectFilter);
});
const runningOption = screen.getByText('Closed');
act(() => {
fireEvent.click(runningOption);
});
expect(mockSetValue).toHaveBeenCalledWith({
statusBasic: 'ALL_CLOSED',
});
});

it('calls the setQueryParams function when the filter is cleared', () => {
const { mockSetValue } = setup({
overrides: {
statusBasic: 'WORKFLOW_EXECUTION_CLOSE_STATUS_FAILED',
},
});
const clearButton = screen.getByLabelText('Clear value');
act(() => {
fireEvent.click(clearButton);
});
expect(mockSetValue).toHaveBeenCalledWith({ statusBasic: undefined });
});
});

function setup({
overrides,
}: {
overrides?: DomainWorkflowsBasicFiltersStatusValue;
}) {
const mockSetValue = jest.fn();
render(
<DomainWorkflowsBasicFiltersStatus
value={{
statusBasic: mockDomainWorkflowsQueryParamsValues.statusBasic,
...overrides,
}}
setValue={mockSetValue}
/>
);

return { mockSetValue };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { WORKFLOW_STATUS_NAMES } from '@/views/shared/workflow-status-tag/workflow-status-tag.constants';

import { type WorkflowStatusBasicVisibility } from './domain-workflows-basic-filters-status.types';

export const WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY = {
ALL_CLOSED: 'Closed',
...WORKFLOW_STATUS_NAMES,
} as const satisfies Record<WorkflowStatusBasicVisibility, string>;

export const WORKFLOW_STATUS_OPTIONS_BASIC_VISIBILITY = Object.entries(
WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY
).map(([key, value]) => ({
id: key,
label: value,
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type Theme } from 'baseui';
import type { FormControlOverrides } from 'baseui/form-control/types';
import { type StyleObject } from 'styletron-react';

export const overrides = {
selectFormControl: {
Label: {
style: ({ $theme }: { $theme: Theme }): StyleObject => ({
...$theme.typography.LabelXSmall,
}),
},
ControlContainer: {
style: (): StyleObject => ({
margin: '0px',
}),
},
} satisfies FormControlOverrides,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client';
import React from 'react';

import { FormControl } from 'baseui/form-control';
import { Select, SIZE } from 'baseui/select';

import { type PageFilterComponentProps } from '@/components/page-filters/page-filters.types';
import { type WorkflowStatus } from '@/views/shared/workflow-status-tag/workflow-status-tag.types';

import { WORKFLOW_STATUS_OPTIONS_BASIC_VISIBILITY } from './domain-workflows-basic-filters-status.constants';
import { overrides } from './domain-workflows-basic-filters-status.styles';
import { type DomainWorkflowsBasicFiltersStatusValue } from './domain-workflows-basic-filters-status.types';

export default function DomainWorkflowsBasicFiltersStatus({
value,
setValue,
}: PageFilterComponentProps<DomainWorkflowsBasicFiltersStatusValue>) {
const statusOptionValue = WORKFLOW_STATUS_OPTIONS_BASIC_VISIBILITY.filter(
(option) => option.id === value.statusBasic
);

return (
<FormControl label="Status" overrides={overrides.selectFormControl}>
<Select
size={SIZE.compact}
value={statusOptionValue}
options={WORKFLOW_STATUS_OPTIONS_BASIC_VISIBILITY}
onChange={(params) =>
setValue({
statusBasic: WORKFLOW_STATUS_OPTIONS_BASIC_VISIBILITY.find(
(opt) => opt.id === params.value[0]?.id
)
? (String(params.value[0]?.id) as WorkflowStatus)
: undefined,
})
}
placeholder="Show all statuses"
/>
</FormControl>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { type WorkflowStatus } from '@/views/shared/workflow-status-tag/workflow-status-tag.types';

export type WorkflowStatusBasicVisibility = WorkflowStatus | 'ALL_CLOSED';

export type DomainWorkflowsBasicFiltersStatusValue = {
statusBasic: WorkflowStatusBasicVisibility | undefined;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY } from '../../domain-workflows-basic-filters-status.constants';
import isWorkflowStatusBasicVisibility from '../is-workflow-status-basic-visibility';

describe(isWorkflowStatusBasicVisibility.name, () => {
it('should return true for valid basic visibility workflow status', () => {
Object.keys(WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY).forEach((key) => {
expect(isWorkflowStatusBasicVisibility(key)).toBe(true);
});
});

it('should return false for invalid basic visibility workflow status', () => {
expect(isWorkflowStatusBasicVisibility('InvalidStatus')).toBe(false);
expect(isWorkflowStatusBasicVisibility(123)).toBe(false);
expect(isWorkflowStatusBasicVisibility(null)).toBe(false);
expect(isWorkflowStatusBasicVisibility(undefined)).toBe(false);
expect(isWorkflowStatusBasicVisibility({})).toBe(false);
expect(isWorkflowStatusBasicVisibility([])).toBe(false);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY } from '../domain-workflows-basic-filters-status.constants';
import { type WorkflowStatusBasicVisibility } from '../domain-workflows-basic-filters-status.types';

export default function isWorkflowStatusBasicVisibility(
value: any
): value is WorkflowStatusBasicVisibility {
return value in WORKFLOW_STATUS_NAMES_BASIC_VISIBILITY;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { styled as createStyled, type Theme } from 'baseui';

export const styled = {
HeaderContainer: createStyled('div', ({ $theme }: { $theme: Theme }) => ({
marginTop: $theme.sizing.scale950,
marginBottom: $theme.sizing.scale900,
})),
InputContainer: createStyled('div', ({ $theme }: { $theme: Theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: $theme.sizing.scale500,
marginBottom: $theme.sizing.scale500,
[$theme.mediaQuery.medium]: {
flexDirection: 'row',
},
})),
SearchContainer: createStyled('div', ({ $theme }: { $theme: Theme }) => ({
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
gap: $theme.sizing.scale500,
[$theme.mediaQuery.medium]: {
flexDirection: 'row',
},
})),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use client';
import { useState } from 'react';

import usePageFilters from '@/components/page-filters/hooks/use-page-filters';
import PageFiltersFields from '@/components/page-filters/page-filters-fields/page-filters-fields';
import PageFiltersSearch from '@/components/page-filters/page-filters-search/page-filters-search';
import PageFiltersToggle from '@/components/page-filters/page-filters-toggle/page-filters-toggle';
import domainPageQueryParamsConfig from '@/views/domain-page/config/domain-page-query-params.config';

import domainWorkflowsBasicFiltersConfig from '../config/domain-workflows-basic-filters.config';
import DOMAIN_WORKFLOWS_BASIC_SEARCH_DEBOUNCE_MS from '../config/domain-workflows-basic-search-debounce-ms.config';

import { styled } from './domain-workflows-basic-filters.styles';

export default function DomainWorkflowsBasicFilters() {
const [areFiltersShown, setAreFiltersShown] = useState(false);

const { resetAllFilters, activeFiltersCount, queryParams, setQueryParams } =
usePageFilters({
pageFiltersConfig: domainWorkflowsBasicFiltersConfig,
pageQueryParamsConfig: domainPageQueryParamsConfig,
});

return (
<styled.HeaderContainer>
<styled.InputContainer>
<styled.SearchContainer>
<PageFiltersSearch
pageQueryParamsConfig={domainPageQueryParamsConfig}
searchQueryParamKey="workflowId"
searchPlaceholder="Workflow ID"
inputDebounceDurationMs={DOMAIN_WORKFLOWS_BASIC_SEARCH_DEBOUNCE_MS}
/>
<PageFiltersSearch
pageQueryParamsConfig={domainPageQueryParamsConfig}
searchQueryParamKey="workflowType"
searchPlaceholder="Workflow Type"
inputDebounceDurationMs={DOMAIN_WORKFLOWS_BASIC_SEARCH_DEBOUNCE_MS}
/>
<PageFiltersToggle
isActive={areFiltersShown}
onClick={() => {
setAreFiltersShown((value) => !value);
}}
activeFiltersCount={activeFiltersCount}
/>
</styled.SearchContainer>
</styled.InputContainer>
{areFiltersShown && (
<PageFiltersFields
pageFiltersConfig={domainWorkflowsBasicFiltersConfig}
resetAllFilters={resetAllFilters}
queryParams={queryParams}
setQueryParams={setQueryParams}
/>
)}
</styled.HeaderContainer>
);
}
14 changes: 14 additions & 0 deletions src/views/domain-workflows-basic/domain-workflows-basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

import { type DomainPageTabContentProps } from '@/views/domain-page/domain-page-content/domain-page-content.types';

import DomainWorkflowsBasicFilters from './domain-workflows-basic-filters/domain-workflows-basic-filters';

export default function DomainWorkflowsBasic(props: DomainPageTabContentProps) {
return (
<>
<DomainWorkflowsBasicFilters />
{/* <DomainWorkflowsBasicTable domain={props.domain} cluster={props.cluster} /> */}
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export const mockDomainWorkflowsQueryParamsValues: PageQueryParamValues<
sortColumn: 'startTime',
sortOrder: 'DESC',
query: '',
workflowId: '',
workflowType: '',
statusBasic: undefined,
};

export const mockDateOverrides = {
Expand Down

0 comments on commit fe91339

Please sign in to comment.