add NodePreview & NodeViewChildListGroup in Library
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="library-list">
|
<div class="library-list">
|
||||||
<div class="library-list-container">
|
<div class="library-list-container" @click="onContainerClick">
|
||||||
<div v-for="(parents, char) in filteredNodes" :key="char">
|
<div v-for="(parents, char) in filteredNodes" :key="char">
|
||||||
<h3>{{ char }}</h3>
|
<h3>{{ char }}</h3>
|
||||||
|
|
||||||
@@ -9,7 +9,10 @@
|
|||||||
v-for="parent in parents" :key="parent.id"
|
v-for="parent in parents" :key="parent.id"
|
||||||
:node="parent"
|
:node="parent"
|
||||||
mode="card"
|
mode="card"
|
||||||
|
@click.native.capture="previewNode = parent"
|
||||||
|
:preview="previewNode === parent"
|
||||||
@open-node="$emit('open-node', $event)"
|
@open-node="$emit('open-node', $event)"
|
||||||
|
@open-child="$emit('open-node', { parentId: parent.id, ...$event })"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,6 +34,12 @@ export default {
|
|||||||
NodeView
|
NodeView
|
||||||
},
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
previewNode: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['orderedTextsDepart', 'search', 'tags']),
|
...mapGetters(['orderedTextsDepart', 'search', 'tags']),
|
||||||
|
|
||||||
@@ -50,6 +59,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onContainerClick (e) {
|
||||||
|
if (!e.target.classList.contains('node-view')) {
|
||||||
|
this.previewNode = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
created () {
|
created () {
|
||||||
this.$store.dispatch('INIT_LIBRARY_LIST')
|
this.$store.dispatch('INIT_LIBRARY_LIST')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,21 @@
|
|||||||
:style="`--x: ${node.x}px; --y: ${node.y}px; --r: ${node.rotate}deg;`"
|
:style="`--x: ${node.x}px; --y: ${node.y}px; --r: ${node.rotate}deg;`"
|
||||||
>
|
>
|
||||||
<node-view
|
<node-view
|
||||||
|
:id="'preview-node-' + node.data.id"
|
||||||
|
:class="{ 'hidden': previewNode === node.data }"
|
||||||
:node="node.data"
|
:node="node.data"
|
||||||
mode="card"
|
mode="card"
|
||||||
@open-node="onOpen(node.data)"
|
|
||||||
:hidden="node.hidden"
|
:hidden="node.hidden"
|
||||||
|
@click.native="onNodeClick(node.data)"
|
||||||
/>
|
/>
|
||||||
</foreignObject>
|
</foreignObject>
|
||||||
</map-zoom>
|
</map-zoom>
|
||||||
|
|
||||||
|
<node-preview-zone
|
||||||
|
v-if="dataNodes"
|
||||||
|
v-model="previewNode" :nodes="dataNodes"
|
||||||
|
@open-node="onPreviewNodeClick"
|
||||||
|
/>
|
||||||
</b-overlay>
|
</b-overlay>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -21,8 +29,8 @@ import { randomUniform } from 'd3'
|
|||||||
import { forceSimulation, forceCollide, forceManyBody } from 'd3-force'
|
import { forceSimulation, forceCollide, forceManyBody } from 'd3-force'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
import { searchInNode, tagsInNode } from '@/store/utils'
|
import { searchInNode, tagsInNode, getRelation } from '@/store/utils'
|
||||||
import { MapZoom } from '@/components/layouts'
|
import { MapZoom, NodePreviewZone } from '@/components/layouts'
|
||||||
import { NodeView } from '@/components/nodes'
|
import { NodeView } from '@/components/nodes'
|
||||||
|
|
||||||
|
|
||||||
@@ -31,13 +39,15 @@ export default {
|
|||||||
|
|
||||||
components: {
|
components: {
|
||||||
MapZoom,
|
MapZoom,
|
||||||
|
NodePreviewZone,
|
||||||
NodeView
|
NodeView
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
simulation: forceSimulation(),
|
simulation: forceSimulation(),
|
||||||
nodes: undefined
|
nodes: undefined,
|
||||||
|
previewNode: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -53,16 +63,27 @@ export default {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
return this.nodes
|
return this.nodes
|
||||||
|
},
|
||||||
|
|
||||||
|
dataNodes () {
|
||||||
|
if (!this.nodes) return
|
||||||
|
return this.nodes.map(node => node.data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onOpen (node) {
|
onOpen (node) {
|
||||||
if (node.parents && node.parents.length) {
|
this.$parent.$emit('open-node', getRelation(node))
|
||||||
this.$emit('open-node', { parentId: node.parents[0].id, childId: node.id })
|
},
|
||||||
} else {
|
|
||||||
this.$emit('open-node', { parentId: node.id })
|
onNodeClick (node) {
|
||||||
}
|
this.previewNode = node
|
||||||
|
this.$root.$emit('bv::show::popover', 'preview-node-' + node.id)
|
||||||
|
},
|
||||||
|
|
||||||
|
onPreviewNodeClick (ids) {
|
||||||
|
this.$root.$emit('bv::hide::popover', 'preview-node-' + this.previewNode.id)
|
||||||
|
this.$emit('open-node', ids)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -93,4 +114,14 @@ foreignObject {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.node-view.hidden {
|
||||||
|
border: $line;
|
||||||
|
border-style: dashed;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
::v-deep .node-view-wrapper {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -14,11 +14,15 @@
|
|||||||
:cx="node.x"
|
:cx="node.x"
|
||||||
:cy="node.y"
|
:cy="node.y"
|
||||||
class="svg-dot"
|
class="svg-dot"
|
||||||
|
:id="'preview-node-' + node.data.id"
|
||||||
:class="['svg-dot-' + node.data.variant, { 'origin': node.parent === null }]"
|
:class="['svg-dot-' + node.data.variant, { 'origin': node.parent === null }]"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="onNodeClick(node.data)"
|
@focus="activeNode = node"
|
||||||
@keyup.enter="onNodeClick(node.data)"
|
|
||||||
@mouseenter="activeNode = node"
|
@mouseenter="activeNode = node"
|
||||||
|
@mouseleave="activeNode = null"
|
||||||
|
@blur="activeNode = null"
|
||||||
|
@click.stop="onNodeClick(node.data)"
|
||||||
|
@keyup.enter="onNodeClick(node.data)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<g>
|
<g>
|
||||||
@@ -30,20 +34,20 @@
|
|||||||
>
|
>
|
||||||
<dot-button
|
<dot-button
|
||||||
:variant="activeNode.data.variant"
|
:variant="activeNode.data.variant"
|
||||||
class="active"
|
active hovered
|
||||||
@click="onNodeClick(activeNode.data)"
|
@click="onNodeClick(activeNode.data)"
|
||||||
@mouseleave="activeNode = null"
|
|
||||||
>
|
>
|
||||||
<template v-if="activeNode.data.variant !== 'depart'">
|
<template v-if="activeNode.data.type === 'prod'">
|
||||||
{{ $t('variants.' + activeNode.data.variant) }}<br>
|
{{ $t('variants.' + activeNode.data.variant) }}<br>
|
||||||
</template>
|
</template>
|
||||||
{{ toCommaList(activeNode.data.authors) }},<br>
|
|
||||||
<span v-if="activeNode.data.preTitle" v-html="trim(activeNode.data.preTitle) + ','" />
|
<node-view-title v-else :node="activeNode.data" block />
|
||||||
<span v-html="trim(activeNode.data.title) || '<em>pas de titre ital</em>'" />
|
|
||||||
</dot-button>
|
</dot-button>
|
||||||
</foreignObject>
|
</foreignObject>
|
||||||
</g>
|
</g>
|
||||||
</map-zoom>
|
</map-zoom>
|
||||||
|
|
||||||
|
<node-preview-zone v-model="previewNode" :nodes="dataNodes" @open-node="onPreviewNodeClick" />
|
||||||
</b-overlay>
|
</b-overlay>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -52,26 +56,33 @@ import { mapGetters } from 'vuex'
|
|||||||
import { line } from 'd3-shape'
|
import { line } from 'd3-shape'
|
||||||
import { forceSimulation, forceLink, forceManyBody, forceX, forceY } from 'd3-force'
|
import { forceSimulation, forceLink, forceManyBody, forceX, forceY } from 'd3-force'
|
||||||
|
|
||||||
import { trim, toCommaList } from '@/helpers/common'
|
import { MapZoom, NodePreviewZone } from '@/components/layouts'
|
||||||
import { MapZoom } from '@/components/layouts'
|
import { NodeViewTitle } from '@/components/nodes'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LibraryTree',
|
name: 'LibraryTree',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
MapZoom
|
MapZoom,
|
||||||
|
NodePreviewZone,
|
||||||
|
NodeViewTitle
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
activeNode: null
|
activeNode: null,
|
||||||
|
previewNode: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['nodeTree']),
|
...mapGetters(['nodeTree']),
|
||||||
|
|
||||||
|
dataNodes () {
|
||||||
|
return this.nodeTree.nodes.map(node => node.data)
|
||||||
|
},
|
||||||
|
|
||||||
// ONE TIME GETTER
|
// ONE TIME GETTER
|
||||||
simulation () {
|
simulation () {
|
||||||
return forceSimulation()
|
return forceSimulation()
|
||||||
@@ -98,6 +109,7 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
nodeTree (tree) {
|
nodeTree (tree) {
|
||||||
this.activeNode = null
|
this.activeNode = null
|
||||||
|
this.previewNode = null
|
||||||
this.simulation.nodes(tree.nodes)
|
this.simulation.nodes(tree.nodes)
|
||||||
this.simulation.force('link').links(tree.links)
|
this.simulation.force('link').links(tree.links)
|
||||||
this.simulation.alpha(0.5).restart()
|
this.simulation.alpha(0.5).restart()
|
||||||
@@ -105,15 +117,16 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toCommaList,
|
|
||||||
trim,
|
|
||||||
|
|
||||||
onNodeClick (node) {
|
onNodeClick (node) {
|
||||||
if (node.parents && node.parents.length) {
|
this.$store.dispatch('GET_NODE', { id: node.id, dataLevel: 'partial' })
|
||||||
this.$emit('open-node', { parentId: node.parents[0].id, childId: node.id })
|
this.previewNode = node
|
||||||
} else {
|
this.$root.$emit('bv::show::popover', 'preview-node-' + node.id)
|
||||||
this.$emit('open-node', { parentId: node.id })
|
},
|
||||||
}
|
|
||||||
|
onPreviewNodeClick (ids) {
|
||||||
|
this.$root.$emit('bv::hide::popover', 'preview-node-' + this.previewNode.id)
|
||||||
|
this.$emit('open-node', ids)
|
||||||
|
this.previewNode = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -140,6 +153,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-dot {
|
&-dot {
|
||||||
|
cursor: pointer;
|
||||||
r: 9.5px;
|
r: 9.5px;
|
||||||
|
|
||||||
@each $color, $value in $theme-colors {
|
@each $color, $value in $theme-colors {
|
||||||
@@ -177,5 +191,10 @@ foreignObject {
|
|||||||
|
|
||||||
.dot-btn {
|
.dot-btn {
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user