diff --git a/src/plugins/workspace/common/constants.ts b/src/plugins/workspace/common/constants.ts index 903f028539d..2f67640bcd3 100644 --- a/src/plugins/workspace/common/constants.ts +++ b/src/plugins/workspace/common/constants.ts @@ -11,6 +11,7 @@ export const PATHS = { create: '/create', overview: '/overview', update: '/update', + list: '/list', }; export const WORKSPACE_OP_TYPE_CREATE = 'create'; export const WORKSPACE_OP_TYPE_UPDATE = 'update'; diff --git a/src/plugins/workspace/public/components/routes.ts b/src/plugins/workspace/public/components/routes.ts index 33f7b477471..9c2d568db02 100644 --- a/src/plugins/workspace/public/components/routes.ts +++ b/src/plugins/workspace/public/components/routes.ts @@ -8,6 +8,7 @@ import { PATHS } from '../../common/constants'; import { WorkspaceCreator } from './workspace_creator'; import { WorkspaceUpdater } from './workspace_updater'; import { WorkspaceOverview } from './workspace_overview'; +import { WorkspaceList } from './workspace_list'; export interface RouteConfig { path: string; @@ -32,4 +33,9 @@ export const ROUTES: RouteConfig[] = [ Component: WorkspaceUpdater, label: 'Update', }, + { + path: PATHS.list, + Component: WorkspaceList, + label: 'List', + }, ]; diff --git a/src/plugins/workspace/public/components/utils/workspace.ts b/src/plugins/workspace/public/components/utils/workspace.ts new file mode 100644 index 00000000000..7ad9a43bf72 --- /dev/null +++ b/src/plugins/workspace/public/components/utils/workspace.ts @@ -0,0 +1,22 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { WORKSPACE_APP_ID, PATHS } from '../../../common/constants'; +import { CoreStart } from '../../../../../core/public'; + +type Core = Pick; + +export const switchWorkspace = ({ workspaces, application }: Core, id: string) => { + const newUrl = workspaces?.formatUrlWithWorkspaceId( + application.getUrlForApp(WORKSPACE_APP_ID, { + path: PATHS.update, + absolute: true, + }), + id + ); + if (newUrl) { + window.location.href = newUrl; + } +}; diff --git a/src/plugins/workspace/public/components/workspace_list/index.tsx b/src/plugins/workspace/public/components/workspace_list/index.tsx new file mode 100644 index 00000000000..4568836b87a --- /dev/null +++ b/src/plugins/workspace/public/components/workspace_list/index.tsx @@ -0,0 +1,127 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useState } from 'react'; +import { + EuiPage, + EuiPageBody, + EuiPageHeader, + EuiPageContent, + EuiBasicTable, + EuiLink, + Direction, + CriteriaWithPagination, +} from '@elastic/eui'; +import useObservable from 'react-use/lib/useObservable'; +import { useMemo } from 'react'; +import { useCallback } from 'react'; +import { WorkspaceAttribute } from '../../../../../core/public'; + +import { useOpenSearchDashboards } from '../../../../../plugins/opensearch_dashboards_react/public'; +import { switchWorkspace } from '../utils/workspace'; + +export const WorkspaceList = () => { + const { + services: { workspaces, application }, + } = useOpenSearchDashboards(); + + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(5); + const [sortField, setSortField] = useState<'name' | 'id'>('name'); + const [sortDirection, setSortDirection] = useState('asc'); + + const workspaceList = useObservable(workspaces!.client.workspaceList$, []); + + const pageOfItems = useMemo(() => { + return workspaceList + .sort((a, b) => { + const compare = a[sortField].localeCompare(b[sortField]); + return sortDirection === 'asc' ? compare : -compare; + }) + .slice(pageIndex * pageSize, (pageIndex + 1) * pageSize); + }, [workspaceList, pageIndex, pageSize, sortField, sortDirection]); + + const handleSwitchWorkspace = useCallback( + (id: string) => { + if (workspaces && application) { + switchWorkspace({ workspaces, application }, id); + } + }, + [workspaces, application] + ); + + const columns = [ + { + field: 'name', + name: 'Name', + sortable: true, + render: (name: string, item: WorkspaceAttribute) => ( + + handleSwitchWorkspace(item.id)}>{name} + + ), + }, + { + field: 'id', + name: 'ID', + sortable: true, + }, + { + field: 'description', + name: 'Description', + truncateText: true, + }, + { + field: 'features', + name: 'Features', + isExpander: true, + hasActions: true, + }, + ]; + + const onTableChange = ({ page, sort }: CriteriaWithPagination) => { + const { field, direction } = sort!; + const { index, size } = page; + + setPageIndex(index); + setPageSize(size); + setSortField(field as 'name' | 'id'); + setSortDirection(direction); + }; + + return ( + + + + + + + + + ); +}; diff --git a/src/plugins/workspace/public/containers/workspace_dropdown_list/workspace_dropdown_list.tsx b/src/plugins/workspace/public/containers/workspace_dropdown_list/workspace_dropdown_list.tsx index ce1b8a6053d..3dd50bb5886 100644 --- a/src/plugins/workspace/public/containers/workspace_dropdown_list/workspace_dropdown_list.tsx +++ b/src/plugins/workspace/public/containers/workspace_dropdown_list/workspace_dropdown_list.tsx @@ -9,6 +9,7 @@ import { EuiButton, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import useObservable from 'react-use/lib/useObservable'; import { CoreStart, WorkspaceAttribute } from '../../../../../core/public'; import { WORKSPACE_APP_ID, PATHS } from '../../../common/constants'; +import { switchWorkspace } from '../../components/utils/workspace'; type WorkspaceOption = EuiComboBoxOptionOption; @@ -57,19 +58,10 @@ export function WorkspaceDropdownList(props: WorkspaceDropdownListProps) { /** switch the workspace */ setLoading(true); const id = workspaceOption[0].key!; - const newUrl = coreStart.workspaces?.formatUrlWithWorkspaceId( - coreStart.application.getUrlForApp(WORKSPACE_APP_ID, { - path: PATHS.update, - absolute: true, - }), - id - ); - if (newUrl) { - window.location.href = newUrl; - } + switchWorkspace(coreStart, id); setLoading(false); }, - [coreStart.workspaces, coreStart.application] + [coreStart] ); const onCreateWorkspaceClick = () => {