Skip to content

Commit

Permalink
Merge pull request #373 from graasp/366/publishItemRefactor
Browse files Browse the repository at this point in the history
feat: add co-editor settings
  • Loading branch information
louisewang1 authored Jul 4, 2022
2 parents 91505ce + 082f77e commit 270a569
Show file tree
Hide file tree
Showing 12 changed files with 1,197 additions and 947 deletions.
1 change: 1 addition & 0 deletions cypress/fixtures/categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const ITEM_WITH_CATEGORIES = {
...PUBLISHED_ITEM,
settings: {
tags: CUSTOMIZED_TAGS,
displayCoEditors: true,
},
// for tests
categories: SAMPLE_ITEM_CATEGORIES,
Expand Down
77 changes: 77 additions & 0 deletions cypress/integration/item/publish/coEditorSettings.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {
buildCoEditorSettingsRadioButtonId,
buildPublishButtonId,
CO_EDITOR_SETTINGS_RADIO_GROUP_ID,
} from '../../../../src/config/selectors';
import { buildItemPath } from '../../../../src/config/paths';
import {
ITEM_WITH_CATEGORIES,
} from '../../../fixtures/categories';
import { PUBLISHED_ITEM } from '../../../fixtures/items';
import { DEFAULT_TAGS } from '../../../fixtures/itemTags';
import { MEMBERS, SIGNED_OUT_MEMBER } from '../../../fixtures/members';
import { EDIT_TAG_REQUEST_TIMEOUT } from '../../../support/constants';
import { DISPLAY_CO_EDITORS_OPTIONS } from '../../../../src/config/constants';

const openPublishItemTab = (id) => {
cy.get(`#${buildPublishButtonId(id)}`).click();
};

const visitItemPage = (item) => {
cy.setUpApi({ items: [item], tags: DEFAULT_TAGS });
cy.visit(buildItemPath(item.id));
openPublishItemTab(item.id);
};

describe('Co-editor Setting', () => {
it('Display choices', () => {
const item = ITEM_WITH_CATEGORIES;
visitItemPage(item);

Object.values(DISPLAY_CO_EDITORS_OPTIONS).forEach((option) => {
const displayTags = cy.get(`#${buildCoEditorSettingsRadioButtonId(option.value)}`);
displayTags.should('be.visible');
});
});

it('Change choice', () => {
const item = ITEM_WITH_CATEGORIES;
visitItemPage(item);

const newOptionValue = DISPLAY_CO_EDITORS_OPTIONS.NO.value;
cy.get(`#${buildCoEditorSettingsRadioButtonId(newOptionValue)}`).click();
cy.wait('@editItem', { timeout: EDIT_TAG_REQUEST_TIMEOUT }).then((data) => {
const {
request: { url, body },
} = data;
expect(url.split('/')).contains(item.id);
expect(body.settings.displayCoEditors).equals(newOptionValue);
});
});
});

describe('Co-editor setting permissions', () => {
it('User signed out cannot edit co-editor setting', () => {
const item = PUBLISHED_ITEM;
cy.setUpApi({
items: [item],
currentMember: SIGNED_OUT_MEMBER,
tags: DEFAULT_TAGS,
});
cy.visit(buildItemPath(item.id));
openPublishItemTab(item.id);
cy.get(`#${CO_EDITOR_SETTINGS_RADIO_GROUP_ID}`).should('not.exist');
});

it('Read-only user cannot edit co-editor setting', () => {
const item = PUBLISHED_ITEM;
cy.setUpApi({
items: [item],
currentMember: MEMBERS.BOB,
tags: DEFAULT_TAGS,
});
cy.visit(buildItemPath(item.id));
openPublishItemTab(item.id);
cy.get(`#${CO_EDITOR_SETTINGS_RADIO_GROUP_ID}`).should('not.exist');
});
});
29 changes: 25 additions & 4 deletions cypress/integration/item/publish/publishedItem.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
buildPublishButtonId,
EMAIL_NOTIFICATION_CHECKBOX,
ITEM_PUBLISH_BUTTON_ID,
ITEM_UNPUBLISH_BUTTON_ID,
ITEM_VALIDATION_BUTTON_ID,
Expand All @@ -10,7 +11,7 @@ import {
SAMPLE_ITEMS,
SAMPLE_PUBLIC_ITEMS,
} from '../../../fixtures/items';
import { DEFAULT_TAGS, ITEM_PUBLISHED_TAG } from '../../../fixtures/itemTags';
import { DEFAULT_TAGS } from '../../../fixtures/itemTags';
import { VALIDATED_ITEM } from '../../../fixtures/validations';

const openPublishItemTab = (id) => {
Expand Down Expand Up @@ -74,11 +75,31 @@ describe('Validated Item', () => {
// click validate item button
cy.get(`#${ITEM_PUBLISH_BUTTON_ID}`).click();

cy.wait('@postItemTag').then((data) => {
cy.wait('@publishItem').then((data) => {
const {
request: { body },
request: { url },
} = data;
expect(url.includes(VALIDATED_ITEM.id));
expect(!url.includes('notification'));
});
});

it('Publish item with notification', () => {
cy.setUpApi({ items: [VALIDATED_ITEM], tags: DEFAULT_TAGS });
const item = VALIDATED_ITEM;
cy.visit(buildItemPath(item.id));
openPublishItemTab(item.id);

// click validate item button
cy.get(`#${EMAIL_NOTIFICATION_CHECKBOX}`).check();
cy.get(`#${ITEM_PUBLISH_BUTTON_ID}`).click();

cy.wait('@publishItem').then((data) => {
const {
request: { url },
} = data;
expect(body?.tagId).to.equal(ITEM_PUBLISHED_TAG.id);
expect(url.includes(VALIDATED_ITEM.id));
expect(url.includes('notification'));
});
});
});
3 changes: 3 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import {
mockGetItemInvitations,
mockPatchInvitation,
mockDeleteInvitation,
mockPublishItem,
} from './server';
import './commands/item';
import './commands/navigation';
Expand Down Expand Up @@ -300,6 +301,8 @@ Cypress.Commands.add(
mockPatchInvitation(items, patchInvitationError);

mockDeleteInvitation(items, deleteInvitationError);

mockPublishItem(items);
},
);

Expand Down
14 changes: 14 additions & 0 deletions cypress/support/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const {
buildDeleteInvitationRoute,
buildPatchInvitationRoute,
buildResendInvitationRoute,
buildItemPublishRoute
} = API_ROUTES;

const API_HOST = Cypress.env('API_HOST');
Expand Down Expand Up @@ -1531,3 +1532,16 @@ export const mockDeleteInvitation = (items, shouldThrowError) => {
},
).as('deleteInvitation');
};

export const mockPublishItem = (items) => {
cy.intercept(
{
method: DEFAULT_GET.method,
url: new RegExp(`${API_HOST}/${buildItemPublishRoute(ID_FORMAT)}`),
},
({ reply, url }) => {
const itemId = url.slice(API_HOST.length).split('/')[2];
reply(items.find(item => item?.id === itemId));
},
).as('publishItem');
};
105 changes: 105 additions & 0 deletions src/components/item/publish/CoEditorSettings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React, { useContext, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Loader } from '@graasp/ui';
import { useTranslation } from 'react-i18next';
import {
Typography,
makeStyles,
Radio,
RadioGroup,
FormControlLabel,
} from '@material-ui/core';
import { MUTATION_KEYS } from '@graasp/query-client';
import { useMutation } from '../../../config/queryClient';
import { CurrentUserContext } from '../../context/CurrentUserContext';
import { DISPLAY_CO_EDITORS_OPTIONS } from '../../../config/constants';
import {
buildCoEditorSettingsRadioButtonId,
CO_EDITOR_SETTINGS_RADIO_GROUP_ID,
} from '../../../config/selectors';

const useStyles = makeStyles((theme) => ({
title: {
marginTop: theme.spacing(2),
},
button: {
marginTop: theme.spacing(1),
marginLeft: theme.spacing(2),
},
}));

const { EDIT_ITEM } = MUTATION_KEYS;

const CoEditorSettings = ({ item }) => {
const { t } = useTranslation();
const classes = useStyles();
const { mutate: updateDisplayCoEditors } = useMutation(EDIT_ITEM);

// user
const { isLoading: isMemberLoading } = useContext(CurrentUserContext);

// current item
const itemId = item?.get('id');
const settings = item?.get('settings');
const itemName = item?.get('name');

// by default, co editors will not be displayed
const [optionValue, setOptionValue] = useState(
DISPLAY_CO_EDITORS_OPTIONS.NO.value,
);

useEffect(() => {
if (settings?.displayCoEditors) {
setOptionValue(settings.displayCoEditors);
}
}, [settings]);

if (isMemberLoading) {
return <Loader />;
}

const handleChange = (event) => {
// value from radio button is string, convert to boolean
const newValue = event.target.value === 'true';
setOptionValue(newValue);
updateDisplayCoEditors({
id: itemId,
name: itemName,
settings: { displayCoEditors: newValue },
});
};

return (
<>
<Typography variant="h6" className={classes.title}>
{t('Co-Editors')}
</Typography>
<Typography variant="body1">
{t(
'Do you want to display co-editors on the publication page? All users with edit or admin permissions will be displayed.',
)}
</Typography>
<RadioGroup
id={CO_EDITOR_SETTINGS_RADIO_GROUP_ID}
name={t('Display co-editors?')}
value={optionValue}
onChange={handleChange}
>
{Object.values(DISPLAY_CO_EDITORS_OPTIONS).map((option) => (
<FormControlLabel
id={buildCoEditorSettingsRadioButtonId(option.value)}
value={option.value}
control={<Radio color="primary" />}
label={t(option.label)}
/>
))}
</RadioGroup>
</>
);
};

CoEditorSettings.propTypes = {
item: PropTypes.instanceOf(Map).isRequired,
};

export default CoEditorSettings;
Loading

0 comments on commit 270a569

Please sign in to comment.