Skip to content

Commit

Permalink
feat: add domain settings for project dashboard (#689)
Browse files Browse the repository at this point in the history
* feat: add domain settings for project dashboard

Signed-off-by: 4nalog <[email protected]>

* fix: dependency between queries

Signed-off-by: 4nalog <[email protected]>

* refactor: use exact imports from lodash

Signed-off-by: 4nalog <[email protected]>

* refactor: tests for domain settings

Signed-off-by: 4nalog <[email protected]>

* chore: bump minor version

Signed-off-by: 4nalog <[email protected]>

* refactor: minor version bump test

Signed-off-by: 4nalog <[email protected]>

* chore: bump minor version

Signed-off-by: 4nalog <[email protected]>

* Update package.json

Signed-off-by: 4nalog <[email protected]>

---------

Signed-off-by: 4nalog <[email protected]>
Co-authored-by: Soham Parekh <[email protected]>
  • Loading branch information
4nalog and Soham Parekh authored Feb 23, 2023
1 parent 3c5d6e8 commit 797bcc2
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 26 deletions.
2 changes: 1 addition & 1 deletion packages/console/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@flyteorg/console",
"version": "0.0.9",
"version": "0.0.10",
"description": "Flyteconsole main app module",
"main": "./dist/index.js",
"module": "./lib/index.js",
Expand Down
36 changes: 30 additions & 6 deletions packages/console/src/components/Project/ProjectDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ import { useOnlyMyExecutionsFilterState } from 'components/Executions/filters/us
import { WaitForData } from 'components/common/WaitForData';
import { history } from 'routes/history';
import { Routes } from 'routes/routes';
import { compact } from 'lodash';
import { getProjectDomainAttributes } from 'models/Project/api';
import { compact, merge } from 'lodash';
import {
getProjectAttributes,
getProjectDomainAttributes,
} from 'models/Project/api';
import t from './strings';
import { failedToLoadExecutionsString } from './constants';

Expand Down Expand Up @@ -166,7 +169,24 @@ export const ProjectDashboard: React.FC<ProjectDashboardProps> = ({
);
return projectDomainAtributes;
},
staleTime: Infinity,
});

const projectAttributesQuery = useQuery<
Admin.ProjectAttributesGetResponse,
Error
>({
queryKey: ['projectAttributes', project],
queryFn: async () => {
const projectAtributes = await getProjectAttributes({
project,
});
queryClient.setQueryData(
['projectAttributes', project],
projectAtributes,
);
return projectAtributes;
},
enabled: !projectDomainAttributesQuery.isFetching,
});

const content = executionsQuery.isLoadingError ? (
Expand All @@ -191,8 +211,12 @@ export const ProjectDashboard: React.FC<ProjectDashboardProps> = ({
);

const configData =
projectDomainAttributesQuery.data?.attributes?.matchingAttributes
?.workflowExecutionConfig ?? undefined;
merge(
projectAttributesQuery.data?.attributes?.matchingAttributes
?.workflowExecutionConfig,
projectDomainAttributesQuery.data?.attributes?.matchingAttributes
?.workflowExecutionConfig,
) ?? undefined;

const renderDomainSettingsSection = () => (
<DomainSettingsSection configData={configData} />
Expand All @@ -206,7 +230,7 @@ export const ProjectDashboard: React.FC<ProjectDashboardProps> = ({
</Typography>
<Typography variant="h5">{t('tasksTotal', numberOfTasks)}</Typography>
</div>
<WaitForQuery query={projectDomainAttributesQuery}>
<WaitForQuery query={projectAttributesQuery}>
{renderDomainSettingsSection}
</WaitForQuery>
<div className={styles.container}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import {
import { useUserProfile } from 'components/hooks/useUserProfile';
import { FetchableData } from 'components/hooks/types';
import { loadedFetchable } from 'components/hooks/__mocks__/fetchableData';
import { getProjectDomainAttributes } from 'models/Project/api';
import {
getProjectAttributes,
getProjectDomainAttributes,
} from 'models/Project/api';
import { Admin } from '@flyteorg/flyteidl-types';
import * as LocalCache from 'basics/LocalCache';
import { ProjectDashboard } from '../ProjectDashboard';
Expand All @@ -33,6 +36,31 @@ jest.mock('notistack', () => ({
}));

jest.mock('models/Project/api', () => ({
getProjectAttributes: jest.fn().mockResolvedValue(() => {
const projectAttributesMock: Admin.ProjectAttributesGetResponse = {
attributes: {
matchingAttributes: {
workflowExecutionConfig: {
maxParallelism: 1,
securityContext: { runAs: { k8sServiceAccount: 'default' } },
rawOutputDataConfig: {
outputLocationPrefix:
'cliOutputLocationPrefixFromProjectAttributes',
},
annotations: {
values: {
cliAnnotationKey: 'cliAnnotationValueFromProjectAttributes',
},
},
labels: {
values: { cliLabelKey: 'cliLabelValueFromProjectAttributes' },
},
},
},
},
};
return projectAttributesMock;
}),
getProjectDomainAttributes: jest.fn().mockResolvedValue(() => {
const projectDomainAttributesMock: Admin.ProjectDomainAttributesDeleteResponse =
{
Expand All @@ -41,9 +69,6 @@ jest.mock('models/Project/api', () => ({
workflowExecutionConfig: {
maxParallelism: 5,
securityContext: { runAs: { k8sServiceAccount: 'default' } },
rawOutputDataConfig: {
outputLocationPrefix: 'cliOutputLocationPrefix',
},
annotations: {
values: { cliAnnotationKey: 'cliAnnotationValue' },
},
Expand Down Expand Up @@ -123,9 +148,17 @@ describe('ProjectDashboard', () => {

it('should display domain attributes section when config was provided', async () => {
const { getByText } = renderView();
expect(getProjectAttributes).toHaveBeenCalled();
expect(getProjectDomainAttributes).toHaveBeenCalled();
await waitFor(() => {
expect(getByText('Domain Settings')).toBeInTheDocument();
expect(
getByText('cliOutputLocationPrefixFromProjectAttributes'),
).toBeInTheDocument();
expect(getByText('cliAnnotationKey')).toBeInTheDocument();
expect(
getByText('cliAnnotationValueFromProjectAttributes'),
).not.toBeInTheDocument();
});
});

Expand Down
12 changes: 6 additions & 6 deletions packages/console/src/components/common/DomainSettingsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ export const DomainSettingsSection = ({
return null;
}

const role = configData.securityContext?.runAs?.iamRole || t('inherited');
const role = configData.securityContext?.runAs?.iamRole || t('noValue');
const serviceAccount =
configData.securityContext?.runAs?.k8sServiceAccount || t('inherited');
configData.securityContext?.runAs?.k8sServiceAccount || t('noValue');
const rawData =
configData.rawOutputDataConfig?.outputLocationPrefix || t('inherited');
configData.rawOutputDataConfig?.outputLocationPrefix || t('noValue');
const maxParallelism = configData.maxParallelism || undefined;

return (
Expand Down Expand Up @@ -101,15 +101,15 @@ export const DomainSettingsSection = ({
{configData.labels?.values ? (
<DataTable data={configData.labels.values} />
) : (
t('inherited')
t('noValue')
)}
</div>
<div>
<p className={styles.subHeader}>{t('annotationsHeader')}</p>
{configData.annotations?.values ? (
<DataTable data={configData.annotations.values} />
) : (
t('inherited')
t('noValue')
)}
</div>
<div>
Expand All @@ -122,7 +122,7 @@ export const DomainSettingsSection = ({
{t('maxParallelismHeader')}
</p>
<Typography variant="body2">
{maxParallelism ?? t('inherited')}
{maxParallelism ?? t('noValue')}
</Typography>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/console/src/components/common/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const str = {
securityContextHeader: 'Security Context',
serviceAccountHeader: 'Service Account',
noMatchingResults: 'No matching results',
noValue: '-',
missingUnionListOfSubType: 'Unexpected missing type for union',
missingMapSubType: 'Unexpected missing subtype for map',
mapMissingMapProperty: 'Map literal missing `map` property',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('DomainSettingsSection', () => {
const tables = queryAllByRole('table');
expect(tables).toHaveLength(2);
// should display a placeholder text, as role was not passed
const emptyRole = queryByText('Inherits from project level values');
const emptyRole = queryByText('-');
expect(emptyRole).toBeInTheDocument();
});

Expand All @@ -76,9 +76,7 @@ describe('DomainSettingsSection', () => {
const tables = queryAllByRole('table');
expect(tables).toHaveLength(1);
// should display two placeholder text, as role and labels were not passed
const inheritedPlaceholders = queryAllByText(
'Inherits from project level values',
);
const inheritedPlaceholders = queryAllByText('-');
expect(inheritedPlaceholders).toHaveLength(2);
});

Expand All @@ -101,9 +99,7 @@ describe('DomainSettingsSection', () => {
const tables = queryByRole('table');
expect(tables).not.toBeInTheDocument();
// should display three placeholder text, as role, labels, annotations were not passed
const inheritedPlaceholders = queryAllByText(
'Inherits from project level values',
);
const inheritedPlaceholders = queryAllByText('-');
expect(inheritedPlaceholders).toHaveLength(3);
});
});
1 change: 1 addition & 0 deletions packages/console/src/models/Common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const endpointPrefixes = {
nodeExecution: '/node_executions',
dynamicWorkflowExecution: '/data/node_executions',
project: '/projects',
projectAttributes: '/project_attributes',
projectDomainAtributes: '/project_domain_attributes',
relaunchExecution: '/executions/relaunch',
recoverExecution: '/executions/recover',
Expand Down
21 changes: 20 additions & 1 deletion packages/console/src/models/Project/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@ export const listProjects = () =>
sortBy(projects, project => `${project.name}`.toLowerCase()) as Project[],
});

export const getProjectAttributes = (scope: IdentifierScope) =>
getAdminEntity<
Admin.ProjectAttributesGetResponse,
Admin.ProjectAttributesGetResponse
>(
{
path: makeProjectDomainAttributesPath(
endpointPrefixes.projectAttributes,
scope,
),
messageType: Admin.ProjectAttributesGetResponse,
},
{
params: {
resource_type: Admin.MatchableResource.WORKFLOW_EXECUTION_CONFIG,
},
},
);

export const getProjectDomainAttributes = (scope: IdentifierScope) =>
getAdminEntity<
Admin.ProjectDomainAttributesGetResponse,
Expand All @@ -32,7 +51,7 @@ export const getProjectDomainAttributes = (scope: IdentifierScope) =>
},
{
params: {
resource_type: 'WORKFLOW_EXECUTION_CONFIG',
resource_type: Admin.MatchableResource.WORKFLOW_EXECUTION_CONFIG,
},
},
);
3 changes: 2 additions & 1 deletion packages/console/src/models/Project/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { compact } from 'lodash';
import { Identifier } from 'models/Common/types';
import { Project } from './types';

Expand All @@ -15,5 +16,5 @@ export function makeProjectDomainAttributesPath(
prefix: string,
{ project, domain }: Partial<Identifier>,
) {
return [prefix, project, domain].join('/');
return compact([prefix, project, domain]).join('/');
}

0 comments on commit 797bcc2

Please sign in to comment.