This article series will record the problems and solutions encountered in the secondary development of kityminder
Some colleagues reported that during the task execution of test cases, sometimes several test cases were omitted and not executed, but they couldn't find them for a long time. Therefore, we hope to have a function to support rapid filtering (shrinkage) of unnecessary use cases and retain the required use case content.
reflection
At this time, the function similar to brain map expansion is considered, which can quickly expand the primary menu / secondary menu. Therefore, what we need to do is to put away other successful and failed use cases when the user clicks only unexecuted use cases, and expand only unexecuted use cases, similar to the following figure:
In the figure above, we click the blocking above, and other nodes will be put away, and only the use case content of the blocking part will be expanded.
What should the overall process be like? Considering that this is a collaborative editing situation, the best way is to directly calculate the diff from the current brain map data to the filtered brain map data through the server, and then distribute the patch data to each end.
Therefore, our process is roughly as follows:
This logic looks ok in theory, no problem, and everything is good after being tested in the local environment.
As a result, the car overturned after going online. When the amount of data is relatively large, once the data filtering is carried out, the front end will be load ed for a long time, and the larger the amount of data, the whole browser will be stuck.
Through the investigation, it is found that the time spent in calculating diff in the background is basically negligible, so the problem is actually the logic of patch. We need to take a look patch
The logic of applyPatch involves minder layout(); This is actually a very heavy action. However, our patches data object is very large, which leads to applyPatch for a long time.
When I was at a loss, I suddenly remembered that our brain map also has the function of folding / expanding nodes at the same time. As shown below:
So I immediately learned about the realization of my own logic.
/** * @command ExpandToLevel * @description Expand the brain map to the specified level * @param {number} level Specify the level to expand to, with a minimum of 1. * @state * 0: Always available */ var ExpandToLevelCommand = kity.createClass('ExpandToLevelCommand', { base: Command, execute: function (km, level) { km.getRoot().traverse(function (node) { if (node.getLevel() < level) node.expand(); if (node.getLevel() == level && !node.isLeaf()) node.collapse(); }); km.refresh(100); }, enableReadOnly: true });
Here we suddenly realized that the logic involved in this area is actually handled by the front end itself, and then directly to the minder. There is no patch logic used here.
solve
Therefore, the next operation is relatively simple, that is to change the logic originally belonging to the background to the front end of the brain map to complete the logic processing.
We customized a minder filter node command to do this logic. The code is directly posted here.
expand.js
var FilterNodeCommand = kity.createClass("FilterNodeCommand", { base: Command, execute: function (km, progress) { // //Update the deployment status of the node function updateNodeExpandState(node, state) { if (!(state === STATE_EXPAND && typeof (node.getData(EXPAND_STATE_DATA)) === 'undefined')) { node.setData(EXPAND_STATE_DATA, state); } } // /** // * Extension node // * @param {*} node // */ function expandNode(node) { updateNodeExpandState(node, STATE_EXPAND); for (var i =0; i<node.getChildren().length; i++) { expandNode(node.getChildren()[i]); } } // /** // * Need to expand // * @param {*} node // * @param {*} progress // * @returns // */ function isNeedExpand(node, progress) { var data = node.getData(); if (typeof (data[PROGRESS_DATA]) === 'undefined') { if (node.getChildren().length === 0) { return progress == DEFAULT_VALUE; } else { var isNeedExpandFlag = false; for (var i =0; i<node.getChildren().length; i++) { if (isNeedExpand(node.getChildren()[i], progress)) { updateNodeExpandState(node.getChildren()[i], STATE_EXPAND); if (!isNeedExpandFlag) { isNeedExpandFlag = true; } } } if (isNeedExpandFlag) { return true; } else { updateNodeExpandState(node, STATE_COLLAPSE); } } } else if (data[PROGRESS_DATA] === progress) { expandNode(node); return true; } else { updateNodeExpandState(node, STATE_COLLAPSE); return false; } } var rootNode = km.getRoot(); isNeedExpand(rootNode, progress); // The root node must be set to the expanded state rootNode.setData(EXPAND_STATE_DATA, STATE_EXPAND); km.refresh(100); }, enableReadOnly: true })