Skip to content

Commit

Permalink
[WorkSpace] Refractor homepage assets list section (#7702)
Browse files Browse the repository at this point in the history
* refractor assets section

Signed-off-by: Qxisylolo <[email protected]>

* refractor assets section

Signed-off-by: Qxisylolo <[email protected]>

* refractor assets section_1

Signed-off-by: Qxisylolo <[email protected]>

* Changeset file for PR #7702 created/updated

* add new test

Signed-off-by: Qxisylolo <[email protected]>

* delete border

Signed-off-by: Qxisylolo <[email protected]>

---------

Signed-off-by: Qxisylolo <[email protected]>
Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
  • Loading branch information
Qxisylolo and opensearch-changeset-bot[bot] authored Aug 14, 2024
1 parent a360b38 commit 765527a
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 62 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/7702.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Refractor the homepage assets list section ([#7702](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7702))
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { RecentWork } from './recent_work';
import { coreMock } from '../../../../core/public/mocks';
import { ChromeRecentlyAccessedHistoryItem } from 'opensearch-dashboards/public';
import { SavedObjectWithMetadata } from '../types';
import { APP_ID } from '../plugin';

const mockedRecentItems: ChromeRecentlyAccessedHistoryItem[] = [
{
Expand Down Expand Up @@ -60,7 +61,7 @@ const getStartMockForRecentWork = () => {
describe('<RecentWork />', () => {
it('render with emty recent work', async () => {
const { findByText } = render(<RecentWork core={getStartMockForRecentWork()} />);
await findByText('No recent work');
await findByText('No assets found');
});

it('render with recent works', async () => {
Expand All @@ -85,14 +86,27 @@ describe('<RecentWork />', () => {
const allCards = await findAllByTestId('recentlyCard');
expect(allCards.length).toBe(2);
expect(allCards[0].querySelector('.euiCard__titleAnchor')?.textContent).toEqual(
mockedRecentItems[0].label
mockedRecentItems[0].label.charAt(0).toUpperCase() + mockedRecentItems[0].label.slice(1)
);

// click the filter button
fireEvent.click(getByTestId('filterButton-recently%20updated'));
fireEvent.click(getByTestId('filterButton-Recently%20updated'));
const allCardsAfterSort = await findAllByTestId('recentlyCard');
expect(allCardsAfterSort[0].querySelector('.euiCard__titleAnchor')?.textContent).toEqual(
mockedRecentItems[1].label
mockedRecentItems[1].label.charAt(0).toUpperCase() + mockedRecentItems[1].label.slice(1)
);
});

it('should be able to show view all button', () => {
const { getByText } = render(<RecentWork core={getStartMockForRecentWork()} />);
expect(getByText('View all')).toBeInTheDocument();
});

it('shoule be able to be linked to the expected page when clicking View all button', () => {
const coreStartMock = getStartMockForRecentWork();
const { getByText } = render(<RecentWork core={coreStartMock} />);
const mockedViewAllButton = getByText('View all');
fireEvent.click(mockedViewAllButton);
expect(coreStartMock.application.navigateToApp).toHaveBeenCalledWith(APP_ID);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import {
EuiFlexItem,
EuiCard,
EuiPanel,
EuiSpacer,
EuiFlexGrid,
EuiFlexGroup,
EuiTitle,
EuiFilterGroup,
EuiFilterButton,
EuiComboBox,
EuiIcon,
EuiLink,
EuiEmptyPrompt,
EuiToolTip,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { i18n } from '@osd/i18n';
import {
Expand All @@ -26,18 +30,19 @@ import {
} from 'opensearch-dashboards/public';
import { useObservable } from 'react-use';
import { SavedObjectWithMetadata } from 'src/plugins/saved_objects_management/common';
import { APP_ID } from '../plugin';
import { createRecentNavLink } from '../../../../core/public';

const allOption = i18n.translate('savedObjectsManagement.recentWorkSection.all.items', {
defaultMessage: 'all items',
defaultMessage: 'All items',
});

const recentlyViewed = i18n.translate('savedObjectsManagement.recentWorkSection.recentlyViewed', {
defaultMessage: 'recently viewed',
defaultMessage: 'Recently viewed',
});

const recentlyUpdated = i18n.translate('savedObjectsManagement.recentWorkSection.recentlyUpdated', {
defaultMessage: 'recently updated',
defaultMessage: 'Recently updated',
});

const sortKeyMap = {
Expand Down Expand Up @@ -102,14 +107,18 @@ export const RecentWork = (props: { core: CoreStart; workspaceEnabled?: boolean
const options: string[] = [allOption];
detailedSavedObjects
.filter((item) => !item.error)
.forEach((recentAccessItem: ChromeRecentlyAccessedHistoryItem) => {
if (recentAccessItem.meta?.type && options.indexOf(recentAccessItem.meta.type) === -1) {
options.push(recentAccessItem.meta.type);
.forEach((recentAccessItem) => {
if (recentAccessItem?.type && options.indexOf(recentAccessItem?.type) === -1) {
options.push(recentAccessItem?.type);
}
});
return options.map((option: string) => ({ label: option, value: option }));
}, [detailedSavedObjects]);

const capitalTheFirstLetter = function (recentAccessItem: DetailedRecentlyAccessedItem) {
return recentAccessItem.type.charAt(0).toUpperCase() + recentAccessItem.type.slice(1);
};

const itemsForDisplay = useMemo(() => {
const sortedResult = [...detailedSavedObjects]
.filter((item) => !item.error)
Expand Down Expand Up @@ -156,22 +165,39 @@ export const RecentWork = (props: { core: CoreStart; workspaceEnabled?: boolean
<EuiPanel>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<EuiTitle>
<h5>
{i18n.translate('savedObjectsManagement.recentWorkSection.title', {
defaultMessage: 'Assets',
})}
</h5>
</EuiTitle>
<EuiFlexGroup justifyContent="flexStart" alignItems="center" gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiTitle>
<h3>
{i18n.translate('savedObjectsManagement.recentWorkSection.title', {
defaultMessage: 'Assets',
})}
</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip
display="inlineBlock"
position="right"
content={i18n.translate('savedObjectsManagement.recentWorkSection.assetsInfo', {
defaultMessage:
'Dashboards, visualizations, saved queries, and other assets within your Worksapces.',
})}
data-test-subj="assetsTooltip"
>
<EuiIcon type="iInCircle" />
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup>
<EuiFlexItem>
<EuiFilterGroup>
{[recentlyViewed, recentlyUpdated].map((item) => (
<EuiFilterButton
hasActiveFilters={selectedSort === item}
key={item}
hasActiveFilters={item === selectedSort}
onClick={() => setSelectedSort(item)}
data-test-subj={`filterButton-${encodeURIComponent(item)}`}
>
Expand Down Expand Up @@ -208,47 +234,80 @@ export const RecentWork = (props: { core: CoreStart; workspaceEnabled?: boolean
core.http.basePath,
core.application.navigateToUrl
);

content = (
<EuiCard
title={recentAccessItem.label}
titleSize="xs"
title={
<EuiFlexGroup justifyContent="flexStart" alignItems="center" gutterSize="none">
<EuiFlexItem grow={false}>
<EuiIcon
style={{ marginRight: widthForRightMargin }}
type={recentAccessItem.meta.icon || 'apps'}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs" color="subdued">
{capitalTheFirstLetter(recentAccessItem)}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
}
data-test-subj="recentlyCard"
description=""
description={<h3>{recentAccessItem.label}</h3>}
textAlign="left"
href={recentNavLink.href}
footer={
<>
<div>
<EuiIcon
style={{ marginRight: widthForRightMargin }}
type={recentAccessItem.meta.icon || 'apps'}
/>
{recentAccessItem.type}
</div>
<EuiSpacer size="s" />
<div>
{selectedSort === recentlyViewed
? i18n.translate('savedObjectsManagement.recentWorkSection.viewedAt', {
defaultMessage: 'Viewed',
})
: i18n.translate('savedObjectsManagement.recentWorkSection.updatedAt', {
defaultMessage: 'Updated',
})}
:{' '}
<b>
{selectedSort === recentlyViewed
? moment(recentAccessItem?.lastAccessedTime).fromNow()
: moment(recentAccessItem?.updatedAt).fromNow()}
</b>
</div>
{workspaceEnabled && (
<div>
{i18n.translate('savedObjectsManagement.recentWorkSection.workspace', {
defaultMessage: 'Workspace',
})}
: <b>{recentAccessItem.workspaceName || 'N/A'}</b>
</div>
)}
<EuiFlexGrid columns={2} gutterSize="s">
<EuiFlexItem grow={false}>
<EuiText size="xs" color="default">
{selectedSort === recentlyViewed
? i18n.translate(
'savedObjectsManagement.recentWorkSection.viewedAt',
{
defaultMessage: 'Viewed',
}
)
: i18n.translate(
'savedObjectsManagement.recentWorkSection.updatedAt',
{
defaultMessage: 'Updated',
}
)}
:{' '}
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={1} style={{ textAlign: 'right' }}>
<EuiText size="xs" color="default">
<b>
{selectedSort === recentlyViewed
? moment(recentAccessItem?.lastAccessedTime).fromNow()
: moment(recentAccessItem?.updatedAt).fromNow()}
</b>
</EuiText>
</EuiFlexItem>

{workspaceEnabled && (
<>
<EuiFlexItem grow={false}>
<EuiText size="xs" color="default">
{i18n.translate(
'savedObjectsManagement.recentWorkSection.workspace',
{
defaultMessage: 'Workspace',
}
)}
:
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={1} style={{ textAlign: 'right' }}>
<EuiText size="xs" color="default">
<b>{recentAccessItem.workspaceName || 'N/A'} </b>
</EuiText>
</EuiFlexItem>
</>
)}
</EuiFlexGrid>
</>
}
onClick={recentNavLink.onClick}
Expand All @@ -262,15 +321,27 @@ export const RecentWork = (props: { core: CoreStart; workspaceEnabled?: boolean
</EuiFlexGroup>
) : (
<EuiEmptyPrompt
icon={<EuiIcon size="l" type="layers" />}
title={
<h2>
{i18n.translate('savedObjectsManagement.recentWorkSection.empty.title', {
defaultMessage: 'No recent work',
defaultMessage: 'No assets found',
})}
</h2>
}
body={i18n.translate('savedObjectsManagement.recentWorkSection.empty.body', {
defaultMessage: "Assets you've recently viewed or updated will appear here.",
})}
/>
)}
<EuiSpacer size="m" />
<EuiLink target="_blank" onClick={() => core.application.navigateToApp(APP_ID)}>
<EuiText size="s" className="eui-displayInline">
{i18n.translate('home.list.card.view_all', {
defaultMessage: 'View all',
})}
</EuiText>
</EuiLink>
</EuiPanel>
);
};
18 changes: 10 additions & 8 deletions src/plugins/saved_objects_management/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ import { RecentWork } from './management_section/recent_work';
import { HOME_CONTENT_AREAS } from '../../../plugins/home/public';
import { getScopedBreadcrumbs } from '../../opensearch_dashboards_react/public';

export const APP_ID = 'objects';

export interface SavedObjectsManagementPluginSetup {
actions: SavedObjectsManagementActionServiceSetup;
columns: SavedObjectsManagementColumnServiceSetup;
Expand Down Expand Up @@ -141,7 +143,7 @@ export class SavedObjectsManagementPlugin

const opensearchDashboardsSection = management.sections.section.opensearchDashboards;
opensearchDashboardsSection.registerApp({
id: 'objects',
id: APP_ID,
title: i18n.translate('savedObjectsManagement.managementSectionLabel', {
defaultMessage: 'Saved objects',
}),
Expand All @@ -160,7 +162,7 @@ export class SavedObjectsManagementPlugin

if (core.chrome.navGroup.getNavGroupEnabled()) {
core.application.register({
id: 'objects',
id: APP_ID,
title: i18n.translate('savedObjectsManagement.assets.label', {
defaultMessage: 'Assets',
}),
Expand All @@ -187,46 +189,46 @@ export class SavedObjectsManagementPlugin

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.settingsAndSetup, [
{
id: 'objects',
id: APP_ID,
order: 300,
},
]);

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.observability, [
{
id: 'objects',
id: APP_ID,
category: DEFAULT_APP_CATEGORIES.manage,
order: 300,
},
]);

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.search, [
{
id: 'objects',
id: APP_ID,
category: DEFAULT_APP_CATEGORIES.manage,
order: 300,
},
]);

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS['security-analytics'], [
{
id: 'objects',
id: APP_ID,
category: DEFAULT_APP_CATEGORIES.manage,
order: 300,
},
]);

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.essentials, [
{
id: 'objects',
id: APP_ID,
category: DEFAULT_APP_CATEGORIES.manage,
order: 300,
},
]);

core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [
{
id: 'objects',
id: APP_ID,
category: DEFAULT_APP_CATEGORIES.manage,
order: 300,
},
Expand Down

0 comments on commit 765527a

Please sign in to comment.