fix(my-joy-beta): prevent race conditions when editing tags

This commit is contained in:
Sérgio Ramos 2018-01-04 12:20:11 +00:00 committed by Sérgio Ramos
parent a6f9b74f6f
commit 17d3563a42

View File

@ -40,6 +40,7 @@ export const Tags = ({
tags = [], tags = [],
addOpen, addOpen,
editing, editing,
editable,
loading, loading,
handleToggleAddOpen, handleToggleAddOpen,
handleToggleEditing, handleToggleEditing,
@ -81,7 +82,7 @@ export const Tags = ({
id={id} id={id}
name={name} name={name}
value={value} value={value}
onClick={!editing && (() => handleToggleEditing(name))} onClick={editable && !editing && (() => handleToggleEditing(name))}
/> />
))} ))}
</TagList> </TagList>
@ -166,16 +167,20 @@ export default compose(
? index.search(filter).map(({ ref }) => find(tags, ['id', ref])) ? index.search(filter).map(({ ref }) => find(tags, ['id', ref]))
: tags; : tags;
const addOpen = get(values, 'add-tags-open', false);
const editingTagName = get(values, 'editing-tag', null); const editingTagName = get(values, 'editing-tag', null);
const removingTagName = get(values, 'removing-tag', null); const removingTagName = get(values, 'removing-tag', null);
const removingTag = editingTagName === removingTagName;
const editingTag = const editingTag =
editingTagName && find(filtered, ['name', editingTagName]); editingTagName && find(filtered, ['name', editingTagName]);
const removingTag = editingTagName === removingTagName;
return { return {
...ownProps, ...ownProps,
tags: filtered, tags: filtered,
addOpen: get(values, 'add-tags-open', false), addOpen,
// are existing tags editable?
editable: !addOpen && !editingTag,
// if a tag is being edited, which one?
editing: editingTag && { editing: editingTag && {
...editingTag, ...editingTag,
removing: Boolean(removingTag), removing: Boolean(removingTag),
@ -192,23 +197,38 @@ export default compose(
handleEdit: async ({ name, value }, _, { form, initialValues }) => { handleEdit: async ({ name, value }, _, { form, initialValues }) => {
const { instance, deleteTag, updateTags, refetch } = ownProps; const { instance, deleteTag, updateTags, refetch } = ownProps;
// call mutations const replaceTag = async () => {
const [err] = await intercept( // we can't mutate in parallel because if the tag name is the
Promise.all([ // same we can have a race condition and remove after updating
deleteTag({
variables: { await updateTags({
id: instance.id, variables: {
name: initialValues.name id: instance.id,
} tags: [{ name, value }]
}), }
updateTags({ });
variables: {
id: instance.id, await deleteTag({
tags: [{ name, value }] variables: {
} id: instance.id,
}) name: initialValues.name
]) }
); });
};
const updateValue = async () => {
await updateTags({
variables: {
id: instance.id,
tags: [{ name, value }]
}
});
};
const mutation =
initialValues.name === name ? updateValue : replaceTag;
const [err] = await intercept(mutation());
if (err) { if (err) {
// show mutation error // show mutation error