Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

workspace dropdown list #9

Merged
merged 15 commits into from
Jun 16, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { WorkspaceDropdownList } from './workspace_dropdown_list';

export { WorkspaceDropdownList };
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState, useCallback, useMemo, useEffect } from 'react';

import { EuiButton, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import useObservable from 'react-use/lib/useObservable';
import { CoreStart, WorkspaceAttribute } from '../../../../../core/public';

type WorkspaceOption = EuiComboBoxOptionOption<WorkspaceAttribute>;

interface WorkspaceDropdownListProps {
coreStart: CoreStart;
onCreateWorkspace: () => void;
onSwitchWorkspace: (workspaceId: string) => Promise<void>;
}

function workspaceToOption(workspace: WorkspaceAttribute): WorkspaceOption {
return { label: workspace.name, key: workspace.id, value: workspace };
}

export function WorkspaceDropdownList(props: WorkspaceDropdownListProps) {
const { coreStart, onCreateWorkspace, onSwitchWorkspace } = props;
const workspaceList = useObservable(coreStart.workspaces.client.workspaceList$, []);
const currentWorkspaceId = useObservable(coreStart.workspaces.client.currentWorkspaceId$, '');

const [loading, setLoading] = useState(false);
const [workspaceOptions, setWorkspaceOptions] = useState([] as WorkspaceOption[]);

const currentWorkspaceOption = useMemo(() => {
Copy link
Collaborator

@SuZhou-Joe SuZhou-Joe Jun 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a currentWorkspace$ that can be used to get currentWorkspace in core.workspaces.client, recommend to use that.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will create another PR to change this

const workspace = workspaceList.find((item) => item.id === currentWorkspaceId);
if (!workspace) {
coreStart.notifications.toasts.addDanger(
`can not get current workspace of id [${currentWorkspaceId}]`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to wrap wordings by i18n.

);
return [workspaceToOption({ id: currentWorkspaceId, name: '' })];
}
return [workspaceToOption(workspace)];
}, [workspaceList, currentWorkspaceId, coreStart]);
const allWorkspaceOptions = useMemo(() => {
return workspaceList.map(workspaceToOption);
}, [workspaceList]);

const onSearchChange = useCallback(
(searchValue: string) => {
setWorkspaceOptions(allWorkspaceOptions.filter((item) => item.label.includes(searchValue)));
},
[allWorkspaceOptions]
);

const onChange = (workspaceOption: WorkspaceOption[]) => {
/** switch the workspace */
setLoading(true);
onSwitchWorkspace(workspaceOption[0].key!)
.catch((err) =>
coreStart.notifications.toasts.addDanger('some error happens in workspace service')
)
.finally(() => {
setLoading(false);
});
};

useEffect(() => {
onSearchChange('');
}, [onSearchChange]);

return (
<>
<EuiComboBox
async
options={workspaceOptions}
isLoading={loading}
onChange={onChange}
selectedOptions={currentWorkspaceOption}
singleSelection={{ asPlainText: true }}
onSearchChange={onSearchChange}
append={<EuiButton onClick={onCreateWorkspace}>Create workspace</EuiButton>}
/>
</>
);
}
32 changes: 32 additions & 0 deletions src/plugins/workspace/public/mount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import ReactDOM from 'react-dom';
import { CoreStart } from '../../../core/public';
import { WorkspaceDropdownList } from './containers/workspace_dropdown_list';

export const mountDropdownList = (core: CoreStart) => {
core.chrome.navControls.registerLeft({
order: 0,
mount: (element) => {
ReactDOM.render(
<WorkspaceDropdownList
coreStart={core}
onCreateWorkspace={() => alert('create')}
onSwitchWorkspace={async (id: string) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
alert(`switch to workspace ${id}`);
}}
// onSwitchWorkspace={(id: string) => alert(`switch to workspace ${id}`)}
/>,
element
);
return () => {
ReactDOM.unmountComponentAtNode(element);
};
},
});
};
2 changes: 2 additions & 0 deletions src/plugins/workspace/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '../../../core/public';
import { WORKSPACE_APP_ID, WORKSPACE_ID_IN_SESSION_STORAGE } from '../common/constants';
import { WORKSPACE_ID_QUERYSTRING_NAME } from '../../../core/public';
import { mountDropdownList } from './mount';

export class WorkspacesPlugin implements Plugin<{}, {}> {
private core?: CoreSetup;
Expand Down Expand Up @@ -100,6 +101,7 @@ export class WorkspacesPlugin implements Plugin<{}, {}> {
}

public start(core: CoreStart) {
mountDropdownList(core);
return {};
}
}