Drastically improved tree tab search UX for locating parts of the sheet
This commit is contained in:
@@ -7,7 +7,7 @@ import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/
|
|||||||
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
||||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
|
||||||
import { recomputeCreatureByDoc } from '/imports/api/creature/computation/methods/recomputeCreature.js';
|
import { recomputeCreatureByDoc } from '/imports/api/creature/computation/methods/recomputeCreature.js';
|
||||||
import { nodesToTree } from '/imports/api/parenting/parenting.js';
|
import nodesToTree from '/imports/api/parenting/nodesToTree.js';
|
||||||
import applyProperties from '/imports/api/creature/actions/applyProperties.js';
|
import applyProperties from '/imports/api/creature/actions/applyProperties.js';
|
||||||
import recomputeInventory from '/imports/api/creature/denormalise/recomputeInventory.js';
|
import recomputeInventory from '/imports/api/creature/denormalise/recomputeInventory.js';
|
||||||
import recomputeInactiveProperties from '/imports/api/creature/denormalise/recomputeInactiveProperties.js';
|
import recomputeInactiveProperties from '/imports/api/creature/denormalise/recomputeInactiveProperties.js';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||||
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
import Creatures from '/imports/api/creature/creatures/Creatures.js';
|
||||||
import { nodesToTree } from '/imports/api/parenting/parenting.js';
|
import nodesToTree from '/imports/api/parenting/nodesToTree.js';
|
||||||
|
|
||||||
export default function recomputeInventory(creatureId){
|
export default function recomputeInventory(creatureId){
|
||||||
let inventoryForest = nodesToTree({
|
let inventoryForest = nodesToTree({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { nodesToTree } from '/imports/api/parenting/parenting.js';
|
import nodesToTree from '/imports/api/parenting/nodesToTree.js';
|
||||||
|
|
||||||
export default function getDescendantsInDepthFirstOrder({
|
export default function getDescendantsInDepthFirstOrder({
|
||||||
collection,
|
collection,
|
||||||
|
|||||||
115
app/imports/api/parenting/nodesToTree.js
Normal file
115
app/imports/api/parenting/nodesToTree.js
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import { union, difference, sortBy, findLast } from 'lodash';
|
||||||
|
|
||||||
|
export function nodeArrayToTree(nodes){
|
||||||
|
// Store a dict and list of all the nodes
|
||||||
|
let nodeIndex = {};
|
||||||
|
let nodeList = [];
|
||||||
|
nodes.forEach( node => {
|
||||||
|
let treeNode = {
|
||||||
|
node: node,
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
nodeIndex[node._id] = treeNode;
|
||||||
|
nodeList.push(treeNode);
|
||||||
|
});
|
||||||
|
// Create a forest of trees
|
||||||
|
let forest = [];
|
||||||
|
// Either the node is a child of its nearest found ancestor, or in the forest as a root
|
||||||
|
nodeList.forEach(treeNode => {
|
||||||
|
let ancestorInForest = findLast(
|
||||||
|
treeNode.node.ancestors,
|
||||||
|
ancestor => !!nodeIndex[ancestor.id]
|
||||||
|
);
|
||||||
|
if (ancestorInForest){
|
||||||
|
nodeIndex[ancestorInForest.id].children.push(treeNode);
|
||||||
|
} else {
|
||||||
|
forest.push(treeNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return forest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the documents from a collection, and return the tree of those documents
|
||||||
|
export default function nodesToTree({
|
||||||
|
collection, ancestorId, filter, options = {},
|
||||||
|
includeFilteredDocAncestors = false, includeFilteredDocDescendants = false
|
||||||
|
}){
|
||||||
|
// Setup the filter
|
||||||
|
let collectionFilter = {
|
||||||
|
'ancestors.id': ancestorId,
|
||||||
|
'removed': {$ne: true},
|
||||||
|
};
|
||||||
|
if (filter){
|
||||||
|
collectionFilter = {
|
||||||
|
...collectionFilter,
|
||||||
|
...filter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set up the options
|
||||||
|
let collectionSort = {
|
||||||
|
order: 1
|
||||||
|
};
|
||||||
|
if (options && options.sort){
|
||||||
|
collectionSort = {
|
||||||
|
...collectionSort,
|
||||||
|
...options.sort,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let collectionOptions = {
|
||||||
|
sort: collectionSort,
|
||||||
|
}
|
||||||
|
if (options){
|
||||||
|
collectionOptions = {
|
||||||
|
...collectionOptions,
|
||||||
|
...options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Find all the nodes that match the filter
|
||||||
|
let docs = collection.find(collectionFilter, collectionOptions).map(doc => {
|
||||||
|
if (!filter) return doc;
|
||||||
|
// Mark the nodes that were found by the custom filter
|
||||||
|
doc._matchedDocumentFilter = true;
|
||||||
|
return doc;
|
||||||
|
});
|
||||||
|
let ancestors = [];
|
||||||
|
let ancestorIds = [];
|
||||||
|
let docIds = [];
|
||||||
|
if (filter && (includeFilteredDocAncestors || includeFilteredDocDescendants)){
|
||||||
|
docIds = docs.map(doc => doc._id)
|
||||||
|
}
|
||||||
|
if (filter && includeFilteredDocAncestors){
|
||||||
|
// Add all ancestor ids to an array
|
||||||
|
docs.forEach(doc => {
|
||||||
|
ancestorIds = union(ancestorIds, doc.ancestors.map(ref => ref.id));
|
||||||
|
});
|
||||||
|
// Remove the IDs of docs we have already found
|
||||||
|
ancestorIds = difference(ancestorIds, docIds);
|
||||||
|
// Get the docs from the collection, don't worry about `removed` docs,
|
||||||
|
// if their descendant was not removed, neither are they
|
||||||
|
ancestors = collection.find({_id: {$in: ancestorIds}}).map(doc => {
|
||||||
|
// Mark that the nodes are ancestors of the found nodes
|
||||||
|
doc._ancestorOfMatchedDocument = true;
|
||||||
|
return doc;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let descendants = [];
|
||||||
|
if (filter && includeFilteredDocDescendants){
|
||||||
|
let exludeIds = union(ancestorIds, docIds);
|
||||||
|
descendants = collection.find({
|
||||||
|
'_id': {$nin: exludeIds},
|
||||||
|
'ancestors.id': {$in: docIds},
|
||||||
|
'removed': {$ne: true},
|
||||||
|
}).map(doc => {
|
||||||
|
// Mark that the nodes are descendants of the found nodes
|
||||||
|
doc._descendantOfMatchedDocument = true;
|
||||||
|
return doc;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let nodes = sortBy([
|
||||||
|
...ancestors,
|
||||||
|
...docs,
|
||||||
|
...descendants
|
||||||
|
], 'order');
|
||||||
|
// Find all the nodes
|
||||||
|
return nodeArrayToTree(nodes);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js';
|
import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js';
|
||||||
import getCollectionByName from '/imports/api/parenting/getCollectionByName.js';
|
import getCollectionByName from '/imports/api/parenting/getCollectionByName.js';
|
||||||
import { flatten, findLast } from 'lodash';
|
import { flatten } from 'lodash';
|
||||||
|
|
||||||
const generalParents = [
|
const generalParents = [
|
||||||
'attribute',
|
'attribute',
|
||||||
@@ -217,41 +217,3 @@ export function getName(doc){
|
|||||||
if (doc.ancestors[i].name) return doc.ancestors[i].name;
|
if (doc.ancestors[i].name) return doc.ancestors[i].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function nodeArrayToTree(nodes){
|
|
||||||
// Store a dict and list of all the nodes
|
|
||||||
let nodeIndex = {};
|
|
||||||
let nodeList = [];
|
|
||||||
nodes.forEach( node => {
|
|
||||||
let treeNode = {
|
|
||||||
node: node,
|
|
||||||
children: [],
|
|
||||||
};
|
|
||||||
nodeIndex[node._id] = treeNode;
|
|
||||||
nodeList.push(treeNode);
|
|
||||||
});
|
|
||||||
// Create a forest of trees
|
|
||||||
let forest = [];
|
|
||||||
// Either the node is a child of its nearest found ancestor, or in the forest as a root
|
|
||||||
nodeList.forEach(treeNode => {
|
|
||||||
let ancestorInForest = findLast(
|
|
||||||
treeNode.node.ancestors,
|
|
||||||
ancestor => !!nodeIndex[ancestor.id]
|
|
||||||
);
|
|
||||||
if (ancestorInForest){
|
|
||||||
nodeIndex[ancestorInForest.id].children.push(treeNode);
|
|
||||||
} else {
|
|
||||||
forest.push(treeNode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return forest;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function nodesToTree({collection, ancestorId, filter = {}, options = {}}){
|
|
||||||
if (!('ancestors.id' in filter)) filter['ancestors.id'] = ancestorId;
|
|
||||||
if (!('removed' in filter)) filter['removed'] = {$ne: true};
|
|
||||||
if (!options.sort) options.sort = {order: 1};
|
|
||||||
if (!('order' in options.sort)) options.sort.order = 1;
|
|
||||||
let nodes = collection.find(filter, options);
|
|
||||||
return nodeArrayToTree(nodes);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<template lang="html">
|
<template lang="html">
|
||||||
<v-sheet
|
<v-sheet
|
||||||
class="tree-node"
|
class="tree-node"
|
||||||
:class="!hasChildren ? 'empty' : null"
|
:class="{
|
||||||
|
'empty': !hasChildren,
|
||||||
|
'found': node._matchedDocumentFilter,
|
||||||
|
}"
|
||||||
:data-id="`tree-node-${node._id}`"
|
:data-id="`tree-node-${node._id}`"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -52,7 +55,7 @@
|
|||||||
:children="computedChildren"
|
:children="computedChildren"
|
||||||
:group="group"
|
:group="group"
|
||||||
:organize="organize"
|
:organize="organize"
|
||||||
:selected-node-id="selectedNodeId"
|
:selected-node="selectedNode"
|
||||||
@reordered="e => $emit('reordered', e)"
|
@reordered="e => $emit('reordered', e)"
|
||||||
@reorganized="e => $emit('reorganized', e)"
|
@reorganized="e => $emit('reorganized', e)"
|
||||||
@selected="e => $emit('selected', e)"
|
@selected="e => $emit('selected', e)"
|
||||||
@@ -80,6 +83,7 @@
|
|||||||
import { canBeParent } from '/imports/api/parenting/parenting.js';
|
import { canBeParent } from '/imports/api/parenting/parenting.js';
|
||||||
import { getPropertyIcon } from '/imports/constants/PROPERTIES.js';
|
import { getPropertyIcon } from '/imports/constants/PROPERTIES.js';
|
||||||
import TreeNodeView from '/imports/ui/properties/treeNodeViews/TreeNodeView.vue';
|
import TreeNodeView from '/imports/ui/properties/treeNodeViews/TreeNodeView.vue';
|
||||||
|
import { some } from 'lodash';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TreeNode',
|
name: 'TreeNode',
|
||||||
@@ -87,16 +91,33 @@
|
|||||||
TreeNodeView,
|
TreeNodeView,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
node: Object,
|
node: {
|
||||||
group: String,
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
organize: Boolean,
|
organize: Boolean,
|
||||||
children: Array,
|
children: {
|
||||||
getChildren: Function,
|
type: Array,
|
||||||
selectedNodeId: String,
|
default: () => [],
|
||||||
|
},
|
||||||
|
getChildren: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
selectedNode: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
},
|
},
|
||||||
data(){ return {
|
data(){return {
|
||||||
expanded: false,
|
expanded: this.node._ancestorOfMatchedDocument ||
|
||||||
|
some(this.selectedNode?.ancestors, ref => ref.id === this.node._id) ||
|
||||||
|
false,
|
||||||
}},
|
}},
|
||||||
computed: {
|
computed: {
|
||||||
hasChildren(){
|
hasChildren(){
|
||||||
@@ -119,6 +140,15 @@
|
|||||||
return canBeParent(this.node.type);
|
return canBeParent(this.node.type);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'node._ancestorOfMatchedDocument'(value){
|
||||||
|
this.expanded = !!value ||
|
||||||
|
some(this.selectedNode?.ancestors, ref => ref.id === this.node._id);
|
||||||
|
},
|
||||||
|
'selectedNode.ancestors'(value){
|
||||||
|
this.expanded = !!some(value, ref => ref.id === this.node._id) || this.expanded;
|
||||||
|
},
|
||||||
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.$options.components.TreeNodeList = require('./TreeNodeList.vue').default
|
this.$options.components.TreeNodeList = require('./TreeNodeList.vue').default
|
||||||
},
|
},
|
||||||
@@ -148,9 +178,12 @@
|
|||||||
.empty .v-btn {
|
.empty .v-btn {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
.found {
|
||||||
|
background: rgba(200, 0, 0, 0.1);
|
||||||
|
}
|
||||||
.ghost {
|
.ghost {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
background: #fbc8c8;
|
background: rgba(251, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
.v-icon.v-icon--disabled {
|
.v-icon.v-icon--disabled {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
@@ -18,8 +18,9 @@
|
|||||||
:node="child.node"
|
:node="child.node"
|
||||||
:children="child.children"
|
:children="child.children"
|
||||||
:group="group"
|
:group="group"
|
||||||
:selected-node-id="selectedNodeId"
|
:selected-node="selectedNode"
|
||||||
:selected="selectedNodeId === child.node._id"
|
:selected="selectedNode && selectedNode._id === child.node._id"
|
||||||
|
:ancestors-of-selected-node="ancestorsOfSelectedNode"
|
||||||
:organize="organize"
|
:organize="organize"
|
||||||
:lazy="lazy"
|
:lazy="lazy"
|
||||||
@selected="e => $emit('selected', e)"
|
@selected="e => $emit('selected', e)"
|
||||||
@@ -49,7 +50,14 @@
|
|||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
selectedNodeId: String,
|
selectedNode: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
ancestorsOfSelectedNode: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data(){ return {
|
data(){ return {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
style="overflow-y: auto;"
|
style="overflow-y: auto;"
|
||||||
:root="{collection: 'creatures', id: creatureId}"
|
:root="{collection: 'creatures', id: creatureId}"
|
||||||
:organize="organize"
|
:organize="organize"
|
||||||
:selected-node-id="selected"
|
:selected-node="selectedNode"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
@selected="clickNode"
|
@selected="clickNode"
|
||||||
/>
|
/>
|
||||||
@@ -51,9 +51,9 @@
|
|||||||
<template slot="detail">
|
<template slot="detail">
|
||||||
<creature-property-dialog
|
<creature-property-dialog
|
||||||
embedded
|
embedded
|
||||||
:_id="selected"
|
:_id="selectedNodeId"
|
||||||
@removed="selected = undefined"
|
@removed="selectedNodeId = undefined"
|
||||||
@duplicated="id => selected = id"
|
@duplicated="id => selectedNodeId = id"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</tree-detail-layout>
|
</tree-detail-layout>
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
data(){ return {
|
data(){ return {
|
||||||
organize: false,
|
organize: false,
|
||||||
organizeDisabled: false,
|
organizeDisabled: false,
|
||||||
selected: undefined,
|
selectedNodeId: undefined,
|
||||||
fab: false,
|
fab: false,
|
||||||
filterString: '',
|
filterString: '',
|
||||||
filterOptions: [
|
filterOptions: [
|
||||||
@@ -144,14 +144,14 @@
|
|||||||
},
|
},
|
||||||
'$vuetify.breakpoint.mdAndUp'(mdAndUp){
|
'$vuetify.breakpoint.mdAndUp'(mdAndUp){
|
||||||
if (!mdAndUp){
|
if (!mdAndUp){
|
||||||
this.selected = undefined;
|
this.selectedNodeId = undefined;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clickNode(id){
|
clickNode(id){
|
||||||
if (this.$vuetify.breakpoint.mdAndUp){
|
if (this.$vuetify.breakpoint.mdAndUp){
|
||||||
this.selected = id;
|
this.selectedNodeId = id;
|
||||||
} else {
|
} else {
|
||||||
this.$store.commit('pushDialogStack', {
|
this.$store.commit('pushDialogStack', {
|
||||||
component: 'creature-property-dialog',
|
component: 'creature-property-dialog',
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
component: 'creature-property-dialog',
|
component: 'creature-property-dialog',
|
||||||
elementId: 'selected-node-card',
|
elementId: 'selected-node-card',
|
||||||
data: {
|
data: {
|
||||||
_id: this.selected,
|
_id: this.selectedNodeId,
|
||||||
startInEditTab: true,
|
startInEditTab: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -175,9 +175,9 @@
|
|||||||
getPropertyName,
|
getPropertyName,
|
||||||
},
|
},
|
||||||
meteor: {
|
meteor: {
|
||||||
selectedProperty(){
|
selectedNode(){
|
||||||
return CreatureProperties.findOne({
|
return CreatureProperties.findOne({
|
||||||
_id: this.selected,
|
_id: this.selectedNodeId,
|
||||||
removed: {$ne: true}
|
removed: {$ne: true}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
:children="children"
|
:children="children"
|
||||||
:group="group"
|
:group="group"
|
||||||
:organize="organize"
|
:organize="organize"
|
||||||
:selected-node-id="selectedNodeId"
|
:selected-node="selectedNode"
|
||||||
@selected="e => $emit('selected', e)"
|
@selected="e => $emit('selected', e)"
|
||||||
@reordered="reordered"
|
@reordered="reordered"
|
||||||
@reorganized="reorganized"
|
@reorganized="reorganized"
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<script lang="js">
|
<script lang="js">
|
||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||||
import { nodesToTree } from '/imports/api/parenting/parenting.js'
|
import nodesToTree from '/imports/api/parenting/nodesToTree.js'
|
||||||
import TreeNodeList from '/imports/ui/components/tree/TreeNodeList.vue';
|
import TreeNodeList from '/imports/ui/components/tree/TreeNodeList.vue';
|
||||||
import { organizeDoc, reorderDoc } from '/imports/api/parenting/organizeMethods.js';
|
import { organizeDoc, reorderDoc } from '/imports/api/parenting/organizeMethods.js';
|
||||||
|
|
||||||
@@ -24,7 +24,10 @@
|
|||||||
props: {
|
props: {
|
||||||
root: Object,
|
root: Object,
|
||||||
organize: Boolean,
|
organize: Boolean,
|
||||||
selectedNodeId: String,
|
selectedNode: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
filter: Object,
|
filter: Object,
|
||||||
group: {
|
group: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -37,6 +40,8 @@
|
|||||||
collection: CreatureProperties,
|
collection: CreatureProperties,
|
||||||
ancestorId: this.root.id,
|
ancestorId: this.root.id,
|
||||||
filter: this.filter,
|
filter: this.filter,
|
||||||
|
includeFilteredDocAncestors: true,
|
||||||
|
includeFilteredDocDescendants: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -234,7 +234,8 @@ export default {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
selectSubProperty(_id){
|
selectSubProperty(doc){
|
||||||
|
let _id = doc && doc._id
|
||||||
this.$store.commit('pushDialogStack', {
|
this.$store.commit('pushDialogStack', {
|
||||||
component: 'creature-property-dialog',
|
component: 'creature-property-dialog',
|
||||||
elementId: `tree-node-${_id}`,
|
elementId: `tree-node-${_id}`,
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
style="bottom: -32px"
|
style="bottom: -32px"
|
||||||
fab
|
fab
|
||||||
:library-id="libraryId"
|
:library-id="libraryId"
|
||||||
:selected-node-id="selected"
|
:selected-node-id="selectedNodeId"
|
||||||
@selected="id => {if ($vuetify.breakpoint.mdAndUp) selected = id}"
|
@selected="id => {if ($vuetify.breakpoint.mdAndUp) selectedNodeId = id}"
|
||||||
/>
|
/>
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
<div
|
<div
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<library-contents-container
|
<library-contents-container
|
||||||
:library-id="libraryId"
|
:library-id="libraryId"
|
||||||
:organize-mode="organize"
|
:organize-mode="organize"
|
||||||
:selected-node-id="selected"
|
:selected-node="selectedNode"
|
||||||
should-subscribe
|
should-subscribe
|
||||||
@selected="clickNode"
|
@selected="clickNode"
|
||||||
/>
|
/>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
v-else
|
v-else
|
||||||
edit-mode
|
edit-mode
|
||||||
:organize-mode="organize"
|
:organize-mode="organize"
|
||||||
:selected-node-id="selected"
|
:selected-node="selectedNode"
|
||||||
style="overflow-y: auto; padding: 12px;"
|
style="overflow-y: auto; padding: 12px;"
|
||||||
@selected="clickNode"
|
@selected="clickNode"
|
||||||
/>
|
/>
|
||||||
@@ -61,10 +61,10 @@
|
|||||||
style="overflow: hidden;"
|
style="overflow: hidden;"
|
||||||
>
|
>
|
||||||
<library-node-dialog
|
<library-node-dialog
|
||||||
:_id="selected"
|
:_id="selectedNodeId"
|
||||||
embedded
|
embedded
|
||||||
@removed="selected = undefined"
|
@removed="selectedNodeId = undefined"
|
||||||
@duplicated="id => {if ($vuetify.breakpoint.mdAndUp) selected = id}"
|
@duplicated="id => {if ($vuetify.breakpoint.mdAndUp) selectedNodeId = id}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</tree-detail-layout>
|
</tree-detail-layout>
|
||||||
@@ -100,7 +100,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data(){ return {
|
data(){ return {
|
||||||
organize: false,
|
organize: false,
|
||||||
selected: undefined,
|
selectedNodeId: undefined,
|
||||||
};},
|
};},
|
||||||
computed: {
|
computed: {
|
||||||
isToolbarDark(){
|
isToolbarDark(){
|
||||||
@@ -120,12 +120,12 @@ export default {
|
|||||||
this.$store.commit('pushDialogStack', {
|
this.$store.commit('pushDialogStack', {
|
||||||
component: 'library-node-edit-dialog',
|
component: 'library-node-edit-dialog',
|
||||||
elementId: 'selected-node-card',
|
elementId: 'selected-node-card',
|
||||||
data: {_id: this.selected},
|
data: {_id: this.selectedNodeId},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
clickNode(id){
|
clickNode(id){
|
||||||
if (this.$vuetify.breakpoint.mdAndUp){
|
if (this.$vuetify.breakpoint.mdAndUp){
|
||||||
this.selected = id;
|
this.selectedNodeId = id;
|
||||||
} else {
|
} else {
|
||||||
this.$store.commit('pushDialogStack', {
|
this.$store.commit('pushDialogStack', {
|
||||||
component: 'library-node-dialog',
|
component: 'library-node-dialog',
|
||||||
@@ -136,7 +136,7 @@ export default {
|
|||||||
},
|
},
|
||||||
callback: result => {
|
callback: result => {
|
||||||
if (result){
|
if (result){
|
||||||
this.selected = id;
|
this.selectedNodeId = id;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -175,7 +175,7 @@ export default {
|
|||||||
},
|
},
|
||||||
selectedNode(){
|
selectedNode(){
|
||||||
return LibraryNodes.findOne({
|
return LibraryNodes.findOne({
|
||||||
_id: this.selected,
|
_id: this.selectedNodeId,
|
||||||
removed: {$ne: true}
|
removed: {$ne: true}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<insert-library-node-button
|
<insert-library-node-button
|
||||||
v-if="editPermission(library)"
|
v-if="editPermission(library)"
|
||||||
:library-id="library._id"
|
:library-id="library._id"
|
||||||
:selected-node-id="selectedNodeId"
|
:selected-node-id="selectedNode && selectedNode._id"
|
||||||
@selected="e => $emit('selected', e)"
|
@selected="e => $emit('selected', e)"
|
||||||
/>
|
/>
|
||||||
<v-btn
|
<v-btn
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
:library-id="library._id"
|
:library-id="library._id"
|
||||||
:organize-mode="organizeMode && editPermission(library)"
|
:organize-mode="organizeMode && editPermission(library)"
|
||||||
:edit-mode="editMode"
|
:edit-mode="editMode"
|
||||||
:selected-node-id="selectedNodeId"
|
:selected-node="selectedNode"
|
||||||
should-subscribe
|
should-subscribe
|
||||||
@selected="e => $emit('selected', e)"
|
@selected="e => $emit('selected', e)"
|
||||||
/>
|
/>
|
||||||
@@ -83,8 +83,8 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
organizeMode: Boolean,
|
organizeMode: Boolean,
|
||||||
editMode: Boolean,
|
editMode: Boolean,
|
||||||
selectedNodeId: {
|
selectedNode: {
|
||||||
type: String,
|
type: Object,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
group="library"
|
group="library"
|
||||||
:children="libraryChildren"
|
:children="libraryChildren"
|
||||||
:organize="organizeMode"
|
:organize="organizeMode"
|
||||||
:selected-node-id="selectedNodeId"
|
:selected-node="selectedNode"
|
||||||
@selected="e => $emit('selected', e)"
|
@selected="e => $emit('selected', e)"
|
||||||
@reordered="reordered"
|
@reordered="reordered"
|
||||||
@reorganized="reorganized"
|
@reorganized="reorganized"
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<script lang="js">
|
<script lang="js">
|
||||||
import Libraries from '/imports/api/library/Libraries.js';
|
import Libraries from '/imports/api/library/Libraries.js';
|
||||||
import LibraryNodes from '/imports/api/library/LibraryNodes.js';
|
import LibraryNodes from '/imports/api/library/LibraryNodes.js';
|
||||||
import { nodesToTree } from '/imports/api/parenting/parenting.js'
|
import nodesToTree from '/imports/api/parenting/nodesToTree.js'
|
||||||
import TreeNodeList from '/imports/ui/components/tree/TreeNodeList.vue';
|
import TreeNodeList from '/imports/ui/components/tree/TreeNodeList.vue';
|
||||||
import { organizeDoc, reorderDoc } from '/imports/api/parenting/organizeMethods.js';
|
import { organizeDoc, reorderDoc } from '/imports/api/parenting/organizeMethods.js';
|
||||||
|
|
||||||
@@ -40,7 +40,10 @@
|
|||||||
props: {
|
props: {
|
||||||
libraryId: String,
|
libraryId: String,
|
||||||
organizeMode: Boolean,
|
organizeMode: Boolean,
|
||||||
selectedNodeId: String,
|
selectedNode: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
shouldSubscribe: Boolean,
|
shouldSubscribe: Boolean,
|
||||||
},
|
},
|
||||||
data(){return {
|
data(){return {
|
||||||
|
|||||||
Reference in New Issue
Block a user