CellEditor.vue 13.9 KB
Newer Older
Anton's avatar
Intial  
Anton committed
1
2
<template lang="pug">

christianrhansen's avatar
christianrhansen committed
3
  div.q-pb-md.full-height(style="overflow-y: scroll;")
christianrhansen's avatar
christianrhansen committed
4
    //---------------------------------------------------------------------------------------------------- source header
5
6
7
    .q-pl-md.q-py-xs(style="border-bottom: 1px solid rgba(255,255,255,0.04);")
      q-item.q-pa-none(style="height: 54px;")
        q-item-main.text-grey-3
8
          strong Edit Cell
9
10
11
12
        q-item-side.text-right.q-pr-xs
          q-btn.q-mr-sm.text-grey-3(@click="closePanel()", flat, no-ripple, round,
            style="width: 42px; height: 42px;")
            q-icon(name="clear", size="18px")
Anton's avatar
Intial  
Anton committed
13

14
    q-list.q-pa-none.ani-opacity(v-for="(cell, index) in cells", :key="cell._uuid")
Anton's avatar
Intial  
Anton committed
15

christianrhansen's avatar
christianrhansen committed
16
      //--------------------------------------------------------------------------------------------------------- header
17
      q-item.q-pa-none.q-my-sm
18
        q-item-main.text-grey-3.q-pl-md
19
          strong {{ itemSpecs[cell.configuration._value.component].type }}
Anton's avatar
Intial  
Anton committed
20

21
        q-item-side.text-grey-3.text-right
22
          q-btn.q-py-sm.q-px-md.text-red(@click="deleteCell(annotations[index])", size="xs", flat, no-ripple)
23
            q-icon(name="delete", size="20px")
Christian Hansen's avatar
Christian Hansen committed
24

christianrhansen's avatar
christianrhansen committed
25
      //-------------------------------------------------------------------------------------------------- preview image
26
      q-item.q-pa-none.q-mx-md.q-mb-md(v-if="cell.configuration._value.component === 'CellImage'",
27
      :class="[isMobile ? '' : 'q-mt-sm']")
28
        img(:src="cell.source._value.content", style="max-height: 50vh; max-width: 100%; margin: 0 auto;")
29

christianrhansen's avatar
christianrhansen committed
30
      //---------------------------------------------------------------------------------------------------------- input
31
32
33
      q-item.q-pa-none.q-px-md.q-pb-lg(
      :class="[isMobile ? '' : 'q-mt-sm']",
      style="border-bottom: 1px solid rgba(255,255,255,0.04);")
34

35
36
        q-item-main.bg-grey-9.q-py-sm(
        style="border-radius: .15rem;")
christianrhansen's avatar
christianrhansen committed
37

38
39
40
41
42
43
44
45
46
47
48
49
          q-item-tile.q-px-md
            q-field(
            :helper="itemSpecs[cell.configuration._value.component].help",
            :error="itemSpecs[cell.configuration._value.component].error",
            :error-label="itemSpecs[cell.configuration._value.component].errorMessage",
            style="width: 100%")
              template(v-if="itemSpecs[cell.configuration._value.component].inputType === 'select'")
                q-select(
                :float-label="itemSpecs[cell.configuration._value.component].label",
                :options="itemSpecs[cell.configuration._value.component].selectOptions",
                @select="value => handleItemChanged(value, cell, itemSpecs[cell.configuration._value.component].path)")
              template(v-else)
Christian Hansen's avatar
Christian Hansen committed
50
                q-input(
51
                dark,
52
                :type="itemSpecs[cell.configuration._value.component].inputType",
53
54
                :min-rows="1",
                :max-height="500",
55
56
                :value="cell.source._value[itemSpecs[cell.configuration._value.component].path]",
                @change="value => handleItemChanged(value, cell, itemSpecs[cell.configuration._value.component].path)",
57
                hide-underline)
58
59
60

      //-------------------------------------------------------------------------------------------- features (optional)
      template(v-if="itemSpecs[cell.configuration._value.component].features.length")
christianrhansen's avatar
christianrhansen committed
61
62
        q-item.q-pt-md.native.cursor-pointer(
        @click.native="toggleFeatures()", style="border-top: 1px solid rgba(255,255,255,0.2);")
63
64
          q-item-main {{ itemSpecs[cell.configuration._value.component].type }}-Features
          q-item-side
christianrhansen's avatar
christianrhansen committed
65
            q-btn.text-grey-3(round, flat)
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
              q-icon(v-if="!show.features", name="keyboard_arrow_down")
              q-icon(v-else, name="keyboard_arrow_up")
        template(v-if="show.features")
          q-item(v-for="spec in itemSpecs[cell.configuration._value.component].features")
            q-item-main.bg-grey-9.q-py-sm
              q-item-tile.q-px-md
                q-input(
                dark,
                :stack-label="spec.label",
                :type="spec.inputType",
                :min-rows="1",
                :max-height="500",
                :value="cell.source._value[spec.path]",
                @change="value => handleItemChanged(value, cell, spec.path)",
                hide-underline)
                //
                  cell-features(:cell="cell")
83

christianrhansen's avatar
christianrhansen committed
84
      //--------------------------------------------------------------------------------------- media-/annotation-button
85
      q-item.q-pa-none.q-mt-md(v-if="cell.configuration._value.component === 'CellMedia' || cell.configuration._value.component === 'CellAnnotationList'")
86

Anton's avatar
Intial  
Anton committed
87
88
89
</template>

<script>
90
  import { mapGetters } from 'vuex'
91
  // import CellFeatures from './CellFeatures'
92

Anton's avatar
Intial  
Anton committed
93
  export default {
94
    // props: ['cells'],
christianrhansen's avatar
christianrhansen committed
95
    components: {
96
      // CellFeatures
christianrhansen's avatar
christianrhansen committed
97
    },
Anton's avatar
Intial  
Anton committed
98
99
    data () {
      return {
100
        show: {features: true},
101
        isMobile: undefined,
102
103
        cells: [],
        cellSourceValues: {},
Anton's avatar
Intial  
Anton committed
104
105
106
107
        typeToIconName: {
          'Image': 'photo',
          'IFrame': 'picture in picture',
          'Internal-Link': 'link',
Anton's avatar
Anton committed
108
          'Media': 'local movies',
Anton's avatar
Intial  
Anton committed
109
          'Text': 'subject',
Christian Hansen's avatar
Christian Hansen committed
110
111
          'Title': 'title',
          'Annotation-List': 'comment'
Anton's avatar
Intial  
Anton committed
112
113
        },
        itemSpecs: {
114
          'CellTitle': {
115
            inputType: 'textarea',
Anton's avatar
Intial  
Anton committed
116
117
118
119
120
            type: 'Title',
            label: 'Title Cell',
            help: '',
            error: false,
            errorMessage: '',
Anton's avatar
Anton committed
121
            value: '',
122
123
124
125
126
127
128
129
130
131
132
            path: 'content',
            features: [{
              inputType: 'url',
              type: 'Title',
              label: 'Link URL',
              help: 'Insert any valid URL',
              error: false,
              errorMessage: 'Needs to be a valid URL',
              value: '',
              path: 'link'
            }]
Anton's avatar
Anton committed
133
          },
134
          'CellText': {
Anton's avatar
Intial  
Anton committed
135
136
137
138
139
140
            inputType: 'textarea',
            type: 'Text',
            label: 'Text Cell',
            help: '',
            error: false,
            errorMessage: '',
Anton's avatar
Anton committed
141
            value: '',
142
143
144
145
            path: 'content',
            features: []
          },
          'CellMedia': {
Anton's avatar
Intial  
Anton committed
146
            inputType: 'url',
147
148
            type: 'Media',
            label: 'Media Cell',
Anton's avatar
Intial  
Anton committed
149
150
151
            help: 'Insert a URL to: a video file or a Vimeo / YouTube video page',
            error: false,
            errorMessage: 'Needs to be a valid URL',
Anton's avatar
Anton committed
152
            value: '',
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
            path: 'content',
            features: [
              {
                inputType: 'number',
                type: 'Video',
                label: 'Start',
                help: 'Set start point (seconds)',
                error: false,
                errorMessage: 'Needs to be a valid number',
                value: 0,
                path: 'start'
              },
              {
                inputType: 'number',
                type: 'Video',
                label: 'Duration',
                help: 'Set duration (seconds)',
                error: false,
                errorMessage: 'Needs to be a valid number',
                value: 0,
                path: 'duration'
              }
            ]
176
          },
177
          'CellImage': {
Anton's avatar
Intial  
Anton committed
178
179
180
181
182
183
            inputType: 'url',
            type: 'Image',
            label: 'Image Cell',
            help: 'Insert a URL to an image file',
            error: false,
            errorMessage: 'Needs to be a valid URL',
Anton's avatar
Anton committed
184
            value: '',
185
186
187
188
189
190
191
192
193
194
195
196
197
            path: 'content',
            features: [
              {
                inputType: 'url',
                type: 'Image',
                label: 'Link URL',
                help: 'Insert any valid URL',
                error: false,
                errorMessage: 'Needs to be a valid URL',
                value: '',
                path: 'link'
              }
            ]
Anton's avatar
Anton committed
198
          },
199
          'CellInternalLink': {
Anton's avatar
Intial  
Anton committed
200
201
202
203
204
205
            inputType: 'url',
            type: 'Internal-Link',
            label: 'Link Cell',
            help: 'Insert a URL to a page in this system',
            error: false,
            errorMessage: 'Needs to be a valid URL',
Anton's avatar
Anton committed
206
            value: '',
207
208
209
210
            path: 'content',
            features: []
          },
          'CellIFrame': {
Anton's avatar
Intial  
Anton committed
211
212
213
214
215
216
            inputType: 'url',
            type: 'IFrame',
            label: 'IFrame Cell',
            help: 'Insert some URL',
            error: false,
            errorMessage: 'Needs to be a valid URL',
Anton's avatar
Anton committed
217
            value: '',
218
219
220
221
            path: 'content',
            features: []
          },
          'CellAnnotationList': {
Anton's avatar
Intial  
Anton committed
222
223
224
225
226
227
            inputType: 'text',
            type: 'Annotation-List',
            label: 'Annotation List Cell',
            help: 'Insert a Video UUID',
            error: false,
            errorMessage: '',
Anton's avatar
Anton committed
228
            value: '',
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
            path: 'content',
            features: [
              {
                inputType: 'number',
                type: 'Annotation-List',
                label: 'Add annotations',
                help: 'Allow user to add more annotations (0 or 1)',
                error: false,
                errorMessage: '',
                value: 0,
                path: 'allow_annotations'
              },
              {
                inputType: 'number',
                type: 'Annotation-List',
                label: 'Start',
                help: 'Filter from video start point (seconds)',
                error: false,
                errorMessage: 'Needs to be a valid number',
                value: 0,
                path: 'start'
              },
              {
                inputType: 'number',
                type: 'Annotation-List',
                label: 'Duration',
                help: 'Filter duration (seconds)',
                error: false,
                errorMessage: 'Needs to be a valid number',
                value: 0,
                path: 'duration'
              },
              {
                inputType: 'text',
                type: 'Annotation-List',
                label: 'Textfilter',
                help: 'Filter annotations by search string',
                error: false,
                errorMessage: '',
                value: undefined,
                path: 'textfilter'
              },
              {
                inputType: 'text',
                type: 'Annotation-List',
                label: 'RegExp',
Mathias Bär's avatar
Mathias Bär committed
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
                help: 'Filter annotations by regular expression',
                error: false,
                errorMessage: '',
                value: undefined,
                path: 'regexp'
              },
              // {
              //   inputType: 'select',
              //   type: 'Annotation-List',
              //   label: 'Display type',
              //   help: '',
              //   error: false,
              //   errorMessage: '',
              //   value: 'scroll-list',
              //   path: 'displayType',
              //   selectOptions: [
              //     {
              //       label: 'Scroll List',
              //       value: 'scroll-list'
              //     },
              //     {
              //       label: 'Tab List',
              //       value: 'tabs'
              //     }
              //   ]
              // }
              {
                inputType: 'text',
                type: 'Annotation-List',
                label: 'Display type',
                help: 'Either "scroll-list" or "tabs"',
                error: false,
                errorMessage: '',
                value: undefined,
                path: 'displayType'
              }
            ]
          }
Anton's avatar
Intial  
Anton committed
314
315
316
        }
      }
    },
317
318
319
    computed: {
      ...mapGetters({
        // showEditingCells: 'mosys/getShowEditingCells'
320
        annotations: 'mosys/getEditingCells'
321
322
      })
    },
Christian Hansen's avatar
Christian Hansen committed
323
    watch: {
324
325
      async annotations (val) {
        this.getCells(val)
Christian Hansen's avatar
Christian Hansen committed
326
327
328
      }
    },
    mounted () {
329
      this.isMobile = this.$q.platform.is.mobile
330
      this.getCells(this.annotations)
Christian Hansen's avatar
Christian Hansen committed
331
    },
Anton's avatar
Intial  
Anton committed
332
    methods: {
333
334
335
      toggleFeatures () {
        this.show.features = !this.show.features
      },
336
337
338
339
340
341
      closePanel () {
        this.$emit('closePanel')
        this.closeHandler()
      },
      deleteCell (annotation) {
        this.$emit('removeCell', annotation)
342
343
344
345
346
347
        this.closeHandler()
      },
      closeHandler () {
        this.$store.commit('mosys/setEditCellModal', false)
        // this.$store.commit('mosys/setEditingCells', '')
      },
348
349
350
351
352
353
354
      async getCells (annotations) {
        this.cells = []
        for (let i = 0; i < annotations.length; i++) {
          let c = await this.$store.dispatch('cells/get', annotations[i].body.source.id)
          c.configuration.value = Object.assign({}, c.configuration._value, { path: 'content' })
          this.cells.push(c)
          this.cellSourceValues[c.id] = c.source._value
Christian Hansen's avatar
Christian Hansen committed
355
356
        }
      },
357
      async handleItemChanged (value, cell, path) {
Anton's avatar
Intial  
Anton committed
358
        if (cell.inputType !== 'url') {
359
          await this.updateCellContent(value, cell, path)
Anton's avatar
Intial  
Anton committed
360
361
362
363
        }
        else {
          cell.error = !(/^http[s]?:\/\/.+/.test(value))
          if (!cell.error) {
364
            await this.updateCellContent(value, cell, path)
Anton's avatar
Intial  
Anton committed
365
366
367
          }
        }
      },
368
      async updateCellContent (value, cell, path) {
369
        if (cell.id) {
370
371
372
373
          const sourceValue = Object.assign({}, cell.source._value)
          sourceValue[path] = value
          cell.source.value = sourceValue
          await this.$store.dispatch('cells/patch', [cell.id, { source: cell.source }])
374
375
376
377
        }
      },
      async updateCellConfig (value, cell, path) {
        if (cell.id) {
378
379
380
381
          const configurationValue = Object.assign({}, cell.configuration._value)
          configurationValue[path] = value
          cell.configuration.value = configurationValue
          await this.$store.dispatch('cells/patch', [cell.id, { configuration: cell.configuration }])
Anton's avatar
Intial  
Anton committed
382
383
384
385
386
387
        }
      }
    }
  }
</script>

388
<style scoped lang="stylus">
389
  @import '~variables'
390
391
392
393
394
395
396
397
398
399
400
401

  .ani-opacity
    animation ani-opacity ease 220ms
  @keyframes ani-opacity {
    from { opacity: 0 }
    to {opacity: 1}
  }

  .media-button
    width: 42px
    border-radius: .35rem

402
403
  .header
    border-bottom 1px solid $grey-4
404
</style>