LibraryList.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <template>
  2. <b-overlay :show="filteredNodes === undefined" class="h-100" z-index="0">
  3. <div class="library-list">
  4. <legend-toggle>
  5. <h6>Mode Alphabétique</h6>
  6. <p>Ce mode vous permet de retrouver l'ensemble des textes de départ.</p>
  7. <p>Pour naviguer plus rapidement vous pouvez <i>Aller à la lettre</i> dans le menu d'options.</p>
  8. </legend-toggle>
  9. <div class="library-list-container" @click="onContainerClick">
  10. <div v-for="([char, nodes]) in filteredNodes" :key="char">
  11. <h3 :id="char">
  12. {{ char }}
  13. </h3>
  14. <div class="library-list-nodes-group nodes-grid">
  15. <node-view
  16. v-for="node in nodes" :key="char + '-' + node.id"
  17. :node="node"
  18. mode="card"
  19. @click.native.capture="previewNode = node"
  20. :preview="previewNode === node"
  21. @open-node="$emit('open-node', $event)"
  22. @open-child="$emit('open-node', { parentId: node.id, ...$event })"
  23. :style="`--opacity: ${getStrangenessOpacity(strangeness, node)};`"
  24. />
  25. </div>
  26. </div>
  27. </div>
  28. </div>
  29. </b-overlay>
  30. </template>
  31. <script>
  32. import { mapGetters } from 'vuex'
  33. import { searchInNode, tagsInNode, getStrangenessOpacity } from '@/store/utils'
  34. import { NodeView } from '@/components/nodes'
  35. export default {
  36. name: 'LibraryList',
  37. components: {
  38. NodeView
  39. },
  40. data () {
  41. return {
  42. previewNode: null
  43. }
  44. },
  45. computed: {
  46. ...mapGetters(['orderedTextsDepart', 'search', 'tags', 'strangeness']),
  47. filteredNodes () {
  48. if (!this.orderedTextsDepart) return
  49. const nodesGroups = []
  50. const search = this.search.toLowerCase()
  51. this.orderedTextsDepart.forEach(([char, nodes]) => {
  52. const filteredNodes = nodes
  53. .filter(node => tagsInNode(this.tags, node.tags))
  54. .filter(node => searchInNode(search, node))
  55. if (filteredNodes.length) {
  56. nodesGroups.push([char, filteredNodes])
  57. }
  58. })
  59. return nodesGroups
  60. }
  61. },
  62. methods: {
  63. getStrangenessOpacity,
  64. onContainerClick (e) {
  65. if (!e.target.classList.contains('node-view')) {
  66. this.previewNode = null
  67. }
  68. }
  69. },
  70. created () {
  71. this.$store.dispatch('INIT_LIBRARY_LIST')
  72. }
  73. }
  74. </script>
  75. <style lang="scss" scoped>
  76. .library-list {
  77. overflow-y: auto;
  78. height: 100%;
  79. &-container {
  80. padding: 1.15rem;
  81. @include media-breakpoint-up($size-bp) {
  82. padding: 2.15rem;
  83. }
  84. }
  85. h3 {
  86. font-family: $font-family-text;
  87. line-height: 1;
  88. font-size: 6.25rem;
  89. margin-top: 2rem;
  90. @include media-breakpoint-up($size-bp) {
  91. margin-top: 2rem;
  92. font-size: 16.5rem;
  93. }
  94. }
  95. &-nodes-group {
  96. .node-view {
  97. max-width: 100%;
  98. height: $node-card-height-sm;
  99. @include media-breakpoint-up($size-bp) {
  100. max-width: $node-card-width;
  101. height: $node-card-height;
  102. }
  103. &.preview {
  104. top: -2rem;
  105. }
  106. &:not(.preview) {
  107. opacity: var(--opacity);
  108. }
  109. }
  110. }
  111. }
  112. </style>