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

UI to manage users/permissions for the content libraries [FC-0062] #1362

Merged
merged 10 commits into from
Oct 15, 2024
24 changes: 13 additions & 11 deletions src/content-tags-drawer/ContentTagsCollapsible.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -393,16 +393,18 @@ const ContentTagsCollapsible = ({
&& (
<div className="mb-3" key={taxonomyId}>
<p className="text-gray-500">{intl.formatMessage(messages.collapsibleNoTagsAddedText)}
<Button
tabIndex={0}
size="inline"
ref={selectInlineEditModeRef}
variant="link"
className="text-info-500 add-tags-button"
onClick={toEditMode}
>
{ intl.formatMessage(messages.collapsibleAddStagedTagsButtonText) }
</Button>
{canTagObject && (
<Button
tabIndex={0}
size="inline"
ref={selectInlineEditModeRef}
variant="link"
className="text-info-500 add-tags-button"
onClick={toEditMode}
>
{ intl.formatMessage(messages.collapsibleAddStagedTagsButtonText) }
</Button>
)}
</p>
</div>
)}
Expand All @@ -418,7 +420,7 @@ const ContentTagsCollapsible = ({
)}

<div className="d-flex taxonomy-tags-selector-menu">
{isEditMode && canTagObject && (
{isEditMode && (
<Select
onBlur={handleOnBlur}
styles={{
Expand Down
26 changes: 25 additions & 1 deletion src/content-tags-drawer/ContentTagsCollapsible.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,30 @@ describe('<ContentTagsCollapsible />', () => {
expect(data.toEditMode).toHaveBeenCalledTimes(1);
});

it('should not render "add tags" button when expanded and not allowed to tag objects', async () => {
await getComponent({
...data,
isEditMode: false,
taxonomyAndTagsData: {
id: 123,
name: 'Taxonomy 1',
canTagObject: false,
contentTags: [],
},
});

const expandToggle = screen.getByRole('button', {
name: /taxonomy 1/i,
});
fireEvent.click(expandToggle);
expect(screen.queryByText(/no tags added yet/i)).toBeInTheDocument();

const addTags = screen.queryByRole('button', {
name: /add tags/i,
});
expect(addTags).not.toBeInTheDocument();
});

it('should call `openCollapsible` when click in the collapsible', async () => {
await getComponent({
...data,
Expand Down Expand Up @@ -396,7 +420,7 @@ describe('<ContentTagsCollapsible />', () => {
expect(data.removeGlobalStagedContentTag).toHaveBeenCalledWith(taxonomyId, 'Tag 3');
});

it('should call `addRemovedContentTag` when a feched tag is deleted', async () => {
it('should call `addRemovedContentTag` when a fetched tag is deleted', async () => {
await getComponent();

const tag = screen.getByText(/tag 2/i);
Expand Down
6 changes: 3 additions & 3 deletions src/content-tags-drawer/ContentTagsCollapsibleHelper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const useContentTagsCollapsibleHelper = (
// State to keep track of the staged tags (and along with ancestors) that should be removed
const [stagedTagsToRemove, setStagedTagsToRemove] = React.useState(/** @type string[] */([]));

// State to keep track of the global tags (stagged and feched) that should be removed
// State to keep track of the global tags (staged and fetched) that should be removed
const [globalTagsToRemove, setGlobalTagsToRemove] = React.useState(/** @type string[] */([]));

// Handles the removal of staged content tags based on what was removed
Expand All @@ -140,7 +140,7 @@ const useContentTagsCollapsibleHelper = (
// A new tag has been removed
removeGlobalStagedContentTag(id, tag);
} else if (contentTags.some(t => t.value === tag)) {
// A feched tag has been removed
// A fetched tag has been removed
addRemovedContentTag(id, tag);
}
});
Expand All @@ -157,7 +157,7 @@ const useContentTagsCollapsibleHelper = (
explicitStaged.forEach((tag) => {
if (globalStagedRemovedContentTags[id]
&& globalStagedRemovedContentTags[id].includes(tag.value)) {
// A feched tag that has been removed has been added again
// A fetched tag that has been removed has been added again
deleteRemovedContentTag(id, tag.value);
} else {
// New tag added
Expand Down
29 changes: 26 additions & 3 deletions src/content-tags-drawer/ContentTagsDrawer.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jest.mock('react-router-dom', () => ({
const renderDrawer = (contentId, drawerParams = {}) => (
render(
<ContentTagsDrawerSheetContext.Provider value={drawerParams}>
<ContentTagsDrawer {...drawerParams} />
<ContentTagsDrawer canTagObject {...drawerParams} />
</ContentTagsDrawerSheetContext.Provider>,
{ path, params: { contentId } },
)
Expand Down Expand Up @@ -244,6 +244,29 @@ describe('<ContentTagsDrawer />', () => {
expect(screen.queryByRole('button', { name: /save/i })).not.toBeInTheDocument();
});

test.each([
{
variant: 'drawer',
editButton: /edit tags/i,
},
{
variant: 'component',
editButton: /manage tags/i,
},
])(
'should hide "$editButton" button on $variant variant if not allowed to tag object',
async ({ variant, editButton }) => {
renderDrawer(stagedTagsId, { variant, canTagObject: false });
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();

expect(screen.queryByRole('button', { name: editButton })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
expect(screen.queryByText(/add a tag/i)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /cancel/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /save/i })).not.toBeInTheDocument();
},
);

it('should test adding a content tag to the staged tags for a taxonomy', async () => {
renderDrawer(stagedTagsId);
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();
Expand Down Expand Up @@ -368,7 +391,7 @@ describe('<ContentTagsDrawer />', () => {
expect(screen.queryByText(/tag 3/i)).not.toBeInTheDocument();
});

it('should test delete feched tags and cancel', async () => {
it('should test delete fetched tags and cancel', async () => {
renderDrawer(stagedTagsId);
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();

Expand Down Expand Up @@ -435,7 +458,7 @@ describe('<ContentTagsDrawer />', () => {
expect(screen.queryByText(/tag 3/i)).not.toBeInTheDocument();
});

it('should test add removed feched tags and cancel', async () => {
it('should test add removed fetched tags and cancel', async () => {
renderDrawer(stagedTagsId);
expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument();

Expand Down
55 changes: 31 additions & 24 deletions src/content-tags-drawer/ContentTagsDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const TaxonomyList = ({ contentId }: TaxonomyListProps) => {
return <Loading />;
};

const ContentTagsDrawerTittle = () => {
const ContentTagsDrawerTitle = () => {
const intl = useIntl();
const {
isContentDataLoaded,
Expand All @@ -100,9 +100,10 @@ const ContentTagsDrawerTittle = () => {

interface ContentTagsDrawerVariantFooterProps {
onClose: () => void,
canTagObject: boolean,
}

const ContentTagsDrawerVariantFooter = ({ onClose }: ContentTagsDrawerVariantFooterProps) => {
const ContentTagsDrawerVariantFooter = ({ onClose, canTagObject }: ContentTagsDrawerVariantFooterProps) => {
const intl = useIntl();
const {
commitGlobalStagedTagsStatus,
Expand Down Expand Up @@ -130,16 +131,18 @@ const ContentTagsDrawerVariantFooter = ({ onClose }: ContentTagsDrawerVariantFoo
? messages.tagsDrawerCancelButtonText
: messages.tagsDrawerCloseButtonText)}
</Button>
<Button
className="rounded-0"
onClick={isEditMode
? commitGlobalStagedTags
: toEditMode}
>
{ intl.formatMessage(isEditMode
? messages.tagsDrawerSaveButtonText
: messages.tagsDrawerEditTagsButtonText)}
</Button>
{canTagObject && (
<Button
className="rounded-0"
onClick={isEditMode
? commitGlobalStagedTags
: toEditMode}
>
{ intl.formatMessage(isEditMode
? messages.tagsDrawerSaveButtonText
: messages.tagsDrawerEditTagsButtonText)}
</Button>
)}
</Stack>
)
: (
Expand All @@ -154,7 +157,7 @@ const ContentTagsDrawerVariantFooter = ({ onClose }: ContentTagsDrawerVariantFoo
);
};

const ContentTagsComponentVariantFooter = () => {
const ContentTagsComponentVariantFooter = ({ canTagObject }: { canTagObject: boolean }) => {
const intl = useIntl();
const {
commitGlobalStagedTagsStatus,
Expand Down Expand Up @@ -196,13 +199,15 @@ const ContentTagsComponentVariantFooter = () => {
)}
</div>
) : (
<Button
variant="outline-primary"
onClick={toEditMode}
block
>
{intl.formatMessage(messages.manageTagsButton)}
</Button>
canTagObject && (
<Button
variant="outline-primary"
onClick={toEditMode}
block
>
{intl.formatMessage(messages.manageTagsButton)}
</Button>
)
)}
</div>
);
Expand All @@ -211,6 +216,7 @@ const ContentTagsComponentVariantFooter = () => {
interface ContentTagsDrawerProps {
id?: string;
onClose?: () => void;
canTagObject?: boolean;
variant?: 'drawer' | 'component';
}

Expand All @@ -226,6 +232,7 @@ interface ContentTagsDrawerProps {
const ContentTagsDrawer = ({
id,
onClose,
canTagObject = false,
variant = 'drawer',
}: ContentTagsDrawerProps) => {
const intl = useIntl();
Expand All @@ -237,7 +244,7 @@ const ContentTagsDrawer = ({
throw new Error('Error: contentId cannot be null.');
}

const context = useContentTagsDrawerContext(contentId);
const context = useContentTagsDrawerContext(contentId, canTagObject);
const { blockingSheet } = useContext(ContentTagsDrawerSheetContext);

const {
Expand Down Expand Up @@ -301,9 +308,9 @@ const ContentTagsDrawer = ({
if (isTaxonomyListLoaded && isContentTaxonomyTagsLoaded) {
switch (variant) {
case 'drawer':
return <ContentTagsDrawerVariantFooter onClose={onCloseDrawer} />;
return <ContentTagsDrawerVariantFooter onClose={onCloseDrawer} canTagObject={canTagObject} />;
case 'component':
return <ContentTagsComponentVariantFooter />;
return <ContentTagsComponentVariantFooter canTagObject={canTagObject} />;
default:
return null;
}
Expand Down Expand Up @@ -331,7 +338,7 @@ const ContentTagsDrawer = ({
)}
>
{variant === 'drawer' && (
<ContentTagsDrawerTittle />
<ContentTagsDrawerTitle />
)}
<Container
className={classNames(
Expand Down
Loading