LibraryList.vue 3.1 KB

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