- this.setState({
- shapeOptionOpen: !this.state.shapeOptionOpen
- })
+ onToggle={() => {
+ this.setState({
+ shapeOptionOpen: !this.state.shapeOptionOpen
+ });
+ appState.logger.addLog({eventName: `NodeShape`, elementName: `Global Shape`});
+ }
}
>
diff --git a/argo-scholar/src/components/panels/LabelsPanel.jsx b/argo-scholar/src/components/panels/LabelsPanel.jsx
index e57c6d3..06aa78c 100644
--- a/argo-scholar/src/components/panels/LabelsPanel.jsx
+++ b/argo-scholar/src/components/panels/LabelsPanel.jsx
@@ -16,7 +16,10 @@ class LabelsPanel extends React.Component {
id="hideAll"
iconName="eye-off"
className={Classes.FILL}
- onClick={() => appState.graph.frame.hideAllLabels()}
+ onClick={() => {
+ appState.graph.frame.hideAllLabels();
+ }
+ }
>
Hide All
@@ -25,7 +28,10 @@ class LabelsPanel extends React.Component {
id="showAll"
iconName="eye-on"
className={Classes.FILL}
- onClick={() => appState.graph.frame.showAllLabels()}
+ onClick={() => {
+ appState.graph.frame.showAllLabels();
+ }
+ }
>
Show All
@@ -34,7 +40,10 @@ class LabelsPanel extends React.Component {
id="hideSelected"
iconName="eye-off"
className={Classes.FILL}
- onClick={() => appState.graph.frame.hideSelectedLabels()}
+ onClick={() => {
+ appState.graph.frame.hideSelectedLabels();
+ }
+ }
>
Hide Selected
@@ -43,7 +52,10 @@ class LabelsPanel extends React.Component {
id="showSelected"
iconName="eye-on"
className={Classes.FILL}
- onClick={() => appState.graph.frame.showSelectedLabels()}
+ onClick={() => {
+ appState.graph.frame.showSelectedLabels();
+ }
+ }
>
Show Selected
diff --git a/argo-scholar/src/components/panels/SelectionPanel.jsx b/argo-scholar/src/components/panels/SelectionPanel.jsx
index a6d64ca..b222dc6 100644
--- a/argo-scholar/src/components/panels/SelectionPanel.jsx
+++ b/argo-scholar/src/components/panels/SelectionPanel.jsx
@@ -67,12 +67,14 @@ class SelectionPanel extends React.Component {
{
sizeOptionOpen: true
},
- () =>
+ () => {
this.batchTwoLayerUpdate(
appState.graph.selectedNodes,
"size",
appState.graph.overrideConfig.size
- )
+ );
+ appState.logger.addLog({eventName: `NodeSize`, elementName: `Selected Size`});
+ }
);
}
}}
@@ -117,12 +119,14 @@ class SelectionPanel extends React.Component {
{
colorOptionOpen: true
},
- () =>
+ () => {
this.batchTwoLayerUpdate(
appState.graph.selectedNodes,
"color",
appState.graph.overrideConfig.color
- )
+ );
+ appState.logger.addLog({eventName: `NodeColor`, elementName: `Selected Color`});
+ }
);
}
}}
@@ -183,12 +187,14 @@ class SelectionPanel extends React.Component {
{
labelOptionOpen: true
},
- () =>
+ () => {
this.batchTwoLayerUpdate(
appState.graph.selectedNodes,
"label",
appState.graph.overrideConfig.label
- )
+ );
+ appState.logger.addLog({eventName: `NodeLabel`, elementName: `Selected Label`});
+ }
);
}
}}
@@ -230,12 +236,14 @@ class SelectionPanel extends React.Component {
{
shapeOptionOpen: true
},
- () =>
+ () => {
this.batchTwoLayerUpdate(
appState.graph.selectedNodes,
"shape",
appState.graph.overrideConfig.shape
- )
+ );
+ appState.logger.addLog({eventName: `NodeShape`, elementName: `Selected Shape`});
+ }
);
}
}}
diff --git a/argo-scholar/src/components/panels/ZoomPanel.jsx b/argo-scholar/src/components/panels/ZoomPanel.jsx
index b94c80d..a7bea9d 100644
--- a/argo-scholar/src/components/panels/ZoomPanel.jsx
+++ b/argo-scholar/src/components/panels/ZoomPanel.jsx
@@ -38,6 +38,7 @@ class ZoomPanel extends React.Component {
targets: appState.controls.zoom,
percent: appState.controls.zoom.nextZoomInPercent
});
+ // appState.logger.addLog({eventName: `ZoomingIn`, elementName: `PlusButton`})
}}
>
@@ -54,6 +55,7 @@ class ZoomPanel extends React.Component {
targets: appState.controls.zoom,
percent: appState.controls.zoom.nextZoomOutPercent
});
+ // appState.logger.addLog({eventName: `ZoomingOut`, elementName: `MinusButton`})
}}>
@@ -66,6 +68,7 @@ class ZoomPanel extends React.Component {
iconName="home"
onClick={() => {
appState.controls.reset();
+ // appState.logger.addLog({eventName: `Reset Viewport`, elementName: `HomeButton`})
}}>
);
diff --git a/argo-scholar/src/graph-frontend/include/OrbitControls.js b/argo-scholar/src/graph-frontend/include/OrbitControls.js
index e6b80ce..487b3ff 100644
--- a/argo-scholar/src/graph-frontend/include/OrbitControls.js
+++ b/argo-scholar/src/graph-frontend/include/OrbitControls.js
@@ -506,7 +506,7 @@ module.exports = function(THREE) {
}
function handleMouseWheel(event) {
-
+ // console.log( "handleMouseWheel" )
mousePos = {x: event.clientX, y: event.clientY}
if (event.deltaY < 0) {
@@ -722,6 +722,8 @@ module.exports = function(THREE) {
function onMouseUp(event) {
if (scope.enabled === false) return;
+ // console.log( 'handleMouseDownPan' );
+ // appState.logger.addLog({eventName: `ViewportPan`, elementName: `ViewportPan`})
handleMouseUp(event);
@@ -770,7 +772,7 @@ module.exports = function(THREE) {
scope.enablePan === false
)
return;
-
+ // appState.logger.addLog({eventName: `ViewportPan`, elementName: `ViewportPan`})
handleKeyUp(event);
}
diff --git a/argo-scholar/src/graph-frontend/src/api.js b/argo-scholar/src/graph-frontend/src/api.js
index 070da23..f4d360f 100644
--- a/argo-scholar/src/graph-frontend/src/api.js
+++ b/argo-scholar/src/graph-frontend/src/api.js
@@ -1,3 +1,5 @@
+const { default: appState } = require("../../stores");
+
var def = require("./imports").default;
var THREE = def.THREE;
var Edge = def.Edge;
@@ -44,10 +46,12 @@ module.exports = function(self) {
};
self.pinSelectedNodes = () => {
+ appState.logger.addLog({eventName: `pinSelectedNodes`, elementName: self.selection.map(node => node.id)})
self.mapNodeAttributes([true, "", "pinned"], self.selection);
};
self.unpinSelectedNodes = () => {
+ appState.logger.addLog({eventName: `unpinSelectedNodes`, elementName: self.selection.map(node => node.id)})
self.mapNodeAttributes([false, "", "pinned"], self.selection);
};
@@ -139,16 +143,22 @@ module.exports = function(self) {
};
self.toggleSelectedLabels = () => {
+ appState.logger.addLog({eventName: 'ToggleSelectedLabels', elementName: self.selection.map(n => n.id)})
+
self.toggleLabels(self.selection.map(n => n.id));
};
self.showSelectedLabels = () => {
+ appState.logger.addLog({eventName: 'ShowSelectedLabels', elementName: self.selection.map(n => n.id)})
+
document.getElementById("showSelected").style.display="none";
document.getElementById("hideSelected").style.display="inline";
self.showLabels(self.selection.map(n => n.id));
};
self.hideSelectedLabels = () => {
+ appState.logger.addLog({eventName: 'HideSelectedLabels', elementName: self.selection.map(n => n.id)})
+
document.getElementById("hideSelected").style.display="none";
document.getElementById("showSelected").style.display="inline";
self.hideLabels(self.selection.map(n => n.id));
@@ -191,6 +201,8 @@ module.exports = function(self) {
};
self.hideAllLabels = () => {
+ appState.logger.addLog({eventName: 'HideAllLabels'})
+
document.getElementById("hideAll").style.display="none";
document.getElementById("showAll").style.display="inline";
self.graph.forEachNode(function(node) {
@@ -201,6 +213,8 @@ module.exports = function(self) {
};
self.showAllLabels = () => {
+ appState.logger.addLog({eventName: 'ShowAllNodes'})
+
document.getElementById("showAll").style.display="none";
document.getElementById("hideAll").style.display="inline";
self.graph.forEachNode(function(node) {
diff --git a/argo-scholar/src/graph-frontend/src/mouse.js b/argo-scholar/src/graph-frontend/src/mouse.js
index 058f01c..1ff77f3 100644
--- a/argo-scholar/src/graph-frontend/src/mouse.js
+++ b/argo-scholar/src/graph-frontend/src/mouse.js
@@ -207,8 +207,21 @@ module.exports = function (self) {
if(selection) {
//when any node is clicked, un-smartpause if smartpaused
//appState.graph.smartPause.lastUnpaused = Date.now(); //old code using lastUnpaused
+ // console.log(selection)
appState.graph.smartPause.interactingWithGraph = true;
- // appState.project.isAddPapersDialogOpen = false;
+ // appState.logger.addLog({eventName: `SelectNode`, elementName: selection.id, valueName: `Label`, newValue: selection.data.label});
+
+
+ // if (!inArray(selection, appState.graph.currentNodes)) {
+ // console.log("other node")
+ // appState.graph.currentNodes = selection
+ // appState.graph.currentNodeX = selection.x
+ // appState.graph.currentNodeY = selection.y
+ // }
+
+ appState.graph.currentNodes = {id: selection.id, x: selection.x, y: selection.y}
+ appState.graph.currentNodeX = selection.x
+ appState.graph.currentNodeY = selection.y
}
@@ -286,6 +299,105 @@ module.exports = function (self) {
self.showBox = false;
self.dragging = null;
self.selectBox.visible = false;
+
+ if (self.selection) {
+ if (self.selection.length == 1) {
+ var selected = self.selection[0]
+ // console.log("size 1")
+ // console.log(selected)
+ // console.log(appState.graph.currentNodes)
+
+ // console.log("========")
+
+ // console.log(selected.x)
+ // console.log(appState.graph.currentNodeX)
+
+ // console.log(selected.x !== appState.graph.currentNodeX)
+
+ // console.log("=======")
+ // console.log(selected.y)
+ // console.log(appState.graph.currentNodeY)
+
+ // console.log(selected.y - appState.graph.currentNodeY)
+
+ if (selected.id === appState.graph.currentNodes.id && (Math.abs(selected.x - appState.graph.currentNodeX) > 5 ||
+ Math.abs(selected. y - appState.graph.currentNodeY) > 5)) {
+ console.log("moved node");
+ var oldValues = {};
+ oldValues['x'] = appState.graph.currentNodeX;
+ oldValues['y'] = appState.graph.currentNodeY;
+
+ var newValues = {};
+ newValues['x'] = selected.x;
+ newValues['y'] = selected.y;
+
+ appState.logger.addLog({eventName: `MovedNode`, elementName: selection.id, valueName: `XYCoord`,
+ oldValue: oldValues, newValue: newValues});
+ appState.graph.currentNodeX = selected.x;
+ appState.graph.currentNodeY = selected.y;
+ }
+ } else if (self.selection.length > 1 && appState.graph.currentNodes) {
+ // console.log("===========")
+ // console.log(self.selection)
+ // console.log("currentNodes")
+ var oldNode = appState.graph.currentNodes
+ // console.log(selectedNode)
+ // console.log("In?")
+ var newNode = findNode(oldNode, self.selection)
+ // console.log(associatedNode)
+ if (newNode) {
+ var xDiff = newNode.x - oldNode.x;
+ var yDiff = newNode.y - oldNode.y;
+ if (Math.abs(xDiff) > 5 || Math.abs(yDiff) > 5) {
+ // console.log("selected")
+ // console.log(appState.graph.selectedNodes.slice())
+ // console.log("selection:")
+ // console.log(self.selection)
+ // console.log(arraysEqual(appState.graph.selectedNodes.slice(), self.selection))
+ var elements = []
+ var oldValues = {};
+ oldValuesX = [];
+ oldValuesY = [];
+
+ var newValues = {};
+ newValuesX = [];
+ newValuesY = [];
+ self.selection.forEach(node => {
+ elements.push(node.id);
+ oldValuesX.push(node.x - xDiff);
+ oldValuesY.push(node.y - yDiff);
+ newValuesX.push(node.x)
+ newValuesY.push(node.y);
+ });
+
+ oldValues['x'] = oldValuesX;
+ oldValues['y'] = oldValuesY;
+
+ newValues['x'] = newValuesX;
+ newValues['y'] = newValuesY;
+
+ appState.logger.addLog({eventName: `MovedNodes`, elementName: elements, valueName: `XYCoord`,
+ oldValue: oldValues, newValue: newValues});
+ console.log("moved selected nodes")
+ }
+ }
+
+ }
+ // appState.graph.currentNodes = self.selection;
+ // console.log("currentNodes:")
+ // console.log(appState.graph.currentNodes.slice())
+
+ // console.log("selection: ")
+ // console.log(self.selection)
+ // console.log("selected")
+ // console.log(appState.graph.selectedNodes[0])
+ // console.log(self.selection[0] === appState.graph.selectedNodes[0])
+ // if (self.selection == appState.graph.selectedNodes[0] && self.selection.x !== appState.graph.currentNodeX && self.selection.y !== appState.graph.currentNodeY) {
+ // console.log("moved node");
+ // appState.graph.currentNodeX = self.selection.x;
+ // appState.graph.currentNodeY = self.selection.y;
+ // }
+ }
self.ee.emit("select-nodes", self.selection);
}
diff --git a/argo-scholar/src/ipc/client.js b/argo-scholar/src/ipc/client.js
index d63f5ef..e21d21d 100644
--- a/argo-scholar/src/ipc/client.js
+++ b/argo-scholar/src/ipc/client.js
@@ -472,6 +472,7 @@ async function createEmptyPaperGraph() {
nodeProperties: ["id", "degree", "pagerank", "paperName", "paperAbstract", "authors", "citationCount", "venue", "year", "url", "node_id"],
nodeComputed: ['pagerank', 'degree'],
edgeProperties: ['source_id', 'target_id'],
+ snapshotId: `f${Math.round(Math.random() * 10000000, 0)}`
},
}
}
diff --git a/argo-scholar/src/ipc/logger.js b/argo-scholar/src/ipc/logger.js
new file mode 100644
index 0000000..47f2bc0
--- /dev/null
+++ b/argo-scholar/src/ipc/logger.js
@@ -0,0 +1,234 @@
+/**
+ * @typedef {Object} LogValue A value that an interaction event changes
+ * @property {string} name Value name
+ * @property {string | number | number[]} value Value
+ */
+
+/**
+ * @typedef {Object} Log A single event log
+ * @property {string} eventName A string from ['click', 'dragEnd',
+ * 'mouseEnter', 'mouseLeave']
+ * @property {string} elementName Name of element that handles the event
+ * @property {Date} time Timestamp for the event
+ * @property {LogValue | null} oldValue The old value that this interaction
+ * changes from
+ * @property {LogValue | null} newValue The new value that this interaction
+ * changes to
+ */
+import appState from "../stores";
+
+/**
+ * An object to log interaction events.
+ */
+export class Logger {
+ /**
+ * Initialize a new Logger object.
+ * @param {any} [initialValues] Any objects to store with the logger
+ */
+ constructor(initialValues = null) {
+ /** @type{Log[]} */
+ this.log = [];
+
+ this.initialValues = initialValues;
+
+ /** @type{Date} */
+ this.startTime = new Date();
+
+ this.id = Math.round(Math.random() * 1000, 0);
+
+ this.fileName = `f${this.startTime}-${this.id}.json`;
+ // Create a map to register any object on the fly
+ /** @type {object[][]} Each entry is [key, value, timestamp]*/
+ this.records = [];
+
+ this.logNum = 0;
+ }
+
+ /**
+ * Add a new log event
+ * @param {object} obj Smart parameter
+ * @param {string} obj.eventName A string from ['click', 'dragEnd',
+ * 'mouseEnter', 'mouseLeave'] or any other given name
+ * @param {string} obj.elementName Name of the element that users interact
+ * with
+ * @param {Date | null} [obj.time] Timestamp for the event
+ * @param {string | null} [obj.valueName] Name of the given value
+ * @param {string | number | null | number[]} [obj.oldValue] Old value that
+ * this interaction changes from
+ * @param {string | number | null | number[]} [obj.newValue] New value that
+ * this interaction changes to
+ */
+ addLog({
+ eventName,
+ elementName,
+ time = null,
+ valueName = null,
+ oldValue = null,
+ newValue = null
+ }) {
+ // Create a time stamp if it is not given
+ const timeStamp = time !== null ? time : new Date();
+
+ // Create value objects if they are given
+
+ /** @type {LogValue} */
+ let oldValueObj = null;
+
+ /** @type {LogValue} */
+ let newValueObj = null;
+
+ if (valueName !== null) {
+ if (oldValue !== null) {
+ oldValueObj = {
+ name: valueName,
+ value: oldValue
+ };
+ }
+ if (newValue !== null) {
+ newValueObj = {
+ name: valueName,
+ value: newValue
+ };
+ }
+ }
+
+ // Create a new Log object
+ /** @type {Log} */
+ const newLog = {
+ eventName,
+ elementName,
+ time: timeStamp,
+ oldValue: oldValueObj,
+ newValue: newValueObj
+ };
+
+ this.log.push(newLog);
+ this.logNum += 1;
+ if (this.logNum % 10 == 0) {
+ appState.logger.uploadToS3();
+ }
+ }
+
+ /**
+ * Overwrite the initial values
+ * @param {any} initialValues
+ */
+ setInitialValues(initialValues) {
+ this.initialValues = initialValues;
+ }
+
+ /**
+ * Add a key value pair to the internal record map.
+ * @param {string} key Key name
+ * @param {any} value Any serializable object
+ */
+ addRecord(key, value) {
+ this.records.push([key, value, new Date()]);
+ }
+
+ /**
+ * Detect what is the current browser and add the info to the record.
+ */
+ addBrowserRecord() {
+ let browser = 'unknown';
+ if (
+ (!!window.opr && !!opr.addons) ||
+ !!window.opera ||
+ navigator.userAgent.indexOf(' OPR/') >= 0
+ ) {
+ browser = 'opera';
+ } else if (typeof InstallTrigger !== 'undefined') {
+ browser = 'firefox';
+ } else if (
+ /constructor/i.test(window.HTMLElement) ||
+ (function (p) {
+ return p.toString() === '[object SafariRemoteNotification]';
+ })(
+ !window['safari'] ||
+ (typeof safari !== 'undefined' && window['safari'].pushNotification)
+ )
+ ) {
+ browser = 'safari';
+ } else if (/*@cc_on!@*/ false || !!document.documentMode) {
+ browser = 'ie';
+ } else if (!!window.StyleMedia) {
+ browser = 'edge';
+ } else if (
+ !!window.chrome &&
+ (!!window.chrome.webstore || !!window.chrome.runtime)
+ ) {
+ browser = 'chrome';
+ }
+
+ this.addRecord('browser', browser);
+ }
+
+ /**
+ * Detect the current OS and add the info to the record.
+ */
+ addOSRecord() {
+ let osName = 'Unknown OS';
+
+ if (navigator.userAgent.indexOf('Win') != -1) osName = 'windows';
+ if (navigator.userAgent.indexOf('Mac') != -1) osName = 'mac';
+ if (navigator.userAgent.indexOf('Linux') != -1) osName = 'linux';
+ if (navigator.userAgent.indexOf('Android') != -1) osName = 'android';
+ if (navigator.userAgent.indexOf('like Mac') != -1) osName = 'ios';
+
+ this.addRecord('os', osName);
+ }
+
+ /**
+ * Export the logs as a JSON string.
+ * @param {any} [endValues] Any values to exported with the log
+ */
+ toJSON(endValues = null) {
+ const exportLog = {
+ log: this.log,
+ startTime: this.startTime,
+ endTime: new Date(),
+ initialValues: this.initialValues,
+ endValues: endValues,
+ records: this.records,
+ key: this.fileName
+ };
+ return JSON.stringify(exportLog);
+ }
+
+ /**
+ * Upload the
+ */
+ async uploadToS3() {
+ try {
+ const url = 'https://argo-cors-anywhere.herokuapp.com/https://h5r94usqaf.execute-api.us-east-1.amazonaws.com/default/LogArgoActions';
+
+ const blob = new Blob([this.toJSON()], {type: 'application/json'});
+
+ fetch(url, {
+ method: 'POST',
+ keepalive: true,
+ body: blob
+ });
+
+ } catch (e) {
+ console.error('Failed to upload to S3');
+ // this.download();
+ return -1;
+ }
+
+ }
+
+ /**
+ * Download the log file as a JSON file.
+ */
+ download() {
+ downloadJSON(JSON.parse(this.toJSON()), null, 'strategy-data.json');
+ }
+}
+
+window.addEventListener('beforeunload', (event) => {
+ if (appState.logger.logNum > 3) {
+ appState.logger.uploadToS3();
+ }
+ }
+);
\ No newline at end of file
diff --git a/argo-scholar/src/services/BackendAPIUtils.js b/argo-scholar/src/services/BackendAPIUtils.js
index 61b443e..2e3b03f 100644
--- a/argo-scholar/src/services/BackendAPIUtils.js
+++ b/argo-scholar/src/services/BackendAPIUtils.js
@@ -180,10 +180,15 @@ export function addSortedCitations(sortMethod, graph) {
}
Promise.all(fetches).then(() => {
+ var nodeLabels = []
+ var nodeIds = []
addedNodes.forEach((node) => {
appState.graph.selectedNodes.push(node);
appState.graph.frame.selection.push(node);
+ nodeLabels.push(node.data.label);
+ nodeIds.push(node.id);
});
+ appState.logger.addLog({eventName: `AddCitation${sortMethod}`, elementName: rightClickedNodeId, valueName: nodeLabels, newValue: nodeIds});
});
})
// Error message, using backup method instead
@@ -317,10 +322,15 @@ function addRandomCitations(graph) {
}
Promise.all(fetches).then(() => {
+ var nodeLabels = [];
+ var nodeIds = [];
addedNodes.forEach((node) => {
appState.graph.selectedNodes.push(node);
appState.graph.frame.selection.push(node);
+ nodeLabels.push(node.data.label);
+ nodeIds.push(node.id);
});
+ appState.logger.addLog({eventName: `AddCitationRandom`, elementName: rightClickedNodeId, valueName: nodeIds, newValue: nodeLabels});
});
})
.catch((error) => {
@@ -475,10 +485,15 @@ export function addSortedReferences(sortMethod, graph) {
}
Promise.all(fetches).then((response) => {
+ var nodeLabels = []
+ var nodeIds = []
addedNodes.forEach((node) => {
appState.graph.selectedNodes.push(node);
appState.graph.frame.selection.push(node);
+ nodeLabels.push(node.data.label);
+ nodeIds.push(node.id);
});
+ appState.logger.addLog({eventName: `AddReference${sortMethod}`, elementName: rightClickedNodeId, valueName: nodeIds, newValue: nodeLabels});
});
})
// Error message, using backup method instead
@@ -594,10 +609,15 @@ function addRandomReferences(graph) {
});
}
Promise.all(fetches).then((response) => {
+ var nodeLabels = [];
+ var nodeIds = [];
addedNodes.forEach((node) => {
appState.graph.selectedNodes.push(node);
appState.graph.frame.selection.push(node);
+ nodeLabels.push(node.data.label);
+ nodeIds.push(node.id);
});
+ appState.logger.addLog({eventName: `AddReferenceRandom`, elementName: rightClickedNodeId, valueName: nodeIds, newValue: nodeLabels});
});
})
.catch((error) => {
diff --git a/argo-scholar/src/stores/GraphStore.js b/argo-scholar/src/stores/GraphStore.js
index d49083b..745c8b6 100644
--- a/argo-scholar/src/stores/GraphStore.js
+++ b/argo-scholar/src/stores/GraphStore.js
@@ -136,6 +136,7 @@ export default class GraphStore {
nodeComputed: ["pagerank", "degree"],
edgeProperties: [],
snapshotName: "loading...", // Optional: for display in Argo-scholar only
+ snapshotId: "",
};
// used for listing all the properties, either original or computed
@@ -373,6 +374,7 @@ export default class GraphStore {
}
showNodes(nodeids) {
+ appState.logger.addLog({eventName: 'ShowNodes', elementName: nodeids})
runInAction("show hidden nodes by ids", () => {
this.rawGraph.nodes = this.rawGraph.nodes.map((n) => {
if (nodeids.includes(n.id)) {
@@ -384,6 +386,7 @@ export default class GraphStore {
}
hideNodes(nodeids) {
+ appState.logger.addLog({eventName: 'HideNodes', elementName: nodeids})
runInAction("hide nodes by ids", () => {
this.frame.removeNodesByIds(nodeids);
this.rawGraph.nodes = this.rawGraph.nodes.map((n) => {
@@ -408,6 +411,9 @@ export default class GraphStore {
}
getSnapshot() {
+ if (!this.metadata.snapshotId) {
+ this.metadata.snapshotId = `${Math.round(Math.random() * 10000000, 0)}`;
+ }
const snapshot = {
rawGraph: this.rawGraph,
overrides: this.overrides,
@@ -604,10 +610,7 @@ export default class GraphStore {
}),
this.frame.rightClickedNode &&
MenuDividerFactory({
- title: "Add Citations or References",
- key: "Add Citations or References",
}),
- this.frame.rightClickedNode &&
MenuItemFactory({
children: [
MenuItemFactory({
@@ -621,8 +624,8 @@ export default class GraphStore {
onClick: () => {
BackendAPIUtils.addSortedCitations("is-influential", this);
},
- text: "Sort By Most Infleunced Papers",
- key: "Sort By Most Infleunced Papers",
+ text: "Sort By Most Influenced Papers",
+ key: "Sort By Most Influenced Papers",
}),
MenuItemFactory({
onClick: () => {
@@ -656,8 +659,8 @@ export default class GraphStore {
onClick: () => {
BackendAPIUtils.addSortedReferences("is-influential", this);
},
- text: "Sort By Most Infleunced Papers",
- key: "Sort By Most Infleunced Papers",
+ text: "Sort By Most Influenced Papers",
+ key: "Sort By Most Influenced Papers",
}),
MenuItemFactory({
onClick: () => {
diff --git a/argo-scholar/src/stores/index.js b/argo-scholar/src/stores/index.js
index f90b08f..7535a2a 100644
--- a/argo-scholar/src/stores/index.js
+++ b/argo-scholar/src/stores/index.js
@@ -9,6 +9,7 @@ import ProjectStore from "./ProjectStore";
import parse from "csv-parse/lib/sync";
import SearchStore from "./SearchStore";
import { runSearch } from "../ipc/client";
+import { Logger } from "../ipc/logger";
import { BACKEND_URL, SAMPLE_GRAPH_SNAPSHOTS } from "../constants";
import { toaster } from "../notifications/client";
@@ -20,6 +21,7 @@ export class AppState {
this.import = new ImportStore();
this.search = new SearchStore();
this.project = new ProjectStore();
+ this.logger = new Logger();
}
}
@@ -35,7 +37,7 @@ const loadSnapshotFromURL = (url) => {
.then((response) => response.text())
.catch((error) => {
toaster.show({
- message: "Failed to fetch graph snapshot.",
+ message: "Failed to fetch graph snapshot",
intent: Intent.DANGER,
timeout: -1,
iconName: "warning-sign",
@@ -54,7 +56,7 @@ const loadSnapshotFromStrapi = (uuid) => {
.then((json) => json[0].body)
.catch((error) => {
toaster.show({
- message: "Failed to fetch graph snapshot.",
+ message: "Failed to fetch graph snapshot",
intent: Intent.DANGER,
timeout: -1,
iconName: "warning-sign",
@@ -66,6 +68,7 @@ const loadSnapshotFromStrapi = (uuid) => {
const loadAndDisplaySnapshotFromURL = (url) => {
loadSnapshotFromURL(url).then((snapshotString) => {
// use filename/last segment of URL as title in Navbar
+ appState.logger.addLog({eventName: `LoadSnapshotFromURL`, elementName: url});
appState.graph.metadata.snapshotName =
url.split("/").pop() || url.split("/").pop().pop();
appState.graph.loadImmediateStates(snapshotString);
@@ -75,6 +78,7 @@ const loadAndDisplaySnapshotFromURL = (url) => {
const loadAndDisplaySnapshotFromStrapi = (uuid) => {
loadSnapshotFromStrapi(uuid).then((snapshotString) => {
// TODO: use more sensible snapshot name
+ appState.logger.addLog({eventName: `LoadSnapshotFromStrapi`, elementName: uuid});
appState.graph.metadata.snapshotName = "Shared";
appState.graph.loadImmediateStates(snapshotString);
});