From ba4403642849100f23e03160615d502c5c45590b Mon Sep 17 00:00:00 2001 From: Qxisylolo Date: Sat, 12 Oct 2024 12:10:05 +0800 Subject: [PATCH 1/6] fix/workspace_selector_style_alignment, sortByRecentVisitedAndAlphabetical Signed-off-by: Qxisylolo --- .../workspace_picker_content.tsx | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx index 2bbb2c613173..2537318c85dd 100644 --- a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx +++ b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx @@ -27,18 +27,6 @@ import { WorkspaceUseCase } from '../../types'; import { validateWorkspaceColor } from '../../../common/utils'; import { getFirstUseCaseOfFeatureConfigs, getUseCaseUrl } from '../../utils'; -function sortBy(getkey: (item: T) => number | undefined) { - return (a: T, b: T): number => { - const aValue = getkey(a); - const bValue = getkey(b); - - if (aValue === undefined) return 1; - if (bValue === undefined) return -1; - - return bValue - aValue; - }; -} - const searchFieldPlaceholder = i18n.translate('workspace.menu.search.placeholder', { defaultMessage: 'Search workspace name', }); @@ -57,6 +45,21 @@ interface Props { isInTwoLines?: boolean; } +const sortByRecentVisitedAndAlphabetical = ( + ws1: UpdatedWorkspaceObject, + ws2: UpdatedWorkspaceObject +) => { + // First, sort by accessTimeStamp in descending order (if both have timestamps) + if (ws1?.accessTimeStamp && ws2?.accessTimeStamp) { + return ws2.accessTimeStamp - ws1.accessTimeStamp; + } + // If one has a timestamp and the other does not, prioritize the one with the timestamp + if (ws1.accessTimeStamp) return -1; + if (ws2.accessTimeStamp) return 1; + // If neither has a timestamp, sort alphabetically by name + return ws1.name.localeCompare(ws2.name); +}; + export const WorkspacePickerContent = ({ coreStart, registeredUseCases$, @@ -72,18 +75,16 @@ export const WorkspacePickerContent = ({ const recentWorkspaces = recentWorkspaceManager.getRecentWorkspaces(); const updatedList = workspaceList.map((workspace) => { const recentWorkspace = recentWorkspaces.find((recent) => recent.id === workspace.id); - - if (recentWorkspace) { - return { - ...workspace, - accessTimeStamp: recentWorkspace.timestamp, - accessTime: `viewed ${moment(recentWorkspace.timestamp).fromNow()}`, - }; - } - return workspace as UpdatedWorkspaceObject; + return { + ...workspace, + accessTimeStamp: recentWorkspace?.timestamp, + accessTime: recentWorkspace + ? `Viewed ${moment(recentWorkspace.timestamp).fromNow()}` + : `Not visited recently`, + }; }); - return updatedList.sort(sortBy((workspace) => workspace.accessTimeStamp)); + return updatedList.sort(sortByRecentVisitedAndAlphabetical); }, [workspaceList]); const queryFromList = ({ list, query }: { list: UpdatedWorkspaceObject[]; query: string }) => { From 8461e6b221c51615998f09ffb1c79df045831cfb Mon Sep 17 00:00:00 2001 From: Qxisylolo Date: Tue, 15 Oct 2024 15:02:44 +0800 Subject: [PATCH 2/6] align styles, typo Signed-off-by: Qxisylolo --- .../workspace_menu/workspace_menu.test.tsx | 2 +- .../workspace_selector.scss | 35 +++++++++++++ .../workspace_selector.test.tsx | 16 +++--- .../workspace_selector/workspace_selector.tsx | 49 +++++++------------ 4 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/plugins/workspace/public/components/workspace_menu/workspace_menu.test.tsx b/src/plugins/workspace/public/components/workspace_menu/workspace_menu.test.tsx index 71a7632d6f08..f70d5efb23a0 100644 --- a/src/plugins/workspace/public/components/workspace_menu/workspace_menu.test.tsx +++ b/src/plugins/workspace/public/components/workspace_menu/workspace_menu.test.tsx @@ -83,7 +83,7 @@ describe('', () => { const selectButton = screen.getByTestId('workspace-select-button'); fireEvent.click(selectButton); - expect(screen.getByText(`viewed ${moment(1234567890).fromNow()}`)).toBeInTheDocument(); + expect(screen.getByText(`Viewed ${moment(1234567890).fromNow()}`)).toBeInTheDocument(); }); it('should be able to display empty state when the workspace list is empty', () => { diff --git a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss index 685d823b30c6..b208ae3b5c56 100644 --- a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss +++ b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss @@ -7,3 +7,38 @@ transition: none !important; transform: none !important; } + +.workspaceSelectorPopoverButtonContainer { + position: relative; + background-color: $euiHeaderBackgroundColor; + border: 1px solid $euiColorMediumShade; + border-radius: 4px; + + &::before { + content: attr(data-label); + position: absolute; + top: -0.2rem; + left: $euiSizeS; + font-size: 0.5rem; + line-height: 0.4rem; + padding: 0 $euiSizeXS; + + /* Trying to hide the button's border: + * The background should start 1px (for the border) higher than at the edge of the button. + * When the top is 0.2rem, the gradient should start at 0.2rem - 1. + * The value is rounded down to the nearest pixel to avoid partial coverage of the border + * we are trying to hide. + */ + --dsm-popover-label-start: round(down, calc(0.2rem - 1px), 1px); + + background: + linear-gradient( + to bottom, + transparent var(--dsm-popover-label-start), + $euiHeaderBackgroundColor var(--dsm-popover-label-start) + ); + color: $euiTextColor; + z-index: 0; + text-transform: uppercase; + } +} diff --git a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx index 5b8b05a6506a..efd68a704548 100644 --- a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx +++ b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx @@ -68,6 +68,7 @@ describe('', () => { expect(screen.getByTestId('workspace-selector-current-title')).toBeInTheDocument(); expect(screen.getByTestId('workspace-selector-current-name')).toBeInTheDocument(); }); + it('should display a list of workspaces in the dropdown', () => { jest .spyOn(recentWorkspaceManager, 'getRecentWorkspaces') @@ -82,11 +83,11 @@ describe('', () => { const selectButton = screen.getByTestId('workspace-selector-button'); fireEvent.click(selectButton); - expect(screen.getByTestId('workspace-menu-item-workspace-1')).toBeInTheDocument(); - expect(screen.getByTestId('workspace-menu-item-workspace-2')).toBeInTheDocument(); + expect(screen.getByText('workspace 1')).toBeInTheDocument(); + expect(screen.getByText('workspace 2')).toBeInTheDocument(); }); - it('should display viewed xx ago for recent workspaces', () => { + it('should display viewed xx ago for recent workspaces, and Not visited recently for never-visited workspace', () => { jest .spyOn(recentWorkspaceManager, 'getRecentWorkspaces') .mockReturnValue([{ id: 'workspace-1', timestamp: 1234567890 }]); @@ -95,13 +96,12 @@ describe('', () => { { id: 'workspace-1', name: 'workspace 1', features: [] }, { id: 'workspace-2', name: 'workspace 2', features: [] }, ]); - render(); - const selectButton = screen.getByTestId('workspace-selector-button'); fireEvent.click(selectButton); - expect(screen.getByText(`viewed ${moment(1234567890).fromNow()}`)).toBeInTheDocument(); + expect(screen.getByText(`Viewed ${moment(1234567890).fromNow()}`)).toBeInTheDocument(); + expect(screen.getByText('Not visited recently')).toBeInTheDocument(); }); it('should be able to display empty state when the workspace list is empty', () => { @@ -127,8 +127,8 @@ describe('', () => { const searchInput = screen.getByRole('searchbox'); fireEvent.change(searchInput, { target: { value: 'works' } }); - expect(screen.getByTestId('workspace-menu-item-workspace-1')).toBeInTheDocument(); - expect(screen.queryByText('workspace-menu-item-workspace-1')).not.toBeInTheDocument(); + expect(screen.getByText('workspace 1')).toBeInTheDocument(); + expect(screen.queryByText('test 2')).not.toBeInTheDocument(); }); it('should be able to display empty state when seach is not found', () => { diff --git a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.tsx b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.tsx index f0c0243703f5..5374f3f2aea6 100644 --- a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.tsx +++ b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.tsx @@ -64,36 +64,21 @@ export const WorkspaceSelector = ({ coreStart, registeredUseCases$ }: Props) => const closePopover = () => { setPopover(false); }; + const button = currentWorkspace ? ( - - + - - {i18n.translate('workspace.left.nav.selector.label', { - defaultMessage: 'WORKSPACE', - })} - - - - + - + color={getValidWorkspaceColor(currentWorkspace.color)} /> - - - + + +

{currentWorkspace.name}

- +
-
+ ) : ( Select a Workspace ); From 341428efa1d4b508544977889ea742582f7cf99a Mon Sep 17 00:00:00 2001 From: Qxisylolo Date: Tue, 15 Oct 2024 18:06:49 +0800 Subject: [PATCH 3/6] resolve comment Signed-off-by: Qxisylolo --- .../workspace_picker_content.tsx | 8 +++---- .../workspace_selector.scss | 24 +++++++------------ 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx index 2537318c85dd..0276181bc352 100644 --- a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx +++ b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx @@ -36,7 +36,7 @@ const getValidWorkspaceColor = (color?: string) => interface UpdatedWorkspaceObject extends WorkspaceObject { accessTimeStamp?: number; - accessTime?: string; + accessTimeDescription?: string; } interface Props { coreStart: CoreStart; @@ -78,7 +78,7 @@ export const WorkspacePickerContent = ({ return { ...workspace, accessTimeStamp: recentWorkspace?.timestamp, - accessTime: recentWorkspace + accessTimeDescription: recentWorkspace ? `Viewed ${moment(recentWorkspace.timestamp).fromNow()}` : `Not visited recently`, }; @@ -187,7 +187,7 @@ export const WorkspacePickerContent = ({ - {workspace.accessTime} + {workspace.accessTimeDescription} @@ -212,7 +212,7 @@ export const WorkspacePickerContent = ({ - {workspace.accessTime} + {workspace.accessTimeDescription} diff --git a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss index b208ae3b5c56..9ac8ef1fa86e 100644 --- a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss +++ b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.scss @@ -8,9 +8,13 @@ transform: none !important; } +/* Trying to show the border label: + * The following style is referenced from data souce selector + * see file src/plugins/data_source_management/public/components/popover_button/popover_button.scss +*/ .workspaceSelectorPopoverButtonContainer { position: relative; - background-color: $euiHeaderBackgroundColor; + background-color: $euiSideNavBackgroundColor; border: 1px solid $euiColorMediumShade; border-radius: 4px; @@ -19,24 +23,14 @@ position: absolute; top: -0.2rem; left: $euiSizeS; - font-size: 0.5rem; + font-size: 0.4rem; line-height: 0.4rem; padding: 0 $euiSizeXS; - /* Trying to hide the button's border: - * The background should start 1px (for the border) higher than at the edge of the button. - * When the top is 0.2rem, the gradient should start at 0.2rem - 1. - * The value is rounded down to the nearest pixel to avoid partial coverage of the border - * we are trying to hide. + /* update + * Delete the line-gradient and set the background color to euiSideNavBackgroundColor directly */ - --dsm-popover-label-start: round(down, calc(0.2rem - 1px), 1px); - - background: - linear-gradient( - to bottom, - transparent var(--dsm-popover-label-start), - $euiHeaderBackgroundColor var(--dsm-popover-label-start) - ); + background-color: $euiSideNavBackgroundColor; color: $euiTextColor; z-index: 0; text-transform: uppercase; From b4b35cdc471292e1561e66e19f270fae14fa079f Mon Sep 17 00:00:00 2001 From: Qxisylolo Date: Wed, 16 Oct 2024 16:22:02 +0800 Subject: [PATCH 4/6] add i18n Signed-off-by: Qxisylolo --- .../workspace_picker_content/workspace_picker_content.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx index 0276181bc352..ec6b4f75a9c6 100644 --- a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx +++ b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx @@ -79,8 +79,12 @@ export const WorkspacePickerContent = ({ ...workspace, accessTimeStamp: recentWorkspace?.timestamp, accessTimeDescription: recentWorkspace - ? `Viewed ${moment(recentWorkspace.timestamp).fromNow()}` - : `Not visited recently`, + ? i18n.translate('workspace.picker.accessTime.description', { + defaultMessage: `Viewed ${moment(recentWorkspace.timestamp).fromNow()}`, + }) + : i18n.translate('workspace.picker.accessTime.not.visited', { + defaultMessage: `Not visited recently`, + }), }; }); From 32a78cde12665a09faf5567bde63b4c47f5dbc4a Mon Sep 17 00:00:00 2001 From: Qxisylolo Date: Fri, 18 Oct 2024 10:46:53 +0800 Subject: [PATCH 5/6] fix i18n in test Signed-off-by: Qxisylolo --- .../workspace_picker_content.tsx | 7 +++++-- .../workspace_selector/workspace_selector.test.tsx | 11 +++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx index ec6b4f75a9c6..cf8ce3324233 100644 --- a/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx +++ b/src/plugins/workspace/public/components/workspace_picker_content/workspace_picker_content.tsx @@ -80,10 +80,13 @@ export const WorkspacePickerContent = ({ accessTimeStamp: recentWorkspace?.timestamp, accessTimeDescription: recentWorkspace ? i18n.translate('workspace.picker.accessTime.description', { - defaultMessage: `Viewed ${moment(recentWorkspace.timestamp).fromNow()}`, + defaultMessage: 'Viewed {timeLabel}', + values: { + timeLabel: moment(recentWorkspace.timestamp).fromNow(), + }, }) : i18n.translate('workspace.picker.accessTime.not.visited', { - defaultMessage: `Not visited recently`, + defaultMessage: 'Not visited recently', }), }; }); diff --git a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx index efd68a704548..6f0b4136698d 100644 --- a/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx +++ b/src/plugins/workspace/public/components/workspace_selector/workspace_selector.test.tsx @@ -10,13 +10,8 @@ import { WorkspaceSelector } from './workspace_selector'; import { coreMock } from '../../../../../core/public/mocks'; import { CoreStart, DEFAULT_NAV_GROUPS, WorkspaceObject } from '../../../../../core/public'; import { BehaviorSubject } from 'rxjs'; -import { IntlProvider } from 'react-intl'; import { recentWorkspaceManager } from '../../recent_workspace_manager'; -jest.mock('@osd/i18n', () => ({ - i18n: { - translate: (id: string, { defaultMessage }: { defaultMessage: string }) => defaultMessage, - }, -})); +import { I18nProvider } from '@osd/i18n/react'; describe('', () => { let coreStartMock: CoreStart; const navigateToApp = jest.fn(); @@ -52,9 +47,9 @@ describe('', () => { const WorkspaceSelectorCreatorComponent = () => { return ( - + - + ); }; From 7acbda4e405cd44c42ed2246a2dfde88c7d32c58 Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 02:50:55 +0000 Subject: [PATCH 6/6] Changeset file for PR #8592 created/updated --- changelogs/fragments/8592.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/8592.yml diff --git a/changelogs/fragments/8592.yml b/changelogs/fragments/8592.yml new file mode 100644 index 000000000000..fd4fae271865 --- /dev/null +++ b/changelogs/fragments/8592.yml @@ -0,0 +1,2 @@ +fix: +- Workspace selector style alignment ([#8592](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8592)) \ No newline at end of file