Skip to content

Commit

Permalink
feat: edit item
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Jan 15, 2021
1 parent a7399fa commit 8134a34
Show file tree
Hide file tree
Showing 28 changed files with 635 additions and 205 deletions.
12 changes: 12 additions & 0 deletions cypress/fixtures/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,37 @@ export const SIMPLE_ITEMS = [
id: 'ecafbd2a-5688-11eb-ae93-0242ac130002',
name: 'own_item_name1',
path: 'ecafbd2a_5688_11eb_ae93_0242ac130002',
extra: {
image: 'someimageurl',
},
},
{
...DEFAULT_ITEM,
id: 'fdf09f5a-5688-11eb-ae93-0242ac130002',
name: 'own_item_name2',
path: 'fdf09f5a_5688_11eb_ae93_0242ac130002',
extra: {
image: 'someimageurl',
},
},
{
...DEFAULT_ITEM,
id: 'fdf09f5a-5688-11eb-ae93-0242ac130003',
name: 'own_item_name3',
path:
'ecafbd2a_5688_11eb_ae93_0242ac130002.fdf09f5a_5688_11eb_ae93_0242ac130003',
extra: {
image: 'someimageurl',
},
},
{
...DEFAULT_ITEM,
id: 'fdf09f5a-5688-11eb-ae93-0242ac130004',
name: 'own_item_name4',
path:
'ecafbd2a_5688_11eb_ae93_0242ac130002.fdf09f5a_5688_11eb_ae93_0242ac130004',
extra: {
image: 'someimageurl',
},
},
];
20 changes: 10 additions & 10 deletions cypress/integration/createItem.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { buildItemPath } from '../../src/config/paths';
import {
buildItemCard,
CREATE_ITEM_BUTTON_ID,
NEW_ITEM_CONFIRM_BUTTON_ID,
NEW_ITEM_DESCRIPTION_INPUT_ID,
NEW_ITEM_IMAGE_INPUT_ID,
NEW_ITEM_NAME_INPUT_ID,
NEW_ITEM_TYPE_SELECT_ID,
ITEM_FORM_CONFIRM_BUTTON_ID,
ITEM_FORM_DESCRIPTION_INPUT_ID,
ITEM_FORM_IMAGE_INPUT_ID,
ITEM_FORM_NAME_INPUT_ID,
ITEM_FORM_TYPE_SELECT_ID,
} from '../../src/config/selectors';
import { CREATED_ITEM, SIMPLE_ITEMS } from '../fixtures/items';

Expand All @@ -18,15 +18,15 @@ const createItem = ({
}) => {
cy.get(`#${CREATE_ITEM_BUTTON_ID}`).click();

cy.get(`#${NEW_ITEM_NAME_INPUT_ID}`).type(name);
cy.get(`#${ITEM_FORM_NAME_INPUT_ID}`).type(name);

cy.get(`#${NEW_ITEM_DESCRIPTION_INPUT_ID}`).type(description);
cy.get(`#${ITEM_FORM_DESCRIPTION_INPUT_ID}`).type(description);

cy.get(`#${NEW_ITEM_TYPE_SELECT_ID}`).click();
cy.get(`#${ITEM_FORM_TYPE_SELECT_ID}`).click();
cy.get(`li[data-value="${type}"]`).click();
cy.get(`#${NEW_ITEM_IMAGE_INPUT_ID}`).type(extra.image);
cy.get(`#${ITEM_FORM_IMAGE_INPUT_ID}`).type(extra.image);

cy.get(`#${NEW_ITEM_CONFIRM_BUTTON_ID}`).click();
cy.get(`#${ITEM_FORM_CONFIRM_BUTTON_ID}`).click();
};

describe('Create Item', () => {
Expand Down
97 changes: 97 additions & 0 deletions cypress/integration/editItem.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { buildItemPath } from '../../src/config/paths';
import {
buildItemCard,
buildItemLink,
buildItemMenu,
ITEM_MENU_BUTTON_CLASS,
ITEM_MENU_EDIT_BUTTON_CLASS,
ITEM_FORM_CONFIRM_BUTTON_ID,
ITEM_FORM_DESCRIPTION_INPUT_ID,
ITEM_FORM_IMAGE_INPUT_ID,
ITEM_FORM_NAME_INPUT_ID,
ITEM_FORM_TYPE_SELECT_ID,
} from '../../src/config/selectors';
import { SIMPLE_ITEMS } from '../fixtures/items';

const editItem = ({
id,
name = '',
type = 'Space',
extra = {},
description = '',
}) => {
const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`;
cy.get(menuSelector).click();
cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_EDIT_BUTTON_CLASS}`).click();

cy.get(`#${ITEM_FORM_NAME_INPUT_ID}`).clear().type(name);

cy.get(`#${ITEM_FORM_DESCRIPTION_INPUT_ID}`).clear().type(description);

cy.get(`#${ITEM_FORM_TYPE_SELECT_ID}`).click();
cy.get(`li[data-value="${type}"]`).click();
cy.get(`#${ITEM_FORM_IMAGE_INPUT_ID}`).clear().type(extra.image);

cy.get(`#${ITEM_FORM_CONFIRM_BUTTON_ID}`).click();
};

describe('Edit Item', () => {
it('edit item on Home', () => {
cy.setUpApi({ items: SIMPLE_ITEMS });
cy.visit('/');

const itemToEdit = SIMPLE_ITEMS[0];
const newName = 'new name';
const newDescription = 'new description';

// create
editItem({
...itemToEdit,
name: newName,
description: newDescription,
});

cy.wait('@editItem').then(
({
response: {
body: { id, name },
},
}) => {
// check item is created and displayed
cy.wait(1000);
cy.get(`#${buildItemCard(id)}`).should('exist');
cy.get(`#${buildItemLink(id)}`).contains(name);
},
);
});

it('create item in item', () => {
cy.setUpApi({ items: SIMPLE_ITEMS });
// go to children item
cy.visit(buildItemPath(SIMPLE_ITEMS[0].id));

const itemToEdit = SIMPLE_ITEMS[2];
const newName = 'new name';
const newDescription = 'new description';

// create
editItem({
...itemToEdit,
name: newName,
description: newDescription,
});

cy.wait('@editItem').then(
({
response: {
body: { id, name },
},
}) => {
// check item is created and displayed
cy.wait(1000);
cy.get(`#${buildItemCard(id)}`).should('exist');
cy.get(`#${buildItemLink(id)}`).contains(name);
},
);
});
});
4 changes: 4 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
mockGetOwnItems,
mockMoveItem,
mockPostItem,
mockEditItem,
} from './server';

Cypress.Commands.add(
Expand All @@ -22,6 +23,7 @@ Cypress.Commands.add(
moveItemError = false,
copyItemError = false,
getItemError = false,
editItemError = false,
} = {}) => {
const cachedItems = JSON.parse(JSON.stringify(items));

Expand All @@ -38,6 +40,8 @@ Cypress.Commands.add(
mockMoveItem(cachedItems, moveItemError);

mockCopyItem(cachedItems, copyItemError);

mockEditItem(cachedItems, editItemError);
},
);

Expand Down
17 changes: 17 additions & 0 deletions cypress/support/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { v4 as uuidv4 } from 'uuid';
import {
buildCopyItemRoute,
buildDeleteItemRoute,
buildEditItemRoute,
buildGetChildrenRoute,
buildGetItemRoute,
buildMoveItemRoute,
Expand Down Expand Up @@ -180,3 +181,19 @@ export const mockCopyItem = (items, shouldThrowError) => {
},
).as('copyItem');
};

export const mockEditItem = (items, shouldThrowError) => {
cy.intercept(
{
method: 'PATCH',
url: new RegExp(`${API_HOST}/${buildEditItemRoute(ID_FORMAT)}`),
},
({ reply, body }) => {
if (shouldThrowError) {
return reply({ statusCode: ERROR_CODE });
}

return reply(body);
},
).as('editItem');
};
17 changes: 17 additions & 0 deletions src/actions/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import {
FLAG_GETTING_ITEMS,
FLAG_MOVING_ITEM,
FLAG_COPYING_ITEM,
EDIT_ITEM_SUCCESS,
FLAG_SETTING_ITEM,
FLAG_EDITING_ITEM,
} from '../types/item';
import { getParentsIdsFromPath } from '../utils/item';
import { createFlag } from './utils';
Expand Down Expand Up @@ -209,3 +211,18 @@ export const getChildren = (id) => async (dispatch) => {
dispatch(createFlag(FLAG_GETTING_CHILDREN, false));
}
};

export const editItem = (item) => async (dispatch) => {
try {
dispatch(createFlag(FLAG_EDITING_ITEM, true));
const editedItem = await Api.editItem(item);
dispatch({
type: EDIT_ITEM_SUCCESS,
payload: editedItem,
});
} catch (e) {
console.error(e);
} finally {
dispatch(createFlag(FLAG_EDITING_ITEM, false));
}
};
8 changes: 8 additions & 0 deletions src/actions/layout.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
SET_COPY_MODAL_SETTINGS,
SET_EDIT_MODAL_SETTINGS,
SET_MOVE_MODAL_SETTINGS,
} from '../types/layout';

Expand All @@ -16,3 +17,10 @@ export const setCopyModalSettings = (payload) => (dispatch) => {
payload,
});
};

export const setEditModalSettings = (payload) => (dispatch) => {
dispatch({
type: SET_EDIT_MODAL_SETTINGS,
payload,
});
};
28 changes: 27 additions & 1 deletion src/api/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import { API_HOST, ROOT_ID } from '../config/constants';
import {
buildCopyItemRoute,
buildDeleteItemRoute,
buildEditItemRoute,
buildGetChildrenRoute,
buildGetItemRoute,
buildMoveItemRoute,
buildPostItemRoute,
GET_OWN_ITEMS_ROUTE,
} from './routes';
import { DEFAULT_DELETE, DEFAULT_GET, DEFAULT_POST } from './utils';
import {
DEFAULT_DELETE,
DEFAULT_GET,
DEFAULT_POST,
DEFAULT_PATCH,
} from './utils';
import * as CacheOperations from '../config/cache';

export const getItem = async (id) => {
Expand Down Expand Up @@ -80,6 +86,26 @@ export const deleteItem = async (id) => {
return res.json();
};

// payload = {name, type, description, extra}
// querystring = {parentId}
export const editItem = async (item) => {
const req = await fetch(`${API_HOST}/${buildEditItemRoute(item.id)}`, {
...DEFAULT_PATCH,
body: JSON.stringify(item),
});

if (!req.ok) {
throw new Error((await req.json()).message);
}

const newItem = await req.json();

await CacheOperations.saveItem(newItem);

return newItem;
};

// we need this function for navigation purposes: when you click on an item, you want to see its 'immediate' children
export const getChildren = async (id) => {
const res = await fetch(
`${API_HOST}/${buildGetChildrenRoute(id)}`,
Expand Down
1 change: 1 addition & 0 deletions src/api/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export const buildGetChildrenRoute = (id) => `items/${id}/children`;
export const buildGetItemRoute = (id) => `items/${id}`;
export const buildMoveItemRoute = (id) => `items/${id}/move`;
export const buildCopyItemRoute = (id) => `items/${id}/copy`;
export const buildEditItemRoute = (id) => `items/${id}`;
6 changes: 6 additions & 0 deletions src/api/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ export const DEFAULT_DELETE = {
method: 'DELETE',
credentials: 'include',
};

export const DEFAULT_PATCH = {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
};
17 changes: 10 additions & 7 deletions src/components/main/CustomCardHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const useStyles = makeStyles((theme) => ({
},
}));

const CustomCardHeader = ({ id, creator, title, type }) => {
const CustomCardHeader = ({ item }) => {
const { id, creator, name, type } = item;
const classes = useStyles();
const { t } = useTranslation();
return (
Expand All @@ -47,7 +48,7 @@ const CustomCardHeader = ({ id, creator, title, type }) => {
<div>
<Link to={buildItemPath(id)} className={classes.link}>
<Typography id={buildItemLink(id)} className={classes.title}>
{title}
{name}
</Typography>
</Link>
<Typography className={classes.subtitle}>
Expand All @@ -58,16 +59,18 @@ const CustomCardHeader = ({ id, creator, title, type }) => {
</Typography>
</div>
</div>
<ItemMenu itemId={id} />
<ItemMenu item={item} />
</div>
);
};

CustomCardHeader.propTypes = {
id: PropTypes.string.isRequired,
creator: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
item: PropTypes.shape({
id: PropTypes.string.isRequired,
creator: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
}).isRequired,
};

export default CustomCardHeader;
Loading

0 comments on commit 8134a34

Please sign in to comment.