Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -193,52 +193,60 @@ const NetworkModificationNodeEditor = () => {
broadcast.onmessage = (event) => {
console.info('message received from broadcast channel: ', event.data);
isInitiatingCopyTab.current = false;
if (JSON.stringify(emptyCopiedModificationsSelection) === JSON.stringify(event.data)) {
cleanClipboard();
if (JSON.stringify(emptyCopiedModificationsSelection) === JSON.stringify(event.data.modificationsToCopy)) {
cleanCurrentTabClipboard(event.data.message);
} else {
setCopiedModifications(event.data.modificationsUuids);
setCopiedModifications(event.data.modificationsToCopy.modificationsUuids);
setCopyInfos({
copyType: event.data.copyInfos.copyType,
originStudyUuid: event.data.copyInfos.originStudyUuid,
originNodeUuid: event.data.copyInfos.originNodeUuid,
copyType: event.data.modificationsToCopy.copyInfos.copyType,
originStudyUuid: event.data.modificationsToCopy.copyInfos.originStudyUuid,
originNodeUuid: event.data.modificationsToCopy.copyInfos.originNodeUuid,
});
snackInfo({ messageId: 'CopiedModificationUpdateMessageFromAnotherStudy' });
snackInfo({ messageId: event.data.message });
}
};
return broadcast;
});

useEffect(() => {
//If the tab is closed we want to invalidate the copy on all tabs because we won't able to track the node modification
window.addEventListener('beforeunload', (event) => {
if (true === isInitiatingCopyTab.current) {
broadcastChannel.postMessage(emptyCopiedModificationsSelection);
snackInfo({
messageId: 'CopiedModificationInvalidationMessageAfterTabClosure',
});
}
});
}, [broadcastChannel, snackInfo]);

const cleanClipboard = useCallback(
(showSnackInfo: boolean = true) => {
const cleanCurrentTabClipboard = useCallback(
(snackInfoMessage?: string) => {
setCopyInfos(null);
setCopiedModifications((oldCopiedModifications) => {
if (oldCopiedModifications.length && showSnackInfo) {
if (oldCopiedModifications.length && snackInfoMessage) {
snackInfo({
messageId: 'CopiedModificationInvalidationMessage',
messageId: snackInfoMessage,
});
}
return [];
});
},
[snackInfo]
);
const cleanOtherTabsClipboard = useCallback(
(snackInfoMessage?: string) => {
if (true === isInitiatingCopyTab.current) {
broadcastChannel.postMessage(emptyCopiedModificationsSelection);
broadcastChannel.postMessage({
modificationsToCopy: emptyCopiedModificationsSelection,
message: snackInfoMessage,
});
isInitiatingCopyTab.current = false;
}
},
[snackInfo, broadcastChannel]
[broadcastChannel]
);

const cleanClipboard = useCallback(() => {
cleanCurrentTabClipboard('copiedModificationsInvalidationMsg');
cleanOtherTabsClipboard('copiedModificationsInvalidationMsgFromOtherStudy');
}, [cleanCurrentTabClipboard, cleanOtherTabsClipboard]);

useEffect(() => {
//If the tab is closed we want to invalidate the copy on all tabs because we won't able to track the node modification
window.addEventListener('beforeunload', (event) => {
cleanOtherTabsClipboard('copiedModificationsInvalidationMsgFromStudyClosure');
});
}, [cleanOtherTabsClipboard]);

// TODO this is not complete.
// We should clean Clipboard on notifications when another user edit
// a modification on a public study which is in the clipboard.
Expand Down Expand Up @@ -1078,7 +1086,9 @@ const NetworkModificationNodeEditor = () => {
originStudyUuid: studyUuid ?? undefined,
originNodeUuid: currentNode?.id,
});
}, [currentNode?.id, selectedModificationsIds, studyUuid]);
isInitiatingCopyTab.current = true;
cleanOtherTabsClipboard('copiedModificationsInvalidationMsg');
}, [cleanOtherTabsClipboard, currentNode?.id, selectedModificationsIds, studyUuid]);

const doCopyModifications = useCallback(() => {
setCopiedModifications(selectedModificationsIds());
Expand All @@ -1088,12 +1098,15 @@ const NetworkModificationNodeEditor = () => {
originNodeUuid: currentNode?.id,
});
broadcastChannel.postMessage({
modificationsUuids: selectedModificationsIds(),
copyInfos: {
copyType: NetworkModificationCopyType.COPY,
originStudyUuid: studyUuid,
originNodeUuid: currentNode?.id,
modificationsToCopy: {
modificationsUuids: selectedModificationsIds(),
copyInfos: {
copyType: NetworkModificationCopyType.COPY,
originStudyUuid: studyUuid,
originNodeUuid: currentNode?.id,
},
},
message: 'copiedModificationsUpdateMsg',
});
isInitiatingCopyTab.current = true;
}, [broadcastChannel, currentNode?.id, selectedModificationsIds, studyUuid]);
Expand All @@ -1105,7 +1118,7 @@ const NetworkModificationNodeEditor = () => {
if (copyInfos.copyType === NetworkModificationCopyType.MOVE) {
copyOrMoveModifications(studyUuid, currentNode.id, copiedModifications, copyInfos)
.then(() => {
cleanClipboard(false);
cleanCurrentTabClipboard();
})
.catch((errmsg) => {
snackError({
Expand All @@ -1121,7 +1134,7 @@ const NetworkModificationNodeEditor = () => {
});
});
}
}, [copyInfos, studyUuid, currentNode?.id, copiedModifications, cleanClipboard, snackError]);
}, [copyInfos, studyUuid, currentNode?.id, copiedModifications, cleanCurrentTabClipboard, snackError]);

const removeNullFields = useCallback((data: NetworkModificationData) => {
let dataTemp = data;
Expand Down
102 changes: 73 additions & 29 deletions src/components/network-modification-tree-pane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,32 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
[dispatch]
);

const dispatchNoNodeSelectionForCopy = useCallback(
(snackInfoMessage = null) => {
if (nodeSelectionForCopyRef.current.nodeId && snackInfoMessage) {
snackInfo({
messageId: snackInfoMessage,
});
}
dispatch(setNodeSelectionForCopy(noNodeSelectionForCopy));
},
[dispatch, snackInfo]
);

const [broadcastChannel] = useState(() => {
const broadcast = new BroadcastChannel('nodeCopyChannel');
broadcast.onmessage = (event) => {
console.info('message received from broadcast channel');
console.info(event.data);
console.info('message received from broadcast channel: ', event.data);
isInitiatingCopyTab.current = false;
if (JSON.stringify(noNodeSelectionForCopy) === JSON.stringify(event.data)) {
dispatch(setNodeSelectionForCopy(noNodeSelectionForCopy));
snackInfo({
messageId: 'CopiedNodeInvalidationMessage',
});
if (JSON.stringify(noNodeSelectionForCopy) === JSON.stringify(event.data.nodeToCopy)) {
dispatchNoNodeSelectionForCopy(event.data.message);
} else {
dispatchNodeSelectionForCopy(event.data.sourceStudyUuid, event.data.nodeId, event.data.copyType);
dispatchNodeSelectionForCopy(
event.data.nodeToCopy.sourceStudyUuid,
event.data.nodeToCopy.nodeId,
event.data.nodeToCopy.copyType
);
snackInfo({ messageId: event.data.message });
}
};
return broadcast;
Expand All @@ -100,7 +113,10 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
//If the tab is closed we want to invalidate the copy on all tabs because we won't able to track the node modification
window.addEventListener('beforeunload', (event) => {
if (true === isInitiatingCopyTab.current) {
broadcastChannel.postMessage(noNodeSelectionForCopy);
broadcastChannel.postMessage({
nodeToCopy: noNodeSelectionForCopy,
message: 'copiedNodeInvalidationMsgFromStudyClosure',
});
}
});
//broadcastChannel doesn't change
Expand Down Expand Up @@ -152,19 +168,19 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
);

const resetNodeClipboard = useCallback(() => {
dispatch(setNodeSelectionForCopy(noNodeSelectionForCopy));
snackInfo({
messageId: 'CopiedNodeInvalidationMessage',
});
dispatchNoNodeSelectionForCopy('copiedNodeInvalidationMsg');

//only the tab that initiated the copy should update through the websocket, all the other tabs will get the info through broadcast
if (true === isInitiatingCopyTab.current) {
broadcastChannel.postMessage(noNodeSelectionForCopy);
broadcastChannel.postMessage({
nodeToCopy: noNodeSelectionForCopy,
message: 'copiedNodeInvalidationMsgFromOtherStudy',
});

//we need to reset isInitiatingCopyTab here otherwise it won't in the current tab thus next unrelated pasting actions will reset other tabs clipboard
isInitiatingCopyTab.current = false;
}
}, [broadcastChannel, dispatch, snackInfo]);
}, [broadcastChannel, dispatchNoNodeSelectionForCopy]);

const reorderSubtree = useCallback(
(parentNodeId, orderedChildrenNodeIds) => {
Expand Down Expand Up @@ -371,16 +387,30 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
isInitiatingCopyTab.current = true;
dispatchNodeSelectionForCopy(studyUuid, nodeId, CopyType.NODE_COPY);
broadcastChannel.postMessage({
sourceStudyUuid: studyUuid,
nodeId: nodeId,
copyType: CopyType.NODE_COPY,
nodeToCopy: {
sourceStudyUuid: studyUuid,
nodeId: nodeId,
copyType: CopyType.NODE_COPY,
},
message: 'copiedNodeUpdateMsg',
});
};

const handleCutNode = (nodeId) => {
nodeId
? dispatchNodeSelectionForCopy(studyUuid, nodeId, CopyType.NODE_CUT)
: dispatch(setNodeSelectionForCopy(noNodeSelectionForCopy));
if (nodeId) {
dispatchNodeSelectionForCopy(studyUuid, nodeId, CopyType.NODE_CUT);
broadcastChannel.postMessage({
nodeToCopy: noNodeSelectionForCopy,
message: 'copiedNodeInvalidationMsgFromOtherStudy',
});
} else {
dispatchNoNodeSelectionForCopy();
broadcastChannel.postMessage({
nodeToCopy: noNodeSelectionForCopy,
message: null,
});
}
isInitiatingCopyTab.current = false;
};

const handlePasteNode = useCallback(
Expand All @@ -395,7 +425,7 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
}
);
//Do not wait for the response, after the first CUT / PASTE operation, we can't paste anymore
dispatch(setNodeSelectionForCopy(noNodeSelectionForCopy));
dispatchNoNodeSelectionForCopy();
} else if (CopyType.NODE_COPY === nodeSelectionForCopyRef.current.copyType) {
copyTreeNode(
nodeSelectionForCopyRef.current.sourceStudyUuid,
Expand All @@ -412,7 +442,7 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
//In copy/paste, we can still paste the same node later
}
},
[studyUuid, dispatch, snackError]
[studyUuid, dispatchNoNodeSelectionForCopy, snackError]
);

const handleRemoveNode = useCallback(
Expand Down Expand Up @@ -524,16 +554,30 @@ export const NetworkModificationTreePane = ({ studyUuid, currentRootNetworkUuid
isInitiatingCopyTab.current = true;
dispatchNodeSelectionForCopy(studyUuid, nodeId, CopyType.SUBTREE_COPY);
broadcastChannel.postMessage({
sourceStudyUuid: studyUuid,
nodeId: nodeId,
copyType: CopyType.SUBTREE_COPY,
nodeToCopy: {
sourceStudyUuid: studyUuid,
nodeId: nodeId,
copyType: CopyType.SUBTREE_COPY,
},
message: 'copiedNodeInvalidationMsgFromOtherStudy',
});
};

const handleCutSubtree = (nodeId) => {
nodeId
? dispatchNodeSelectionForCopy(studyUuid, nodeId, CopyType.SUBTREE_CUT)
: dispatch(setNodeSelectionForCopy(noNodeSelectionForCopy));
if (nodeId) {
dispatchNodeSelectionForCopy(studyUuid, nodeId, CopyType.SUBTREE_CUT);
broadcastChannel.postMessage({
nodeToCopy: noNodeSelectionForCopy,
message: 'copiedNodeInvalidationMsgFromOtherStudy',
});
} else {
dispatchNoNodeSelectionForCopy();
broadcastChannel.postMessage({
nodeToCopy: noNodeSelectionForCopy,
message: null,
});
}
isInitiatingCopyTab.current = false;
};

const handlePasteSubtree = useCallback(
Expand Down
15 changes: 10 additions & 5 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@

"moveStudyNotification": "The study has been moved from {oldStudyPath} to {studyPath}",

"CopiedNodeInvalidationMessage": "As a result of node modification, the contents of the clipboard have been deleted",
"CopiedModificationInvalidationMessage": "Following a modification of the hypothesis, the content of the clipboard has been deleted",
"CopiedModificationInvalidationMessageFromAnotherStudy": "Following a change in the modifications in another study, the content of the clipboard has been deleted",
"CopiedModificationUpdateMessageFromAnotherStudy": "As a result of copying modifications from another study, the content of the clipboard has been updated",
"CopiedModificationInvalidationMessageAfterTabClosure": "As a result of closing the tab from another study, the content of the clipboard has been deleted",
"copiedNodeInvalidationMsg": "Clipboard content cleared due to changes in nodes",
"copiedNodeInvalidationMsgFromOtherStudy": "Clipboard content cleared due to changes in nodes in another study",
"copiedNodeInvalidationMsgFromStudyClosure": "Clipboard content cleared due to a study being closed",
"copiedNodeUpdateMsg": "Clipboard content updated after copying a node in another study",

"copiedModificationsInvalidationMsg": "Clipboard content cleared due to changes in modifications",
"copiedModificationsInvalidationMsgFromOtherStudy": "Clipboard content cleared due to changes in modifications in another study",
"copiedModificationsInvalidationMsgFromStudyClosure": "Clipboard content cleared due to a study being closed",
"copiedModificationsUpdateMsg": "Clipboard content updated after copying modifications in another study",

"exportNetwork": "Export the network",
"export": "Export",
"download.fileName": "File name",
Expand Down
15 changes: 10 additions & 5 deletions src/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@

"moveStudyNotification": "L'étude a été déplacée de {oldStudyPath} à {studyPath}",

"CopiedNodeInvalidationMessage": "Suite à modification de nœud, le contenu du presse papier a été supprimé",
"CopiedModificationInvalidationMessage": "Suite à modification d'hypothèse, le contenu du presse papier a été supprimé",
"CopiedModificationInvalidationMessageFromAnotherStudy": "Suite à un changement des modifications dans une autre étude, le contenu du presse papier a été supprimé",
"CopiedModificationUpdateMessageFromAnotherStudy": "Suite à la copie de modifications dans une autre étude, le presse papier a été modifié",
"CopiedModificationInvalidationMessageAfterTabClosure": "Suite à la fermeture de l'onglet d'une autre étude, le presse papier a été supprimé",
"copiedNodeInvalidationMsg": "Contenu du presse-papier supprimé, suite à un changement dans les noeuds",
"copiedNodeInvalidationMsgFromOtherStudy": "Contenu du presse-papier supprimé, suite à un changement dans les noeuds dans une autre étude",
"copiedNodeInvalidationMsgFromStudyClosure": "Contenu du presse-papier supprimé, suite à la fermeture d'une étude",
"copiedNodeUpdateMsg": "Contenu du presse-papier mis à jour, suite à la copie d'un noeud dans une autre étude",

"copiedModificationsInvalidationMsg": "Contenu du presse-papier supprimé, suite à un changement dans les modifications",
"copiedModificationsInvalidationMsgFromOtherStudy": "Contenu du presse-papier supprimé, suite à un changement dans les modifications dans une autre étude",
"copiedModificationsInvalidationMsgFromStudyClosure": "Contenu du presse-papier supprimé, suite à la fermeture d'une étude",
"copiedModificationsUpdateMsg": "Contenu du presse-papier mis à jour, suite à la copie de modifications dans une autre étude",

"exportNetwork": "Exporter le réseau",
"export": "Exporter",
"download.fileName": "Nom de fichier",
Expand Down
Loading