update library opening strategy
This commit is contained in:
+46
-120
@@ -1,101 +1,55 @@
|
||||
<template>
|
||||
<div class="library">
|
||||
<!-- BACKGROUND (mode) -->
|
||||
<component :is="mode" @open="openText" />
|
||||
<component :is="'library-' + mode" @open-node="openNode" />
|
||||
|
||||
<!-- FOREGROUND (texts) -->
|
||||
<div v-if="parents.length" class="main-texts-container">
|
||||
<section
|
||||
v-for="(parent, i) in parents" :key="parent.id"
|
||||
class="main-text-container text-break"
|
||||
:style="`--n: ${i};`"
|
||||
:class="{ 'text-blur': i !== parents.length - 1 }"
|
||||
>
|
||||
<text-card
|
||||
:id="parent.id"
|
||||
:children="parent.children"
|
||||
class="text-card-main"
|
||||
@open="openText" @close="closeText"
|
||||
@click.native="onMainTextClick(i)"
|
||||
/>
|
||||
|
||||
<section class="sub-texts-container">
|
||||
<text-card
|
||||
v-for="(id, j) in parent.children" :key="id"
|
||||
:id="id"
|
||||
class="text-card-sub text-break"
|
||||
:style="`--n: ${j};`"
|
||||
@close="closeText(parent.id, $event)"
|
||||
@click.native="onSubTextClick(i, j)"
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<!-- FOREGROUND (nodes) -->
|
||||
<node-book
|
||||
v-if="nodebook.length"
|
||||
:nodes="nodebook"
|
||||
class="library-node-book no-events-container"
|
||||
@open-node="openNode"
|
||||
@close-node="closeNode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { CardList, CardMap, TreeMap } from './library'
|
||||
import TextCard from '@/components/text/TextCard'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import {
|
||||
LibraryList,
|
||||
LibraryMap,
|
||||
LibraryTree
|
||||
} from './library'
|
||||
import { NodeBook } from '@/components/layouts'
|
||||
|
||||
|
||||
export default {
|
||||
name: 'Library',
|
||||
|
||||
components: {
|
||||
CardList,
|
||||
CardMap,
|
||||
TreeMap,
|
||||
TextCard
|
||||
LibraryList,
|
||||
LibraryMap,
|
||||
LibraryTree,
|
||||
NodeBook
|
||||
},
|
||||
|
||||
props: {
|
||||
mode: { type: String, required: true },
|
||||
texts: { type: Array, required: true }
|
||||
query: { type: Object, required: true }
|
||||
},
|
||||
|
||||
computed: {
|
||||
parents () {
|
||||
return this.texts.map(text => {
|
||||
const [id, ...children] = text
|
||||
return { id, children }
|
||||
})
|
||||
...mapGetters(['mode', 'nodebook'])
|
||||
},
|
||||
|
||||
watch: {
|
||||
query (query) {
|
||||
this.$store.dispatch('UPDATE_NODEBOOK', query)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
openText (id, childId) {
|
||||
const parent = this.parents.find(p => p.id === id)
|
||||
if (parent && (childId === undefined || parent.children.includes(childId))) return
|
||||
|
||||
if (!parent) {
|
||||
this.parents.push({ id, children: childId ? [childId] : [] })
|
||||
} else if (childId) {
|
||||
parent.children.push(childId)
|
||||
}
|
||||
this.updateQuery(this.parents)
|
||||
},
|
||||
|
||||
closeText (id, childId) {
|
||||
const parent = this.parents.find(p => p.id === id)
|
||||
if (!childId) {
|
||||
this.updateQuery(this.parents.filter(p => p !== parent))
|
||||
} else {
|
||||
parent.children = parent.children.filter(childId_ => childId_ !== childId)
|
||||
this.updateQuery(this.parents)
|
||||
}
|
||||
},
|
||||
|
||||
updateQuery (parents) {
|
||||
// Update the route's query (will not reload the page) and let vue determine what changed.
|
||||
this.$router.push({
|
||||
query: {
|
||||
mode: this.mode,
|
||||
texts: parents.map(parent => [parent.id, ...parent.children])
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onMainTextClick (mainTextIndex) {
|
||||
if (mainTextIndex === this.texts.length - 1) return
|
||||
this.parents.push(this.parents.splice(mainTextIndex, 1)[0])
|
||||
@@ -118,7 +72,19 @@ export default {
|
||||
if (needUpdate) {
|
||||
this.updateQuery(this.parents)
|
||||
}
|
||||
},
|
||||
|
||||
openNode (parentId, childId) {
|
||||
this.$store.dispatch('OPEN_NODE', [parentId, childId])
|
||||
},
|
||||
|
||||
closeNode (parentId, childId) {
|
||||
this.$store.dispatch('CLOSE_NODE', [parentId, childId])
|
||||
}
|
||||
},
|
||||
|
||||
created () {
|
||||
this.$store.dispatch('UPDATE_NODEBOOK', this.query)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -126,53 +92,13 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.library {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.main-texts-container {
|
||||
position: relative;
|
||||
top: -100%;
|
||||
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.main-text-container {
|
||||
border-top: 2px solid $black;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
> * {
|
||||
flex-basis: 50%;
|
||||
&-node-book {
|
||||
position: relative;
|
||||
margin-bottom: -100%;
|
||||
// compensate header border
|
||||
height: calc(100% + 2px);
|
||||
top: calc(-100% - 2px);
|
||||
}
|
||||
}
|
||||
|
||||
.sub-texts-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.text-card {
|
||||
pointer-events: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-break {
|
||||
position: absolute;
|
||||
height: calc(100% - (var(--n) * #{$text-card-header-height}));
|
||||
top: calc(var(--n) * #{$text-card-header-height});
|
||||
z-index: var(--n);
|
||||
}
|
||||
|
||||
.text-blur::before {
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba($white, .5);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
>
|
||||
<b-form-radio-group
|
||||
id="mode-select"
|
||||
v-model="currentMode" :options="modes"
|
||||
v-model="activeMode" :options="modes"
|
||||
name="mode-select" :aria-describedby="ariaDescribedby"
|
||||
buttons button-variant="outline-dark"
|
||||
/>
|
||||
</b-form-group>
|
||||
|
||||
<b-form-group
|
||||
v-if="currentMode !== 'tree-map'"
|
||||
v-if="mode !== 'tree'"
|
||||
:label="$t('options.filters.title')"
|
||||
>
|
||||
<b-form-group
|
||||
@@ -22,8 +22,7 @@
|
||||
>
|
||||
<multiple-tags-select
|
||||
id="tags-select" :button-text="$t('options.filters.choices.tags')"
|
||||
v-model="selectedTags" :options="tags"
|
||||
:disabled="true"
|
||||
v-model="selectedTags" :options="tagsOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
|
||||
@@ -80,20 +79,13 @@ export default {
|
||||
MultipleTagsSelect
|
||||
},
|
||||
|
||||
props: {
|
||||
show: { type: Boolean, required: true },
|
||||
mode: { type: String, required: true },
|
||||
tags: { type: Array, default: () => ([]) }
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
modes: [
|
||||
{ text: this.$t('options.display.choices.tree-map'), value: 'tree-map' },
|
||||
{ text: this.$t('options.display.choices.card-map'), value: 'card-map' },
|
||||
{ text: this.$t('options.display.choices.card-list'), value: 'card-list' }
|
||||
{ text: this.$t('options.display.choices.tree-map'), value: 'tree' },
|
||||
{ text: this.$t('options.display.choices.card-map'), value: 'map' },
|
||||
{ text: this.$t('options.display.choices.card-list'), value: 'list' }
|
||||
],
|
||||
currentMode: this.mode,
|
||||
selectedTags: [],
|
||||
strangeness: 0,
|
||||
textDepartId: undefined,
|
||||
@@ -102,7 +94,11 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['nodesDepartsOptions']),
|
||||
...mapGetters(['mode', 'nodebook', 'nodesDepartsOptions', 'tagsOptions']),
|
||||
|
||||
show () {
|
||||
return this.nodebook.length === 0
|
||||
},
|
||||
|
||||
nodeDepartId: {
|
||||
get () {
|
||||
@@ -111,12 +107,15 @@ export default {
|
||||
set (value) {
|
||||
this.$store.dispatch('SET_NODE_DEPART_ID', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentMode (mode) {
|
||||
this.$router.push({ query: { mode } })
|
||||
activeMode: {
|
||||
get () {
|
||||
return this.mode
|
||||
},
|
||||
set (value) {
|
||||
this.$store.dispatch('UPDATE_QUERY_MODE', value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user