Search.vue 3.38 KB
Newer Older
Markus Opolka's avatar
Markus Opolka committed
1
<template>
Markus Opolka's avatar
Markus Opolka committed
2
3
4
5
6
<v-container grid-list-md>
  <v-layout row wrap>
    <v-flex xs12>
      <h3>{{header}}</h3>
    </v-flex>
Markus Opolka's avatar
Markus Opolka committed
7

Markus Opolka's avatar
Markus Opolka committed
8
    <!-- Search Help -->
Markus Opolka's avatar
Markus Opolka committed
9
10
11
12
13
14
15
    <v-flex xs12>
      <v-expansion-panel>
        <v-expansion-panel-content>
          <div slot="header">Toggle Syntax Help</div>
          <v-card>
            <v-card-text class="grey lighten-3">
              <p>Content in an element: <strong>element:content</strong> (Regular Expressions are supported)</p>
16
17
18
              <p>If no element is provided, the text will be searched.</p>
              <!-- <p>Attribute of an element: <strong>element@attribute=value</strong></p> -->
              <!-- <p>Attribute and content: <strong>element@attribute=value:content</strong></p> -->
Markus Opolka's avatar
Markus Opolka committed
19
20
21
22
23
24
            </v-card-text>
          </v-card>
        </v-expansion-panel-content>
      </v-expansion-panel>
    </v-flex>

Markus Opolka's avatar
Markus Opolka committed
25
    <!-- Main Input Field -->
26
    <v-flex xs12 md9>
Markus Opolka's avatar
Markus Opolka committed
27
28
29
30
31
32
33
      <v-text-field
        v-model="search"
        label="Query"
        data-vv-search="search"
        required
        @keyup.enter.native="validate"
        ></v-text-field>
34
35
    </v-flex>

Markus Opolka's avatar
Markus Opolka committed
36
    <!-- Search Buttons -->
37
38
39
40
41
    <v-flex xs12 md3>
      <v-btn @click="validate" color="blue-grey darken-2" class="white--text">Search</v-btn>
      <v-btn @click="clear" color="blue-grey darken-2" class="white--text">Clear</v-btn>
    </v-flex>

Markus Opolka's avatar
Markus Opolka committed
42
43
44
45
    <!-- Options -->
    <v-flex xs9>
    </v-flex>

Markus Opolka's avatar
Markus Opolka committed
46
    <!-- Invalid Search Warning -->
47
48
    <v-flex xs12>
      <v-alert outline color="lime darken-2" icon="warning" :value="invalid">
Markus Opolka's avatar
Markus Opolka committed
49
50
51
52
53
54
        Invalid Search Query
      </v-alert>
    </v-flex>

    <!-- Progress Bar -->
    <v-flex xs12 v-if="searching">
55
      <v-progress-linear indeterminate color="primary"></v-progress-linear>
Markus Opolka's avatar
Markus Opolka committed
56
57
    </v-flex>

Markus Opolka's avatar
Markus Opolka committed
58
    <!-- Search Results Meta -->
59
60
61
    <v-flex xs12 v-if="results">
      <v-card color="blue-grey lighten-1" class="white--text">
        <v-card-text>
62
          Results: {{results.length}} letter(s)
63
64
65
66
        </v-card-text>
      </v-card>
    </v-flex>

Markus Opolka's avatar
Markus Opolka committed
67
    <!-- Search Results -->
Markus Opolka's avatar
Markus Opolka committed
68
    <v-flex xs12 v-if="results">
69
        <result :letter="letter" v-for="letter in results" v-bind:key="letter.url" />
Markus Opolka's avatar
Markus Opolka committed
70
    </v-flex>
Markus Opolka's avatar
Markus Opolka committed
71

Markus Opolka's avatar
Markus Opolka committed
72
  </v-layout>
Markus Opolka's avatar
Markus Opolka committed
73
74
75
76
 </v-container>
</template>

<script>
Markus Opolka's avatar
Markus Opolka committed
77
export default {
Markus Opolka's avatar
Markus Opolka committed
78
  // General Search Component
Markus Opolka's avatar
Markus Opolka committed
79
80
81
82
83
84
  name: 'Search',
  data () {
    return {
      header: 'Search',
      invalid: false,
      search: '',
85
      pattern: '^([a-z]+):(.+)',
Markus Opolka's avatar
Markus Opolka committed
86
      results: null,
Markus Opolka's avatar
Markus Opolka committed
87
      searching: false,
88
      cutoff: 100,
Markus Opolka's avatar
Markus Opolka committed
89
      showlabels: false
Markus Opolka's avatar
Markus Opolka committed
90
91
92
    }
  },
  methods: {
93
94
    find (params) {
      // Call search API
Markus Opolka's avatar
Markus Opolka committed
95
96
97
98
99
100
      // Remove undefined values
      Object.keys(params).forEach((key) => (params[key] == null) && delete params[key])
      this.searching = true
      this.$http.get('http://localhost:3000/api/search/', {params: params}).then(function (data) {
        this.results = data.body
        this.searching = false
Markus Opolka's avatar
Markus Opolka committed
101
      })
Markus Opolka's avatar
Markus Opolka committed
102
    },
Markus Opolka's avatar
Markus Opolka committed
103
    validate () {
Markus Opolka's avatar
Markus Opolka committed
104
      // Validate input field
105
      let search = this.search.split(':')
Markus Opolka's avatar
Markus Opolka committed
106

107
108
109
110
111
112
113
114
115
116
117
      // If no element is entered we search the text <l>
      if (typeof search[1] === 'undefined') {
        search.unshift('l')
      }

      let params = {
        element: search[0],
        content: search[1]
      }

      if (!params.content) {
Markus Opolka's avatar
Markus Opolka committed
118
        this.invalid = true
119
120
121
      } else {
        this.invalid = false
        this.find(params)
Markus Opolka's avatar
Markus Opolka committed
122
      }
Markus Opolka's avatar
Markus Opolka committed
123
124
    },
    clear () {
Markus Opolka's avatar
Markus Opolka committed
125
      // Clear input field
Markus Opolka's avatar
Markus Opolka committed
126
127
      this.invalid = false
      this.search = ''
Markus Opolka's avatar
Markus Opolka committed
128
129
    }
  }
Markus Opolka's avatar
Markus Opolka committed
130
}
Markus Opolka's avatar
Markus Opolka committed
131
</script>