Skip to content

Commit

Permalink
feat(metadata-sidebar): add metadata empty state to metadata sidebar …
Browse files Browse the repository at this point in the history
…redesign (#3605)

* chore(content-sidebar): Temporarily remove files

while we be working with not yet publish internal library.
Will remove this commit after the library will become publicly
available on NPM and added to BUIE.

feat(metadata-sidebar): MetadataEmptyState

feat(metadata-sidebar): comment api to pass test

feat(metadata-sidebar): uncomment comments

feat(metadata-sidebar): add states

feat(metadata-sidebar): tests update

feat(metadata-sidebar): PR comments

feat(metadata-sidebar): delete git add . in showEditor

feat(metadata-sidebar): PR comments

feat(metadata-sidebar): storybook tests

feat(metadata-sidebar): update unit tests

feat(metadata-sidebar): pr comments

feat(metadata-sidebar): variables name changes

feat(metadata-sidebar): PR comments

feat(metadata-sidebar): PR comments

feat(metadata-sidebar): global token change  and status enum

feat(metadata-sidebar): global token update

feat(metadata-sidebar): global variables and enum upper case change

feat(metadata-sidebar): PR comments

feat(metadata-sidebar): styles import and title deletion

feat(metadata-sidebar): convert type to interface

* feat(metadata-sidebar): missing tests after rebase

---------

Co-authored-by: Dawid Jankowiak <jankowiak.dawid@gmail.com>
  • Loading branch information
karolinaru and jankowiakdawid committed Sep 6, 2024
1 parent 114506a commit 2bc7e8e
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/elements/content-sidebar/MetadataSidebarRedesign.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
border-left: 1px solid $gray-10;

.bcs-MetadataSidebarRedesign-content {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: $space-2;
background-color: $gray-02;
}
Expand Down
25 changes: 22 additions & 3 deletions src/elements/content-sidebar/MetadataSidebarRedesign.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as React from 'react';
import flow from 'lodash/flow';
import { FormattedMessage, useIntl } from 'react-intl';
import { InlineError, LoadingIndicator } from '@box/blueprint-web';
import { AddMetadataTemplateDropdown } from '@box/metadata-editor';
import { AddMetadataTemplateDropdown , MetadataEmptyState } from '@box/metadata-editor';

import API from '../../api';
import SidebarContent from './SidebarContent';
Expand All @@ -31,6 +31,7 @@ const MARK_NAME_JS_READY = `${ORIGIN_METADATA_SIDEBAR_REDESIGN}_${EVENT_JS_READY
mark(MARK_NAME_JS_READY);

export interface ExternalProps {
isBoxAiSuggestionsEnabled: boolean;
isFeatureEnabled: boolean;
}

Expand All @@ -53,12 +54,24 @@ export interface MetadataSidebarRedesignProps extends PropsWithoutContext, Error
api: API;
}

function MetadataSidebarRedesign({ api, elementId, fileId, onError, isFeatureEnabled }: MetadataSidebarRedesignProps) {
function MetadataSidebarRedesign({
api,
elementId,
fileId,
isBoxAiSuggestionsEnabled,
onError,
isFeatureEnabled,
}: MetadataSidebarRedesignProps) {
const { formatMessage } = useIntl();

const [selectedTemplates, setSelectedTemplates] = React.useState<Array<MetadataTemplate>>([]);

const { templates, errorMessage, status } = useSidebarMetadataFetcher(api, fileId, onError, isFeatureEnabled);
const { editors, file, templates, errorMessage, status } = useSidebarMetadataFetcher(
api,
fileId,
onError,
isFeatureEnabled,
);

const metadataDropdown = status === STATUS.SUCCESS && templates && (
<AddMetadataTemplateDropdown
Expand All @@ -76,6 +89,9 @@ function MetadataSidebarRedesign({ api, elementId, fileId, onError, isFeatureEna
</InlineError>
);

const showEditor = file && templates && editors;
const showEmptyState = showEditor && editors.length === 0;

return (
<SidebarContent
actions={metadataDropdown}
Expand All @@ -89,6 +105,9 @@ function MetadataSidebarRedesign({ api, elementId, fileId, onError, isFeatureEna
{status === STATUS.LOADING && (
<LoadingIndicator aria-label={formatMessage(messages.loading)} data-testid="loading" />
)}
{showEmptyState && (
<MetadataEmptyState level={'file'} isBoxAiSuggestionsFeatureEnabled={isBoxAiSuggestionsEnabled} />
)}
</div>
</SidebarContent>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('elements/content-sidebar/Metadata/MetadataSidebarRedesign', () => {
api: {},
fileId: 'test-file-id-1',
elementId: 'element-1',
isBoxAiSuggestionsEnabled: true,
isFeatureEnabled: true,
onError: jest.fn(),
} satisfies MetadataSidebarRedesignProps;
Expand All @@ -43,6 +44,7 @@ describe('elements/content-sidebar/Metadata/MetadataSidebarRedesign', () => {
beforeEach(() => {
mockUseSidebarMetadataFetcher.mockReturnValue({
templates: mockTemplates,
editors: [],
errorMessage: null,
status: STATUS.SUCCESS,
file: mockFile,
Expand Down Expand Up @@ -83,6 +85,7 @@ describe('elements/content-sidebar/Metadata/MetadataSidebarRedesign', () => {

test('should render metadata sidebar with error', async () => {
mockUseSidebarMetadataFetcher.mockReturnValue({
editors: [],
templates: [],
errorMessage: {
id: 'error',
Expand All @@ -101,6 +104,7 @@ describe('elements/content-sidebar/Metadata/MetadataSidebarRedesign', () => {

test('should render metadata sidebar with loading indicator', async () => {
mockUseSidebarMetadataFetcher.mockReturnValue({
editors: [],
templates: [],
errorMessage: null,
status: STATUS.LOADING,
Expand All @@ -113,4 +117,22 @@ describe('elements/content-sidebar/Metadata/MetadataSidebarRedesign', () => {
expect(screen.getByTestId('loading')).toBeInTheDocument();
expect(screen.getByRole('status', { name: 'Loading' })).toBeInTheDocument();
});

test('should correctly render empty state when AI feature is enabled', () => {
renderComponent();
expect(screen.getByRole('heading', { level: 2, name: 'Autofill Metadata with Box AI' })).toBeInTheDocument();
expect(
screen.getByText(
'Use the power of Box AI to quickly capture document metadata, with ever-increasing accuracy.',
),
).toBeInTheDocument();
});

test('should correctly render empty state when AI feature is disabled', () => {
renderComponent({ isBoxAiSuggestionsEnabled: false });
expect(screen.getByRole('heading', { level: 2, name: 'Add Metadata Templates' })).toBeInTheDocument();
expect(
screen.getByText('Add Metadata to your file to support business operations, workflows, and more!'),
).toBeInTheDocument();
});
});
13 changes: 9 additions & 4 deletions src/elements/content-sidebar/hooks/useSidebarMetadataFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { type MessageDescriptor } from 'react-intl';
import API from '../../../api';
import { type ElementsXhrError } from '../../../common/types/api';
import { isUserCorrectableError } from '../../../utils/error';
import { FIELD_IS_EXTERNALLY_OWNED, FIELD_PERMISSIONS, FIELD_PERMISSIONS_CAN_UPLOAD } from '../../../constants';
import { FIELD_IS_EXTERNALLY_OWNED, FIELD_PERMISSIONS, FIELD_PERMISSIONS_CAN_UPLOAD, IS_ERROR_DISPLAYED} from '../../../constants';

import messages from '../../common/messages';

Expand All @@ -19,9 +19,10 @@ export enum STATUS {
SUCCESS = 'success',
}
interface DataFetcher {
status: STATUS;
editors: Array<MetadataEditor>;
file: BoxItem | null;
errorMessage: MessageDescriptor | null;
status: STATUS;
templates: Array<MetadataTemplate>;
}

Expand All @@ -35,6 +36,7 @@ function useSidebarMetadataFetcher(
const [file, setFile] = React.useState<BoxItem>(null);
const [templates, setTemplates] = React.useState(null);
const [errorMessage, setErrorMessage] = React.useState<MessageDescriptor | null>(null);
const [editors, setEditors] = React.useState<Array<MetadataEditor>>([]);

const onApiError = React.useCallback(
(error: ElementsXhrError, code: string, message: MessageDescriptor) => {
Expand All @@ -51,7 +53,8 @@ function useSidebarMetadataFetcher(
);

const fetchMetadataSuccessCallback = React.useCallback(
({ templates: fetchedTemplates }: { editors: Array<MetadataEditor>; templates: Array<MetadataTemplate> }) => {
({ editors: fetchedEditors, templates: fetchedTemplates }: { editors: Array<MetadataEditor>; templates: Array<MetadataTemplate> }) => {
setEditors(fetchedEditors);
setErrorMessage(null);
setStatus(STATUS.SUCCESS);
setTemplates(fetchedTemplates);
Expand All @@ -61,6 +64,7 @@ function useSidebarMetadataFetcher(

const fetchMetadataErrorCallback = React.useCallback(
(e: ElementsXhrError, code: string) => {
setEditors(null);
setTemplates(null);
onApiError(e, code, messages.sidebarMetadataFetchingErrorContent);
},
Expand Down Expand Up @@ -115,9 +119,10 @@ function useSidebarMetadataFetcher(
}, [api, fetchFileErrorCallback, fetchFileSuccessCallback, fileId, status]);

return {
status,
file,
editors,
errorMessage,
status,
templates,
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { type StoryObj } from '@storybook/react';
import { fn } from '@storybook/test';
import { type ComponentProps } from 'react';
import React, { type ComponentProps } from 'react';
import MetadataSidebarRedesign from '../MetadataSidebarRedesign';
import ContentSidebar from '../ContentSidebar';

const fileIdWithMetadata = global.FILE_ID;
const fileIdWithNoMetadata = '416047501580';
const mockFeatures = {
'metadata.redesign.enabled': true,
};
Expand All @@ -15,6 +16,7 @@ const mockLogger = {
};

const defaultMetadataSidebarProps: ComponentProps<typeof MetadataSidebarRedesign> = {
isBoxAiSuggestionsEnabled: true,
isFeatureEnabled: true,
onError: fn,
};
Expand All @@ -30,6 +32,27 @@ export default {
token: global.TOKEN,
metadataSidebarProps: defaultMetadataSidebarProps,
},
render: args => {
return <ContentSidebar {...args} />;
},
};

export const AddTemplateDropdownMenu: StoryObj<typeof MetadataSidebarRedesign> = {};

export const EmptyStateWithBoxAiEnabled: StoryObj<typeof MetadataSidebarRedesign> = {
args: {
fileId: fileIdWithNoMetadata,
metadataSidebarProps: {
...defaultMetadataSidebarProps,
},
},};

export const EmptyStateWithBoxAiDisabled: StoryObj<typeof MetadataSidebarRedesign> = {
args: {
fileId: fileIdWithNoMetadata,
metadataSidebarProps: {
...defaultMetadataSidebarProps,
isBoxAiSuggestionsEnabled: false,
},
},
};

0 comments on commit 2bc7e8e

Please sign in to comment.