Skip to content

Commit

Permalink
Add features quantity in workspace list page (opensearch-project#309)
Browse files Browse the repository at this point in the history
* feat: unite feature set

Signed-off-by: tygao <tygao@amazon.com>

* update feature utils

Signed-off-by: tygao <tygao@amazon.com>

* update feature utils

Signed-off-by: tygao <tygao@amazon.com>

* use featureMatchConfig

Signed-off-by: tygao <tygao@amazon.com>

* update

Signed-off-by: tygao <tygao@amazon.com>

* add util test

Signed-off-by: tygao <tygao@amazon.com>

* unite feature set

Signed-off-by: tygao <tygao@amazon.com>

---------

Signed-off-by: tygao <tygao@amazon.com>
  • Loading branch information
raintygao authored Apr 2, 2024
1 parent e2d36ba commit 55d9b82
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@ import {
import { i18n } from '@osd/i18n';
import { groupBy } from 'lodash';

import {
AppNavLinkStatus,
DEFAULT_APP_CATEGORIES,
PublicAppInfo,
} from '../../../../../core/public';
import { DEFAULT_APP_CATEGORIES, PublicAppInfo } from '../../../../../core/public';

import { WorkspaceFeature, WorkspaceFeatureGroup } from './types';
import { isDefaultCheckedFeatureId, isWorkspaceFeatureGroup } from './utils';
import { getAllExcludingManagementApps } from '../../utils';

const libraryCategoryLabel = i18n.translate('core.ui.libraryNavList.label', {
defaultMessage: 'Library',
Expand Down Expand Up @@ -58,17 +55,10 @@ export const WorkspaceFeatureSelector = ({
Array<WorkspaceFeature | WorkspaceFeatureGroup>
>((previousValue, currentKey) => {
const apps = category2Applications[currentKey];
const features = apps
.filter(
({ navLinkStatus, chromeless, category }) =>
navLinkStatus !== AppNavLinkStatus.hidden &&
!chromeless &&
category?.id !== DEFAULT_APP_CATEGORIES.management.id
)
.map(({ id, title }) => ({
id,
name: title,
}));
const features = getAllExcludingManagementApps(apps).map(({ id, title }) => ({
id,
name: title,
}));
if (features.length === 0) {
return previousValue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import { WORKSPACE_CREATE_APP_ID } from '../../../common/constants';

import { cleanWorkspaceId } from '../../../../../core/public';
import { DeleteWorkspaceModal } from '../delete_workspace_modal';
import { useApplications } from '././../../hooks';
import { getSelectedFeatureQuantities } from '../../utils';

const WORKSPACE_LIST_PAGE_DESCRIPTIOIN = i18n.translate('workspace.list.description', {
defaultMessage:
Expand All @@ -47,6 +49,7 @@ export const WorkspaceList = () => {
pageSizeOptions: [5, 10, 20],
});
const [deletedWorkspace, setDeletedWorkspace] = useState<WorkspaceAttribute | null>(null);
const applications = useApplications(application);

const handleSwitchWorkspace = useCallback(
(id: string) => {
Expand Down Expand Up @@ -106,6 +109,10 @@ export const WorkspaceList = () => {
name: 'Features',
isExpander: true,
hasActions: true,
render: (features: string[]) => {
const { total, selected } = getSelectedFeatureQuantities(features, applications);
return `${selected}/${total}`;
},
},
{
name: 'Actions',
Expand Down
9 changes: 5 additions & 4 deletions src/plugins/workspace/public/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { ApplicationStart, PublicAppInfo } from 'opensearch-dashboards/public';
import { useObservable } from 'react-use';
import { useMemo } from 'react';
import { of } from 'rxjs';
import { ApplicationStart, PublicAppInfo } from '../../../core/public';

export function useApplications(application: ApplicationStart) {
const applications = useObservable(application.applications$);
export function useApplications(application?: ApplicationStart) {
const applications = useObservable(application?.applications$ ?? of(new Map()), new Map());
return useMemo(() => {
const apps: PublicAppInfo[] = [];
applications?.forEach((app) => {
applications.forEach((app) => {
apps.push(app);
});
return apps;
Expand Down
48 changes: 47 additions & 1 deletion src/plugins/workspace/public/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { featureMatchesConfig } from './utils';
import { featureMatchesConfig, getSelectedFeatureQuantities } from './utils';
import { PublicAppInfo } from '../../../core/public';

describe('workspace utils: featureMatchesConfig', () => {
it('feature configured with `*` should match any features', () => {
Expand Down Expand Up @@ -91,3 +92,48 @@ describe('workspace utils: featureMatchesConfig', () => {
);
});
});

describe('workspace utils: getSelectedFeatureQuantities', () => {
const defaultApplications = [
{
appRoute: '/app/dashboards',
id: 'dashboards',
title: 'Dashboards',
category: {
id: 'opensearchDashboards',
label: 'OpenSearch Dashboards',
euiIconType: 'inputOutput',
order: 1000,
},
status: 0,
navLinkStatus: 1,
},
{
appRoute: '/app/dev_tools',
id: 'dev_tools',
title: 'Dev Tools',
category: {
id: 'management',
label: 'Management',
order: 5000,
euiIconType: 'managementApp',
},
status: 0,
navLinkStatus: 1,
},
] as PublicAppInfo[];
it('should support * rules and exclude management category', () => {
const { total, selected } = getSelectedFeatureQuantities(['*'], defaultApplications);
expect(total).toBe(1);
expect(selected).toBe(1);
});

it('should get quantity normally and exclude management category', () => {
const { total, selected } = getSelectedFeatureQuantities(
['dev_tools', '!@management'],
defaultApplications
);
expect(total).toBe(1);
expect(selected).toBe(0);
});
});
30 changes: 29 additions & 1 deletion src/plugins/workspace/public/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { AppCategory } from '../../../core/public';
import {
AppCategory,
PublicAppInfo,
AppNavLinkStatus,
DEFAULT_APP_CATEGORIES,
} from '../../../core/public';

/**
* Checks if a given feature matches the provided feature configuration.
Expand Down Expand Up @@ -55,3 +60,26 @@ export const featureMatchesConfig = (featureConfigs: string[]) => ({

return matched;
};

// Get all apps excluding management category
export const getAllExcludingManagementApps = (applications: PublicAppInfo[]): PublicAppInfo[] => {
return applications.filter(
({ navLinkStatus, chromeless, category }) =>
navLinkStatus !== AppNavLinkStatus.hidden &&
!chromeless &&
category?.id !== DEFAULT_APP_CATEGORIES.management.id
);
};

export const getSelectedFeatureQuantities = (
featuresConfig: string[],
applications: PublicAppInfo[]
) => {
const visibleApplications = getAllExcludingManagementApps(applications);
const featureFilter = featureMatchesConfig(featuresConfig);
const selectedApplications = visibleApplications.filter((app) => featureFilter(app));
return {
total: visibleApplications.length,
selected: selectedApplications.length,
};
};

0 comments on commit 55d9b82

Please sign in to comment.