diff --git a/frontend/src/api/datamanager.js b/frontend/src/api/datamanager.js index 9bef9bc5a..afdf44bba 100644 --- a/frontend/src/api/datamanager.js +++ b/frontend/src/api/datamanager.js @@ -188,3 +188,33 @@ export const deleteByQuery = (ids, parentId) => { }) } +export const saveTreeView = (tree) => { + return axios({ + url: '/api/tree', + method: 'POST', + data: { tree } + }) +} + +export const getTreeView = () => { + return axios({ + url: '/api/tree', + method: 'GET' + }) +} + +export const saveTreeViewOpenNodes = (openNodes) => { + return axios({ + url: '/api/tree/open-nodes', + method: 'POST', + data: { openNodes } + }) +} + +export const getTreeViewOpenNodes = () => { + return axios({ + url: '/api/tree/open-nodes', + method: 'GET' + }) +} + diff --git a/frontend/src/components/DocumentTree.vue b/frontend/src/components/DocumentTree.vue index c88100fac..cfd637a34 100644 --- a/frontend/src/components/DocumentTree.vue +++ b/frontend/src/components/DocumentTree.vue @@ -15,6 +15,7 @@ hoverable :open="groupListOpenNode" + item-key="id" style="padding-left:0px" > @@ -145,6 +146,7 @@ export default { resetGroupListOpenNode (payload) { for (const node of this.$store.state.dataManager.groupListOpenNode) { this.$store.commit('deleteGroupListOpenNode', node.id) + this.$store.dispatch('saveTreeViewOpenNodes', this.$store.state.dataManager.groupListOpenNode) } for (const parent of payload.parent) { this.$store.commit('addGroupListOpenNode', parent.id) diff --git a/frontend/src/components/DocumentTreeNode.vue b/frontend/src/components/DocumentTreeNode.vue index 31181d83f..7a67b5847 100644 --- a/frontend/src/components/DocumentTreeNode.vue +++ b/frontend/src/components/DocumentTreeNode.vue @@ -58,7 +58,7 @@ @@ -174,18 +174,21 @@ export default { this.$store.commit('setDeleteDialogSource', 'single') this.$store.commit('setIsShownDeleteDialog', true) }, - changeMenuStatus (e) { + changeMenuStatus (data, e) { e.preventDefault() + this.$store.commit('setFocusedLeaf', data) this.$store.commit('setIsShownNodeMenu', true) this.$store.commit('setShownNodeMenuPosition', {'x': e.clientX, 'y': e.clientY}) }, onToggleStatusChange () { if (this.isNodeOpen) { this.$store.commit('deleteGroupListOpenNode', this.data.id) + this.$store.dispatch('saveTreeViewOpenNodes', this.$store.state.dataManager.groupListOpenNode) return } if (!this.isLoadTreeAsync) { this.$store.commit('addGroupListOpenNode', this.data.id) + this.$store.dispatch('saveTreeViewOpenNodes', this.$store.state.dataManager.groupListOpenNode) return } if (this.isLoading) { @@ -198,6 +201,8 @@ export default { this.data.children = response.data.data this.isLoading = false this.$store.commit('addGroupListOpenNode', this.data.id) + this.$store.dispatch('saveTreeView', this.$store.state.dataManager.treeData) + this.$store.dispatch('saveTreeViewOpenNodes', this.$store.state.dataManager.groupListOpenNode) }) .catch(error => { this.$bus.$emit('msg.error', 'Load group ' + this.data.name + ' children error: ' + error.data.message) @@ -207,6 +212,9 @@ export default { if (!this.editable) { return } + this.$store.commit('setFocusedLeaf', this.data) + this.$store.dispatch('saveTreeViewOpenNodes', this.$store.state.dataManager.groupListOpenNode) + this.$store.dispatch('saveTreeView', this.$store.state.dataManager.treeData) this.$store.commit('setFocusNodeInfo', this.data) if (this.data.type === 'group') { this.$store.dispatch('loadGroupDetail', this.data) diff --git a/frontend/src/components/DocumentTreeNodeMenu.vue b/frontend/src/components/DocumentTreeNodeMenu.vue index 422c73735..45844251e 100644 --- a/frontend/src/components/DocumentTreeNodeMenu.vue +++ b/frontend/src/components/DocumentTreeNodeMenu.vue @@ -154,6 +154,8 @@ export default { }, onTreeNodeCut () { this.$store.dispatch('cutGroupOrData', this.data) + let targetNode = this.findNode(this.$store.state.dataManager.treeData, this.data.parent_id) + targetNode.children = targetNode.children.filter(item => item.id != this.data.id) }, onTreeNodeCopy () { this.$store.dispatch('copyGroupOrData', this.data) @@ -166,7 +168,26 @@ export default { this.$store.commit('setIsShownDuplicateDialog', true) return } - this.$store.dispatch('duplicateGroupOrData', this.data) + let targetNode = this.findNode(this.$store.state.dataManager.treeData, this.data.parent_id) + this.$store.dispatch('duplicateGroupOrData', { + data: this.data, + targetTreeNode: targetNode + }) + }, + findNode (tree, parent_id) { + if (!tree) { return null} + for (let node of tree) { + if (node.id == parent_id) { + return node + } + if (!this.$store.state.dataManager.groupListOpenNode.includes(node.id)) { + continue + } + let result = this.findNode(node.children, parent_id) + if (result) { + return result + } + } }, onTreeNodeAddGroup () { this.$store.commit('setIsShownCreateDialog', true) diff --git a/frontend/src/store/datamanager.js b/frontend/src/store/datamanager.js index 457ea40df..11eb97f33 100644 --- a/frontend/src/store/datamanager.js +++ b/frontend/src/store/datamanager.js @@ -6,7 +6,7 @@ export default { state: { title: 'Mock Data', treeSearchStr: '', - groupList: [], + treeData: [], conflictInfo: null, isLoadConflictInfo: false, groupListOpenNode: [], @@ -34,7 +34,6 @@ export default { isLabelDisplay: true, isDisplayConfiguration: false, isLoadTreeAsync: false, - isReloadTreeWhenUpdate: false, undisplayedKey: ['children', 'type', 'parent_id', 'abs_parent_path', 'parent', 'link'], undeletableKey: ['id', 'rule', 'name', 'label', 'category', 'super_by'], uneditableKey: ['id', 'rule', 'super_by'], @@ -43,6 +42,7 @@ export default { treeUndeletableId: [], temporaryMockDataList: [], tempGroupId: 'tmp_group', + focusedLeaf: {} }, mutations: { setTitle (state, title) { @@ -51,8 +51,11 @@ export default { setTreeSearchStr (state, treeSearchStr) { state.treeSearchStr = treeSearchStr }, - setGroupList (state, groupList) { - state.groupList = groupList + setTreeData (state, treeData) { + state.treeData = treeData + }, + setFocusedLeaf (state, focusedLeaf) { + state.focusedLeaf = focusedLeaf }, setConflictInfo (state, conflictInfo) { state.conflictInfo = conflictInfo @@ -161,9 +164,6 @@ export default { setUndisplayedKey (state, undisplayedKey) { state.undisplayedKey = undisplayedKey }, - setIsReloadTreeWhenUpdate (state, isReloadTreeWhenUpdate) { - state.isReloadTreeWhenUpdate = isReloadTreeWhenUpdate - }, concatUndisplayedKey (state, undisplayedKey) { state.undisplayedKey = state.undisplayedKey.concat(undisplayedKey) }, @@ -193,6 +193,40 @@ export default { }, }, actions: { + saveTreeView ({ }, payload) { + api.saveTreeView(payload) + .then(response => { + }) + .catch(error => { + bus.$emit('msg.error', 'Save treeview failed: ' + error.data.message) + }) + }, + getTreeView ({ commit }) { + api.getTreeView() + .then(response => { + commit('setTreeData', response.data.data) + }) + .catch(error => { + bus.$emit('msg.error', 'Get treeview failed: ' + error.data.message) + }) + }, + saveTreeViewOpenNodes ({ }, payload) { + api.saveTreeViewOpenNodes(payload) + .then(response => { + }) + .catch(error => { + bus.$emit('msg.error', 'Save treeview openNodes failed: ' + error.data.message) + }) + }, + getTreeViewOpenNodes ({ commit }) { + api.getTreeViewOpenNodes() + .then(response => { + commit('setGroupListOpenNode', response.data.data) + }) + .catch(error => { + bus.$emit('msg.error', 'Get treeview openNodes failed: ' + error.data.message) + }) + }, loadDataMap ({ state, commit }) { return new Promise((resolve, reject) => { setTimeout(() => { @@ -201,18 +235,18 @@ export default { if (state.isLoadTreeAsync) { api.getGroupMap({labels: state.dataListSelectedLabel}) .then(response => { - commit('setGroupList', [response.data.data]) + commit('setTreeData', [response.data.data]) commit('concatTreeUndeletableId', response.data.data.id) api.getGroupChildren(response.data.data.id) .then(r => { - state.groupList[0].children = [] - state.groupList[0].children.push(...r.data.data) + state.treeData[0].children = [] + state.treeData[0].children.push(...r.data.data) commit('addGroupListOpenNode', response.data.data.id) commit('setIsLoading', false) }) .catch(error => { - bus.$emit('msg.error', 'Load group ' + state.groupList[0].name + ' children error: ' + error) + bus.$emit('msg.error', 'Load group ' + state.treeData[0].name + ' children error: ' + error) commit('setIsLoading', false) }) @@ -226,7 +260,7 @@ export default { api.getGroupMap({labels: state.dataListSelectedLabel}) .then(response => { commit('addGroupListOpenNode', response.data.data.id) - commit('setGroupList', [response.data.data]) + commit('setTreeData', [response.data.data]) commit('concatTreeUndeletableId', response.data.data.id) commit('setIsLoading', false) }) @@ -260,11 +294,8 @@ export default { saveDataDetail ({ state, commit, dispatch }, payload) { api.updateData(payload) .then(response => { + state.focusedLeaf.name = payload.name dispatch('loadDataDetail', payload) - if (state.isReloadTreeWhenUpdate) { - dispatch('loadDataMap') - commit('setIsReloadTreeWhenUpdate', false) - } bus.$emit('msg.success', 'Data ' + payload.name + ' update!') }) .catch(error => { @@ -275,7 +306,7 @@ export default { if (groupName) { api.createGroup(groupName, parentId) .then(response => { - dispatch('loadDataMap') + dispatch('getTreeView') bus.$emit('msg.success', 'Group ' + groupName + ' created!') }) .catch(error => { @@ -289,18 +320,10 @@ export default { bus.$emit('msg.loading', 'Updating group ' + payload.name + ' ...') api.updateGroup(payload.id, payload) .then(response => { - if (state.isReloadTreeWhenUpdate) { - dispatch('loadDataMap') - dispatch('loadDataLabel') - commit('setIsReloadTreeWhenUpdate', false) - } + state.focusedLeaf.name = payload.name + commit('setFocusNodeInfo', response.data.message) dispatch('loadGroupDetail', payload) - bus.$emit('msg.destroy') - if (response.data.message && response.data.message.length > 0) { - bus.$emit('msg.info', response.data.message) - } else { - bus.$emit('msg.success', 'Group ' + payload.name + ' update!') - } + bus.$emit('msg.success', 'Group ' + payload.name + ' update!') }) .catch(error => { bus.$emit('msg.error', 'Group ' + payload.name + ' update error: ' + error.data.message) @@ -419,31 +442,45 @@ export default { bus.$emit('msg.error', payload.type + ' ' + payload.name + ' copy error: ' + error.data.message) }) }, - pasteGroupOrData ({ commit, dispatch }, payload) { + pasteGroupOrData ({ state, commit, dispatch }, payload) { bus.$emit('msg.loading', `Pasting ${payload.type} ${payload.name} ...`) api.pasteGroupOrData(payload.id) .then(response => { commit('addGroupListOpenNode', payload.id) - dispatch('loadDataMap') - bus.$emit('msg.destroy') - bus.$emit('msg.success', payload.type + ' ' + payload.name + ' paste success') + api.getGroupChildren(payload.id) + .then(response => { + state.focusedLeaf.children = response.data.data + commit('addGroupListOpenNode', payload.id) + }) + .catch(error => { + bus.$emit('msg.error', 'Load group ' + payload.name + ' children error: ' + error.data.message) + }) + .finally(() => { + bus.$emit('msg.destroy') + bus.$emit('msg.success', payload.type + ' ' + payload.name + ' paste success') + }) }) .catch(error => { bus.$emit('msg.error', payload.type + ' ' + payload.name + ' paste error: ' + error.data.message) }) }, - duplicateGroupOrData ({ commit, dispatch }, payload) { - bus.$emit('msg.loading', 'Duplicating group ' + payload.name + ' ...') - api.duplicateGroupOrData(payload.id) + duplicateGroupOrData ({ state, commit, dispatch }, payload) { + bus.$emit('msg.loading', 'Duplicating group ' + payload.data.name + ' ...') + api.duplicateGroupOrData(payload.data.id) .then(response => { - commit('addGroupListOpenNode', payload.parent_id) - commit('addGroupListOpenNode', response.data.id) - dispatch('loadDataMap') + api.getGroupChildren(payload.data.parent_id) + .then(_response => { + payload.targetTreeNode.children = _response.data.data + commit('addGroupListOpenNode', payload.data.parent_id) + }) + .catch(error => { + bus.$emit('msg.error', 'Load group ' + payload.data.name + ' children error: ' + error.data) + }) bus.$emit('msg.destroy') bus.$emit('msg.info', response.data.message) }) .catch(error => { - bus.$emit('msg.error', payload.type + ' ' + payload.name + ' duplicate error: ' + error.data.message) + bus.$emit('msg.error', payload.data.type + ' ' + payload.data.name + ' duplicate error: ' + error.data.message) }) }, importSnapshot ({ state, commit, dispatch }, snapshotId) { @@ -468,10 +505,12 @@ export default { bus.$emit('msg.error', 'Load snapshot information error: ' + err.data.message) }) }, - deleteByQuery ({ state, commit }, payload) { + deleteByQuery ({ state, commit, dispatch }, payload) { bus.$emit('msg.loading', 'Deleting ' + payload.length + ' items ...') api.deleteByQuery(payload) .then(_ => { + dispatch('getTreeView') + dispatch('getTreeViewOpenNodes') commit('setFocusNodeInfo', {}) commit('setDeleteNode', []) commit('setSelectedNode', new Set()) diff --git a/frontend/src/store/inspector.js b/frontend/src/store/inspector.js index 487b47310..1a95f27ae 100644 --- a/frontend/src/store/inspector.js +++ b/frontend/src/store/inspector.js @@ -171,7 +171,6 @@ export default { api.saveSelectedFlow(state.selectedIds) .then(response => { bus.$emit('msg.success', state.selectedIds.length + ' flow saved!') - dispatch('loadDataMap') commit('clearSelectedFlows') commit('clearSelectedId') }) diff --git a/frontend/src/views/datamanager/DataDetail.vue b/frontend/src/views/datamanager/DataDetail.vue index 744dfc88c..3782964f0 100644 --- a/frontend/src/views/datamanager/DataDetail.vue +++ b/frontend/src/views/datamanager/DataDetail.vue @@ -31,9 +31,6 @@ export default { DataDetailFolder }, computed: { - groupDetail () { - return this.$store.state.dataManager.groupDetail - }, nodeInfo () { return this.$store.state.dataManager.focusNodeInfo }, diff --git a/frontend/src/views/datamanager/DataDetailHttpData.vue b/frontend/src/views/datamanager/DataDetailHttpData.vue index 8e9324d88..86bec4f99 100644 --- a/frontend/src/views/datamanager/DataDetailHttpData.vue +++ b/frontend/src/views/datamanager/DataDetailHttpData.vue @@ -215,8 +215,6 @@ export default { // Add Flag newData['lyrebirdInternalFlow'] = 'datamanager' - this.$store.commit('setIsReloadTreeWhenUpdate', this.dataDetail.name !== newData.name) - this.$store.dispatch('saveDataDetail', newData) }, onJsonPathChange (payload) { diff --git a/frontend/src/views/datamanager/DataDetailInfo.vue b/frontend/src/views/datamanager/DataDetailInfo.vue index 80b94e767..cc4f3bc4f 100644 --- a/frontend/src/views/datamanager/DataDetailInfo.vue +++ b/frontend/src/views/datamanager/DataDetailInfo.vue @@ -208,9 +208,6 @@ export default { }, set (val) { this.$store.commit('setGroupDetailItem', { key: this.infoKey, value: val }) - if (this.infoKey === 'name') { - this.$store.commit('setIsReloadTreeWhenUpdate', true) - } } }, infoValue () { diff --git a/frontend/src/views/datamanager/DataDetailPlainConfig.vue b/frontend/src/views/datamanager/DataDetailPlainConfig.vue index 34eb1d413..c1eaa9ce1 100644 --- a/frontend/src/views/datamanager/DataDetailPlainConfig.vue +++ b/frontend/src/views/datamanager/DataDetailPlainConfig.vue @@ -131,7 +131,6 @@ export default { const newData = {} Object.assign(newData, JSON.parse(this.editorCache.info)) newData['json'] = this.editorCache.json - this.$store.commit('setIsReloadTreeWhenUpdate', false) this.$store.dispatch('saveDataDetail', newData) }, onJsonPathChange (payload) { diff --git a/frontend/src/views/datamanager/DataDetailPlainJSON.vue b/frontend/src/views/datamanager/DataDetailPlainJSON.vue index 0732cb561..99c3d0e5d 100644 --- a/frontend/src/views/datamanager/DataDetailPlainJSON.vue +++ b/frontend/src/views/datamanager/DataDetailPlainJSON.vue @@ -131,7 +131,6 @@ export default { const newData = {} Object.assign(newData, JSON.parse(this.editorCache.info)) newData['json'] = this.editorCache.json - this.$store.commit('setIsReloadTreeWhenUpdate', this.dataDetail.name !== newData.name) this.$store.dispatch('saveDataDetail', newData) }, onJsonPathChange (payload) { diff --git a/frontend/src/views/datamanager/DataList.vue b/frontend/src/views/datamanager/DataList.vue index 773d4a7b1..1c6d21625 100644 --- a/frontend/src/views/datamanager/DataList.vue +++ b/frontend/src/views/datamanager/DataList.vue @@ -47,7 +47,7 @@ export default { }, computed: { treeData () { - return this.$store.state.dataManager.groupList + return this.$store.state.dataManager.treeData }, spinShow () { return this.$store.state.dataManager.isLoading diff --git a/frontend/src/views/datamanager/DataManager.vue b/frontend/src/views/datamanager/DataManager.vue index 57dd5266f..30eded2c1 100644 --- a/frontend/src/views/datamanager/DataManager.vue +++ b/frontend/src/views/datamanager/DataManager.vue @@ -64,8 +64,8 @@ export default { } }, computed: { - groupList () { - return this.$store.state.dataManager.groupList + treeData () { + return this.$store.state.dataManager.treeData }, isPreloadDataMap () { return this.$store.state.settings.preLoadFuncSet.has('loadDataMap') diff --git a/frontend/src/views/inspector/TempMockDrawer.vue b/frontend/src/views/inspector/TempMockDrawer.vue index 9efb7a63b..481fef185 100644 --- a/frontend/src/views/inspector/TempMockDrawer.vue +++ b/frontend/src/views/inspector/TempMockDrawer.vue @@ -40,7 +40,7 @@ export default { }, computed: { treeData () { - return this.$store.state.dataManager.groupList + return this.$store.state.dataManager.treeData }, temporaryMockDataList () { return this.$store.state.dataManager.temporaryMockDataList diff --git a/lyrebird/mock/blueprints/apis/__init__.py b/lyrebird/mock/blueprints/apis/__init__.py index 05bfafd70..41756cd70 100644 --- a/lyrebird/mock/blueprints/apis/__init__.py +++ b/lyrebird/mock/blueprints/apis/__init__.py @@ -2,7 +2,7 @@ from flask_restful import Api from .common import Status, WorkMode, Manifest, DiffMode, Render from .flow import Flow, FlowList -from .mock import MockData, MockGroup, ActivatedMockGroup, MockGroupByName, MockDataLabel +from .mock import MockData, MockGroup, ActivatedMockGroup, MockGroupByName, MockDataLabel, TreeView, OpenNodes from .config import Conf from .menu import Menu from .notice import Notice @@ -44,6 +44,8 @@ def after_request(response): api_source.add_resource(Copy, '/copy/') api_source.add_resource(Paste, '/paste/') api_source.add_resource(Duplicate, '/duplicate/') +api_source.add_resource(TreeView, '/tree') +api_source.add_resource(OpenNodes, '/tree/open-nodes') api_source.add_resource(MockGroup, '/group', '/group/', '/group/label/') api_source.add_resource(MockData, '/data', '/data/') api_source.add_resource(SearchMockDataByName, '/search/group/name/', '/search/group/name/') diff --git a/lyrebird/mock/blueprints/apis/mock.py b/lyrebird/mock/blueprints/apis/mock.py index 7025b0486..374daf430 100644 --- a/lyrebird/mock/blueprints/apis/mock.py +++ b/lyrebird/mock/blueprints/apis/mock.py @@ -17,6 +17,24 @@ ''' +class TreeView(Resource): + def get(self): + return application.make_ok_response(data=context.application.data_manager.tree) + + def post(self): + data = request.json.get('tree') + context.application.data_manager.tree = data + return context.make_ok_response() + +class OpenNodes(Resource): + def get(self): + return application.make_ok_response(data=context.application.data_manager.open_nodes) + + def post(self): + data = request.json.get('openNodes') + context.application.data_manager.open_nodes = data + return context.make_ok_response() + class MockGroup(Resource): """ mock数据组 @@ -62,6 +80,8 @@ def get(self, group_id=None, label=None): if application.config.get(CONFIG_TREE_LOAD_CHILDREN_ASYNC): # Although async, reload is needed data_map = context.application.data_manager.root_without_children() + context.application.data_manager.tree = [data_map] + context.application.data_manager.open_nodes = [data_map['id']] return application.make_ok_response(data=data_map) root = context.application.data_manager.root diff --git a/lyrebird/mock/dm/__init__.py b/lyrebird/mock/dm/__init__.py index 26a2a89e8..b8c25dfe3 100644 --- a/lyrebird/mock/dm/__init__.py +++ b/lyrebird/mock/dm/__init__.py @@ -53,6 +53,9 @@ def __init__(self): # init temp mock self.temp_mock_tree = TempMock() + self.tree = [] + self.open_nodes = [] + @property def snapshot_workspace(self): if not self._snapshot_workspace: @@ -650,6 +653,13 @@ def add_group(self, data): self.id_map[group_id] = new_group # Save prop self._adapter._add_group(new_group) + # Update tree + parent_children = self._get_group_children(parent_node['id']) + tree_target_node = self.get_target_node(self.tree, parent_node['id']) + if not tree_target_node: + context.emit('datamanagerUpdate') + else: + tree_target_node['children'] = parent_children return group_id def add_group_by_path(self, path): @@ -933,6 +943,7 @@ def update_group(self, _id, data, save=True, **kwargs): if not node: raise IDNotFound(_id) + old_name = node['name'] if node['name'] != data['name'] else '' # Remove unsave_key add by DataManager itself for key in self.unsave_keys: data.pop(key) if key in data else None @@ -955,17 +966,54 @@ def update_group(self, _id, data, save=True, **kwargs): node.update(update_data) # 2. Remove deleted key in node - delete_keys = [k for k in node if k not in data and k not in self.update_group_ignore_keys] + delete_keys = [k for k in node if k not in data and k not in self.update_group_ignore_keys and k not in self.unsave_keys] for key in delete_keys: node.pop(key) # 3. Update existed value - for key, value in data.items(): - if key in node: - node[key] = value + # 3. Modify abs_parent_path、parent、children + if old_name: + self.update_node_when_name_changed(node, _id, data['name'], old_name) + + # 4. Update tree + tree_target_node = self.get_target_node(self.tree, _id) + if tree_target_node: + tree_target_node.update(update_data) + for key in delete_keys: + tree_target_node.pop(key) + if old_name: + self.update_node_when_name_changed(tree_target_node, _id, data['name'], old_name) + if not message.get('message', None): + message['message'] = tree_target_node return message + def get_target_node(self, tree, id): + if not tree: + return + for node in tree: + if node['id'] not in self.open_nodes: + continue + if node['id'] == id: + return node + result = self.get_target_node(node.get('children', []), id) + if result is not None: + return result + + def update_node_when_name_changed(self, node, id, new_name, old_name): + abs_parent_path = node.get('abs_parent_path', '') + parts = abs_parent_path.rsplit(old_name, 1) + if len(parts) > 1: + abs_parent_path = new_name.join(parts) + node['abs_parent_path'] = abs_parent_path + + for parent in node.get('parent', []): + if (parent['id'] == id): + parent['name'] = new_name + + for child in node.get('children', []): + self.update_node_when_name_changed(child, id, new_name, old_name) + def update_data(self, _id, data): node = self.id_map.get(_id) if not node: @@ -976,10 +1024,17 @@ def update_data(self, _id, data): self.add_data(node['parent_id'], data, data_id=data['id']) return - if 'name' in data: + tree_target_node = None + if 'name' in data and node['name'] != data['name']: + self.update_node_when_name_changed(node, _id, data['name'], node['name']) + tree_target_node = self.get_target_node(self.tree, _id) + if tree_target_node: + tree_target_node['name'] = data['name'] + self.update_node_when_name_changed(tree_target_node, _id, data['name'], node['name']) node['name'] = data['name'] self._adapter._update_data(data) self._adapter._update_group(node) + return tree_target_node or node # ----- # Snapshot @@ -1127,6 +1182,21 @@ def delete_by_query(self, query): # Delete from ID mapping self.id_map.pop(id_) + # Modify tree + for id_ in node_delete_group_ids: + if id_ in self.open_nodes: + self.open_nodes.remove(id_) + + def delete_subtrees(tree, ids_to_delete): + new_tree = [] + for node in tree: + if node['id'] not in ids_to_delete: + node['children'] = delete_subtrees(node.get('children', []), ids_to_delete) + new_tree.append(node) + return new_tree + + self.tree = delete_subtrees(self.tree, id_list) + # Delete self._adapter._delete_group_by_query({'id': node_delete_group_ids}) self._adapter._delete_data_by_query({'id': node_delete_data_ids}) @@ -1136,8 +1206,6 @@ def delete_by_query(self, query): 'state': 'finish' }) - context.emit('datamanagerUpdate') - def update_by_query(self, query, data): return self.update_group(data.get('id'), data, query=query)