search.vue 3.99 KB
Newer Older
Anton's avatar
Anton committed
1
2
<template lang="pug">
  full-screen
3

4
    content-block(:position="'first'")
5
      headline(:content="'Search timelines'")
christianrhansen's avatar
christianrhansen committed
6

7
      // input field
8
      content-paragraph(:position="'first'")
9
        q-input.q-mb-sm(v-model="query", dark, float-label="Search", :before="[{icon: 'search'}]")
10
        .full-width.text-right
11
          q-btn.full-width(@click="search", color="primary") Search
12

13
14
15
      // results
      content-paragraph(v-for="(result, i) in results", :class="{'q-mt-xl': i === 0}")
        div(:class="{'ui-border-bottom': i < results.length - 1}")
16
17
          // div
          markdown-display.markdown-display(:content="result.body.value", :options="mdOptions")
18
          .q-my-md
Anton's avatar
Anton committed
19
20
            a.cursor-pointer(:href="`/piecemaker/media/${getMedia(result).annotation._uuid}/annotate#${result._uuid}`")
              | {{ getMedia(result).metadata.title }}
21
            p.text-grey-8 {{ formatDate(result.target.selector._valueMillis) }}
Anton's avatar
Anton committed
22
23
24
</template>

<script>
25
  import { mapGetters } from 'vuex'
Anton's avatar
Anton committed
26
  import { DateTime } from 'luxon'
27
28
  import BackButtonNew from '../../../components/shared/buttons/BackButtonNew'
  import Headline from '../../../components/shared/elements/Headline'
29
  import ContentBlock from '../../../components/shared/elements/ContentBlock'
30
  import ContentParagraph from '../../../components/shared/elements/ContentParagraph'
31
  import PageSubNav from '../../../components/shared/navigation/PageSubNav'
Anton's avatar
Anton committed
32
33

  export default {
34
    components: {
Anton's avatar
Anton committed
35
      PageSubNav,
36
      BackButtonNew,
37
      Headline,
38
39
      ContentBlock,
      ContentParagraph
40
    },
Anton's avatar
Anton committed
41
42
43
44
    data () {
      return {
        query: undefined,
        map: undefined,
Anton's avatar
Anton committed
45
        media: [],
46
47
48
49
        results: [],
        mdOptions: {
          target: '_blank'
        }
Anton's avatar
Anton committed
50
51
52
      }
    },
    async mounted () {
53
      this.$root.$emit('setBackButton', '/piecemaker/timelines')
Anton's avatar
Anton committed
54
      this.$q.loading.show()
55
      this.map = await this.$store.dispatch('maps/get', this.$route.params.uuid)
Anton's avatar
Anton committed
56
      const media = await this.$store.dispatch('annotations/find', {
Anton's avatar
Anton committed
57
        'target.id': this.map.id,
Anton's avatar
Anton committed
58
        'body.type': 'Media'
Anton's avatar
Anton committed
59
      })
Anton's avatar
Anton committed
60
61
      this.media = media.items.sort(this.$sort.onRef).map(annotation => { return { annotation } })
      for (let i in this.media) {
Anton's avatar
Anton committed
62
        try {
Anton's avatar
Anton committed
63
          this.media[i].metadata = await this.$store.dispatch('metadata/get', this.media[i].annotation)
Anton's avatar
Anton committed
64
        }
Anton's avatar
Anton committed
65
        catch (e) { this.media[i].metadata = {} }
Anton's avatar
Anton committed
66
      }
Anton Koch's avatar
Anton Koch committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

      // const aggs = {
      //   annotations_per_minute: {
      //     date_histogram: {
      //       field: 'target.selector._valueMillis',
      //       calendar_interval: '1m'
      //     }
      //   }
      // }
      // const query = {
      //   match: { 'target.id': this.map.id }
      // }
      // const aggregations = await this.$store.dispatch('search/query', { index: 'annotations', aggs, query })
      // console.debug('Aggregations', aggregations)

Anton's avatar
Anton committed
82
83
      this.$q.loading.hide()
    },
84
85
86
87
88
    computed: {
      ...mapGetters({
        isMobile: 'globalSettings/getIsMobile'
      })
    },
Anton's avatar
Anton committed
89
90
91
92
    methods: {
      async search () {
        this.$q.loading.show()
        const query = {
Anton Koch's avatar
Anton Koch committed
93
          match: { 'body.value': this.query }
Anton's avatar
Anton committed
94
        }
Anton Koch's avatar
Anton Koch committed
95
96
97
        const result = await this.$store.dispatch('search/query', { index: 'annotations', query })
        this.results = (result && Array.isArray(result.hits) ? result.hits.sort(this.$sort.onRef) : [])
          .map(hit => hit._source)
Anton's avatar
Anton committed
98
99
        this.$q.loading.hide()
      },
100
101
      formatDate (millis) {
        return DateTime.fromMillis(millis).toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)
Anton's avatar
Anton committed
102
      },
Anton's avatar
Anton committed
103
104
      getMedia (annotation) {
        for (let video of this.media) {
Anton's avatar
Anton committed
105
          const
106
107
            annoTime = DateTime.fromMillis(annotation.target.selector._valueMillis),
            videoStart = DateTime.fromMillis(video.annotation.target.selector._valueMillis),
Anton's avatar
Anton committed
108
109
110
            videoEnd = videoStart.plus(video.metadata.duration * 1000)
          if (annoTime >= videoStart && annoTime < videoEnd) return video
        }
Anton Koch's avatar
Anton Koch committed
111
        return { annotation: {}, metadata: {} }
Anton's avatar
Anton committed
112
113
114
115
      }
    }
  }
</script>