Browse Source

separate TextList into sub components

axolotle 3 years ago
parent
commit
7209b6bbee

+ 62 - 0
src/components/text/TextCard.vue

@@ -0,0 +1,62 @@
+<template>
+  <text-card-base v-bind="$attrs">
+    <template v-slot:header-extra="{ text }">
+      <b-nav class="ml-auto flex-nowrap" pills>
+        <template v-if="children">
+          <b-nav-item
+            v-for="child in text.children" :key="child.id"
+            @click="$emit('open', text.id, child.id)"
+            :active="children.includes(child.id)"
+          >
+            {{ child.id }}
+          </b-nav-item>
+        </template>
+
+        <b-nav-item>
+          <b-button-close @click="$emit('close', text.id)" />
+        </b-nav-item>
+      </b-nav>
+    </template>
+
+    <template v-slot:footer-extra="{ text, toCommaList }">
+      <b-button
+        v-if="text.siblings"
+        :id="'siblings-' + text.id"
+      >
+        {{ $t('siblings') }}
+      </b-button>
+      <b-popover
+        v-if="text.siblings"
+        :target="'siblings-' + text.id" triggers="click" placement="top"
+      >
+        <div v-for="sibling in text.siblings" :key="sibling.id">
+          <h6>
+            <span>{{ toCommaList(sibling.authors) }},</span>
+            <span>{{ sibling.title }},</span>
+            <span>{{ sibling.edition }}</span>
+          </h6>
+        </div>
+      </b-popover>
+    </template>
+  </text-card-base>
+</template>
+
+<script>
+import TextCardBase from './TextCardBase'
+
+
+export default {
+  name: 'TextCard',
+
+  components: {
+    TextCardBase
+  },
+
+  props: {
+    children: { type: Array, default: null }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 24 - 39
src/components/text/TextCardBase.vue

@@ -5,7 +5,7 @@
         <b-card-header header-tag="header">
           <h4>
             <template v-if="text.type === 'Textref'">
-              <span>{{ text.authors | list }},</span>
+              <span>{{ toCommaList(text.authors) }},</span>
               <span>{{ text.title }},</span>
               <span>{{ text.edition }}</span>
             </template>
@@ -14,20 +14,10 @@
             </template>
           </h4>
 
-          <b-nav class="ml-auto flex-nowrap" pills>
-            <b-nav-item
-              v-for="child in text.children" :key="child.id"
-              @click="$emit('open', id, child.id)"
-              :active="children.includes(child.id)"
-            >
-              {{ child.id }}
-            </b-nav-item>
-
-            <b-button-close @click="$emit('close', id)" />
-          </b-nav>
+          <slot name="header-extra" :text="text" />
         </b-card-header>
 
-        <b-card-body v-html="text.content" class="overflow-auto" />
+        <b-card-body v-html="text.content" :class="ellipsis ? 'ellipsis' : 'overflow-auto'" />
 
         <b-card-footer>
           <b-badge
@@ -37,24 +27,7 @@
             {{ tag.name }}
           </b-badge>
 
-          <b-button
-            v-if="text.siblings"
-            :id="'siblings-' + text.id"
-          >
-            {{ $t('siblings') }}
-          </b-button>
-          <b-popover
-            v-if="text.siblings"
-            :target="'siblings-' + text.id" triggers="click" placement="top"
-          >
-            <div v-for="sibling in text.siblings" :key="sibling.id">
-              <h6>
-                <span>{{ sibling.authors | list }},</span>
-                <span>{{ sibling.title }},</span>
-                <span>{{ sibling.edition }}</span>
-              </h6>
-            </div>
-          </b-popover>
+          <slot name="footer-extra" v-bind="{ text, toCommaList }" />
         </b-card-footer>
       </div>
     </b-overlay>
@@ -63,27 +36,34 @@
 
 <script>
 export default {
-  name: 'TextCard',
+  name: 'TextCardBase',
 
   props: {
     id: { type: Number, required: true },
-    children: { type: Array, default: null }
+    textData: { type: Object, default: null },
+    ellipsis: { type: Boolean, default: false }
   },
 
   data () {
     return {
-      loading: true,
-      text: null
+      loading: this.textData === null,
+      text: this.textData
     }
   },
 
-  filters: {
-    list (arr) {
-      return arr.map(({ name }) => name).join(', ')
+  methods: {
+    toCommaList (arr) {
+      // FIXME TEMP some texts doesn't have authors
+      try {
+        return arr.map(({ name }) => name).join(', ')
+      } catch {
+        return arr
+      }
     }
   },
 
   created () {
+    if (this.text !== null) return
     this.$store.dispatch('GET_TEXT', { id: this.id }).then((text) => {
       this.text = text
       this.loading = false
@@ -95,8 +75,8 @@ export default {
 <style lang="scss" scoped>
 article {
   height: 100%;
-  // max-height: 100%;
 }
+
 header {
   display: flex;
 
@@ -105,4 +85,9 @@ header {
     flex-direction: column;
   }
 }
+
+.ellipsis {
+  max-height: 10rem;
+  overflow: hidden;
+}
 </style>

+ 20 - 0
src/components/text/TextMiniCard.vue

@@ -0,0 +1,20 @@
+<template>
+  <text-card-base v-bind="$attrs" ellipsis>
+  </text-card-base>
+</template>
+
+<script>
+import TextCardBase from './TextCardBase'
+
+
+export default {
+  name: 'TextMiniCard',
+
+  components: {
+    TextCardBase
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>