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

3
  div.cell-grid-container(
4
  :class="{'overflow-hidden': activeHandler}",
5
  style="overflow-y: hidden; scroll-behavior: smooth;")
christianrhansen's avatar
christianrhansen committed
6

christianrhansen's avatar
christianrhansen committed
7 8 9
    q-window-resize-observable(@resize="updateGridDimensions")

    //----- modal for existing cell editing
10
    q-modal(v-model="modal", minimized, content-css="background-color: #eee; border-radius: .75rem;")
11
      grid-editor-editing-cells-mobile
12

christianrhansen's avatar
christianrhansen committed
13
    // ----------------------------------------------------------------------------------------------- "new cell"-header
14 15
    #new-cell-header.fixed-top.z-top.bg-dark.text-white.transition(:class="{'show': cachedNewCell}")
      q-item.q-pl-md.q-pr-xs.q-py-none.full-height
16
        q-item-main
17
          strong New {{ newCellType }}
18

christianrhansen's avatar
christianrhansen committed
19 20
        q-item-side.text-white
          q-btn(@click="event => {addMobileCell(event)}", round, flat)
21 22
            q-icon(name="check")

christianrhansen's avatar
christianrhansen committed
23
          q-btn.clear-button.q-px-md.q-mr-md.on-right(@click="clearHandler('cached cell')", flat)
christianrhansen's avatar
christianrhansen committed
24
            q-icon(name="clear")
25

christianrhansen's avatar
christianrhansen committed
26
    // ------------------------------------------------------------------------------------------ "selected cell"-header
27
    #selected-cell-header.fixed-top.z-top.bg-dark.text-white.transition(:class="{'show': showEditingCells}")
28
      q-item.q-pl-md.q-pr-none.q-py-none.full-height(v-if="!modal")
29
        q-item-main
30
          strong {{ selectedCell.type }}
31

christianrhansen's avatar
christianrhansen committed
32 33
        q-item-side.text-white
          q-btn.q-px-sm(@click="event => {handleCellEdit(event, selectedCell.annotation)}", flat)
34 35
            q-icon(name="edit")

christianrhansen's avatar
christianrhansen committed
36 37
          q-btn.q-px-sm.on-right.on-left(
          @click="event => {handleCellContextMenuDelete(event, mobileSelectedCell)}", flat)
38
            q-icon(name="delete")
39

christianrhansen's avatar
christianrhansen committed
40
          q-btn.clear-button.q-px-md.q-mr-md.on-right(@click="clearHandler('cell')", flat)
41 42
            q-icon(name="clear")

43
    // ------------------------------------------------------------------------------------------------------------ grid
44
      @click="event => {addMobileCell(event)}",
45
    div.cell-grid.relative-position(
46
    v-touch-pan="panGrid",
47 48 49 50 51 52
    @dragenter="handleGridDragOver",
    @dragover="handleGridDragOver",
    @dragleave="handleGridDragEnd",
    @drop="handleGridDrop",
    @contextmenu="handleGridContextMenu",
    :style="gridStyle")
Anton's avatar
Intial  
Anton committed
53

54 55
      // context menu grid (desktop only)
      q-context-menu.desktop-only(ref="gridmenu")
Anton's avatar
Intial  
Anton committed
56 57
        q-list(link, separator, no-border, style="min-width: 150px; max-height: 300px;")
          q-item(
58 59 60 61 62
          v-for="action in gridContextMenuActions",
          :key="action.label",
          v-close-overlay,
          @click.native="event => {action.handler(event)}")
            q-item-main(:label="action.label")
Anton's avatar
Intial  
Anton committed
63 64 65

      template(v-if="!resizingGrid")

66
        template(v-for="(annotation, index) in annotations")
christianrhansen's avatar
christianrhansen committed
67 68

          //----- cell
69
          // v-touch-hold="event => {cellHold(event, annotation)}",
Anton's avatar
Intial  
Anton committed
70
          .cell-item(
71 72 73 74 75 76 77 78 79 80
          v-if="!annotationUIStates[annotation._uuid] || !annotationUIStates[annotation._uuid].beingDragged",
          draggable="true",
          @click.prevent="event => {handleCellTouch(event, annotation)}",
          @dragstart="event => {handleCellDragStart(event, annotation)}",
          @dragend="event => {handleCellDragEnd(event, annotation)}",
          @contextmenu="handleCellContextMenu",
          :style="getAnnotationStyle(annotation)",
          :class="getAnnotationClasses(annotation._uuid, 'cell-item')",
          :key="`cell-${index}`")

81
            //--------------------------------------------------------------------------------------- edit-/close-button
82
            // TODO: find a more elegant solution
83
            //-------------------------------------------------------------------------------------------------- desktop
84
            .desktop-only
Mathias Bär's avatar
Mathias Bär committed
85
              q-btn.edit-button.absolute-top-right(
86 87 88 89 90
              @click.prevent="event => {handleCellEditClick(event, annotation)}",
              :class="getAnnotationClasses(annotation._uuid, 'editing')",
              style="top: 8px; right: 8px;",
              :icon="annotationUIStates[annotation._uuid].editing ? 'close' : 'edit'", flat, round, size="md"
              )
91
            //--------------------------------------------------------------------------------------------------- mobile
92
            .mobile-only
93
              .edit-button.absolute.fit.bg-transparent(
94
              v-touch-hold="event => {handleCellEdit(event, annotation)}",
95
              @click.prevent="event => {touchMobileCell(event, annotation)}")
96

97 98 99
                //
                  q-btn.absolute-top-right.text-dark.q-pa-none.q-mr-xs(
                  v-if="showEditingCells",
100
                  @click.prevent="event => {handleCellEdit(event, annotation)}",
101 102
                  flat, round, size="sm", style="margin-top: 2px;")
                    q-icon(name="edit", size="20px")
christianrhansen's avatar
christianrhansen committed
103

104 105 106
              //----- invisible edit-modal handler
              //
                q-btn.absolute-top-left.bg-blue(
107
                @click.prevent="event => {handleCellEdit(event, annotation)}", flat, style="opacity: 0") bla
108
                // @click.prevent="handleModal()", flat, style="opacity: 0") bla
109

110
            //----- selecting cells disabled because it has no use currently
111 112 113 114 115 116 117 118
            // switch with cell component below to re-enable it
            //cell(
              @click.native.prevent="event => {handleCellClick(event, annotation)}", :annotation="annotation", :preview="true")
            cell(
            :annotation="annotation",
            :preview="true"
            )

christianrhansen's avatar
christianrhansen committed
119
            //----- resize-handler (desktop only)
120
            .desktop-only.cell-item-resize-handle(
121 122 123 124
            draggable="true",
            @dragstart="event => {handleCellResizerDragStart(event, annotation)}",
            @dragend="event => {handleCellResizerDragEnd(event, annotation)}",
            @dragexit="event => {handleCellResizerDragEnd(event, annotation)}")
125
              q-icon.q-ma-xs(name="network cell")
126

127 128 129
            //----- context menu for cells (desktop only)
            // TODO: needs revision
            q-context-menu.desktop-only
130 131 132 133 134 135 136
              q-list(link, separator, no-border, style="min-width: 150px; max-height: 300px;")
                q-item(
                v-for="action in cellContextMenuActions",
                :key="action.label",
                v-close-overlay,
                @click.native="event => {action.handler(event, annotation)}")
                  q-item-main(:label="action.label")
Anton's avatar
Intial  
Anton committed
137

138
        //----- temporary cell when pulling a new cell into grid (desktop)
139
        template(v-for="(tmpCell, index) in tmpObjects")
140
          .cell-item.cell-item-tmp(:style="getAnnotationStyle(tmpCell)", :key="`cell-tmp-${index}`")
Anton's avatar
Intial  
Anton committed
141 142
            cell(:cell="tmpCell")

christianrhansen's avatar
christianrhansen committed
143
        //-------------------------------------------------------------------------------------- temporary cell (mobile)
144
        template(v-if="mobileTempCell.show && cachedNewCell")
145

146 147 148
          .cell-item.cell-item-tmp-mobile.row.justify-center.items-center(
          ref="_mobileTempCell",
          :style="mobileTempCellStyle(mobileTempCell)")
149

christianrhansen's avatar
christianrhansen committed
150
            cell.absolute-top-left.q-ma-sm(:cell="cachedNewCell", :temp="true")
151

152 153 154 155 156
            //
              q-btn.text-white(v-if="mobileTempCell.button",
              @click="event => {addMobileCell(event)}", round, flat, size="lg",
              style="background-color: rgba(0, 0, 0, 0);")
                q-icon(name="check")
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
        //------------------------------------------------------------------------------------------------- move handler
        //----- (main)
        cell-handler-mobile.main-handler.shadow-1(
        v-if="!cellHandler.resize.pushed",
        @onIntersectionChange="intersectionChanged",
        :element="'move'",
        v-touch-pan="handleMoveCell",
        :style="{left: cellHandler.move.x - 20 + 'px', top: cellHandler.move.y - 20 + 'px'}",
        :class="[{'pushed': !cellHandler.move.pushed}, {'hide': !mobileTempCell.onGrid && !showEditingCells}]")
          q-icon.rotate-180(name="open_with", size="22px")

        //----- (temp)
        //----- (when main move handler is outside of viewport)
        cell-handler-mobile.temp-handler.shadow-1(
        v-touch-pan="handleMoveCell",
        :doubleTap="{el: $el, type: 'scroll', oLeft: mobileTempCell.left}",
        :class="[(!mobileTempCell.onGrid || tempHandler.move.intersectingMainHandler || cellHandler.resize.pushed || cellHandler.move.pushed ? 'hide': 'show'), (tempHandler.move.side === 'left' ? 'left-side' : 'right-side')]",
        :style="{top: cellHandler.move.y + 59 - 20 + 'px'}",)
          q-icon.rotate-180(name="open_with", size="22px")

        //----------------------------------------------------------------------------------------------- resize handler
        //----- (main)
        cell-handler-mobile.main-handler.shadow-1(
        v-if="!cellHandler.move.pushed",
        @onIntersectionChange="intersectionChanged",
        :element="'resize'",
        v-touch-pan="handleResizeCell",
        :style="{left: cellHandler.resize.x - 20 + 'px', top: cellHandler.resize.y - 20 + 'px'}",
        :class="[{'pushed': !cellHandler.resize.pushed}, {'hide': !mobileTempCell.onGrid && !showEditingCells}]")
          q-icon(name="signal_cellular_4_bar", size="12px", style="margin-left: -3px;")

        //----- (temp)
        //----- (when main resize handler is outside of viewport)
        cell-handler-mobile.temp-handler.shadow-1(
        v-touch-pan="handleResizeCell",
        :class="[(!mobileTempCell.onGrid || tempHandler.resize.intersectingMainHandler || cellHandler.move.pushed || cellHandler.resize.pushed ? 'hide': 'show'), (tempHandler.resize.side === 'left' ? 'left-side' : 'right-side')]",
        :style="{top: cellHandler.resize.y + 59 - 20 + 'px'}",)
          q-icon(name="signal_cellular_4_bar", size="12px", style="margin-left: -3px;")
196

christianrhansen's avatar
christianrhansen committed
197
      // ---------------------------------------------------------------------------------------------------------------
Anton's avatar
Intial  
Anton committed
198
      template(v-else)
199
        .cell-item(:style="getAnnotationStyle({x:0,y:0,width:1,height:1})", key="cell-grid-resizer")
Anton's avatar
Intial  
Anton committed
200
          div.cell-item-resize-handle(
201 202 203 204 205
          draggable="true",
          @dragstart="event => {handleGridResizerDragStart(event)}",
          @dragend="event => {handleGridResizerDragEnd(event)}",
          @dragexit="event => {handleGridResizerDragEnd(event)}")
            q-icon(name="network cell")
Anton's avatar
Intial  
Anton committed
206

Mathias Bär's avatar
Mathias Bär committed
207
      //template(v-if="!isMobile")
208 209 210 211 212
        .fixed-top-right(style="right:18px; top:68px", v-if="!$store.state.mosys.showSources")
          q-btn(round, color="primary", small, @click="handleGridButtonClickEdit", style="margin-right: 0.5em")
            q-icon(name="add")
          q-btn(round, color="primary", small, @click="$router.push(`/mosys/grids/${$route.params.uuid}`)")
            q-icon(name="remove red eye")
Mathias Bär's avatar
Mathias Bär committed
213
      //template(v-if="isMobile")
Mathias Bär's avatar
Mathias Bär committed
214 215 216 217 218
        .fixed-top-right.q-mt-sm(v-if="!$store.state.mosys.showSources", style="z-index: 10000; padding-top: 3px;")
          q-btn.q-mr-sm(round, color="primary", size="sm", @click="handleGridButtonClickEdit")
            q-icon(name="add")
          q-btn.q-mr-md(round, color="primary", size="sm", @click="$router.push(`/mosys/grids/${$route.params.uuid}`)")
            q-icon(name="remove red eye")
Anton's avatar
Intial  
Anton committed
219

220
    // ------------------------------------------------------------------------------------------ edit box (mobile only)
221

222
    q-page-sticky.edit-box.q-mx-md.q-mb-md.transition-bottom.backdrop-filter.shadow-6.overflow-hidden.hidden(
christianrhansen's avatar
christianrhansen committed
223
    v-if="isMobile",
224
    :class="[{'show-full' : carousel.visibility && showEditingCells}, {'show-minimized' : showEditingCells}]",
225
    style="border-radius: .5rem;",
226
    position="bottom-right")
christianrhansen's avatar
christianrhansen committed
227

228
      //------------------------- buttons
229 230
      // .row.text-dark(style="background-color: rgba(0, 0, 0, .2);")
      .row.text-dark(style="background-color: rgba(255, 150, 150, .3);")
231 232 233

        //----- delete cell
        .col
christianrhansen's avatar
christianrhansen committed
234
          q-btn.q-py-none.q-pl-sm.q-ml-xs(
235
            @click="event => {handleCellContextMenuDelete(event, mobileSelectedCell)}", flat, no-ripple)
christianrhansen's avatar
christianrhansen committed
236
            q-icon(name="delete")
christianrhansen's avatar
christianrhansen committed
237

238 239
        //----- toggle edit-box
        .col.text-right
christianrhansen's avatar
christianrhansen committed
240
          q-btn.q-py-none.q-pr-sm.q-mr-xs(@click="carouselVisibility()", flat, no-ripple)
christianrhansen's avatar
christianrhansen committed
241 242
            q-icon(v-if="carousel.visibility", name="keyboard_arrow_down")
            q-icon(v-else, name="keyboard_arrow_up")
243

christianrhansen's avatar
christianrhansen committed
244
      //q-item-separator.q-ma-none
245 246 247 248 249 250

      //------------------------- carousel
      q-carousel.q-py-sm.carousel.transition-opacity(ref="carousel", v-model="slide",
      infinite, @input="getCarouselIcon(index)", style="width: 180px;")

        //----- move
christianrhansen's avatar
christianrhansen committed
251 252
        // q-carousel-slide.q-py-sm
        q-carousel-slide.q-py-none
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
          .text-center
            q-btn.edit-cell-button(@click="mobileCellMove(mobileSelectedCell, 0, -1)", round, flat, size="md")
              q-icon.rotate-90(name="keyboard_backspace")
          .text-center
            q-btn.edit-cell-button(@click="mobileCellMove(mobileSelectedCell, -1, 0)", round, flat, size="md")
              q-icon(name="keyboard_backspace")
            q-btn.invisible.text-dark(round, flat, size="md")
              q-icon.flip-vertical(name="photo_size_select_small")
            q-btn.edit-cell-button(@click="mobileCellMove(mobileSelectedCell, 1, 0)", round, flat, size="md")
              q-icon.rotate-180(name="keyboard_backspace")
          .text-center
            q-btn.edit-cell-button(@click="mobileCellMove(mobileSelectedCell, 0, 1)", round, flat, size="md")
              q-icon.rotate-270(name="keyboard_backspace")

        //----- resize
christianrhansen's avatar
christianrhansen committed
268 269
        // q-carousel-slide.q-py-sm
        q-carousel-slide.q-py-none
270 271 272 273 274 275 276 277 278 279 280 281 282
          .text-center
            q-btn.edit-cell-button(@click="mobileCellResize(mobileSelectedCell, 0, -1)", round, flat, size="md")
              q-icon(name="remove")
          .text-center
            q-btn.edit-cell-button(@click="mobileCellResize(mobileSelectedCell, -1, 0)", round, flat, size="md")
              q-icon(name="remove")
            q-btn.invisible.text-dark(round, flat, size="md")
              q-icon.rotate-45(name="zoom_out_map")
            q-btn.edit-cell-button(@click="mobileCellResize(mobileSelectedCell, 1, 0)", round, flat, size="md")
              q-icon(name="add")
          .text-center
            q-btn.edit-cell-button(@click="mobileCellResize(mobileSelectedCell, 0, 1)", round, flat, size="md")
              q-icon(name="add")
Anton's avatar
Intial  
Anton committed
283 284 285 286
</template>

<script>
  import Cell from './Cell'
287 288
  import { userHasFeature } from 'mbjs-quasar/src/lib'
  import { mapGetters } from 'vuex'
289
  import GridEditorEditingCellsMobile from './/GridEditorEditingCellsMobile'
290
  import CellHandlerMobile from './CellHandlerMobile'
Anton's avatar
Intial  
Anton committed
291 292 293 294 295 296

  const nullImage = new Image()
  nullImage.src = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='

  export default {
    components: {
297
      Cell,
298 299
      GridEditorEditingCellsMobile,
      CellHandlerMobile
Anton's avatar
Intial  
Anton committed
300
    },
301
    props: ['gridUuid', 'tabsAreOpen'],
Anton's avatar
Intial  
Anton committed
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
    data () {
      return {
        gridContextMenuActions: {
          insert_column_left: {
            label: 'Insert Column Left',
            handler: this.handleGridContextMenuInsertColumnLeft
          },
          delete_column: {
            label: 'Delete Column',
            handler: this.handleGridContextMenuDeleteColumn
          },
          insert_row_above: {
            label: 'Insert Row Above',
            handler: this.handleGridContextMenuInsertRowAbove
          },
          delete_row: {
            label: 'Delete Row',
            handler: this.handleGridContextMenuDeleteRow
          },
          edit_grid_dimensions: {
            label: 'Change Grid',
            handler: () => { this.resizingGrid = !this.resizingGrid }
          }
        },
        grid: undefined,
327
        annotations: undefined,
328
        tmpObjects: [],
329
        annotationUIStates: {},
Anton's avatar
Anton committed
330
        gridDimensions: { gridWidth: 0, gridHeight: 0, cellWidth: 0, cellHeight: 0 },
Anton's avatar
Intial  
Anton committed
331
        contextMenuClickPosition: {},
332
        resizingGrid: false,
christianrhansen's avatar
christianrhansen committed
333
        mobileSelectedCell: undefined,
334
        touch: {position: {top: undefined, left: undefined}},
335
        isMobile: this.$q.platform.is.mobile,
336 337 338 339 340 341 342 343 344 345 346 347
        mobileTempCell: {
          x: 0,
          y: 0,
          ox: 0,
          oy: 0,
          width: 1,
          height: 1,
          left: 0,
          show: false,
          onGrid: false,
          button: false
        },
348
        slide: undefined,
349
        modal: false,
350
        carousel: {visibility: false, icon: 'open_with', slide: 0},
christianrhansen's avatar
christianrhansen committed
351
        // cursor: {x: undefined, y: undefined},
352
        cellHandler: {
353
          size: {width: 40, height: 40},
354
          move: {x: 20, y: undefined, gridPosition: {row: undefined, column: undefined}, pushed: false, pos: undefined, inViewport: undefined, onLeft: undefined, onRight: undefined, dataLeft: undefined},
355
          resize: {x: undefined, y: undefined, gridPosition: {row: undefined, column: undefined}, pushed: false, pos: undefined}
356
        },
357
        tempHandler: {
christianrhansen's avatar
christianrhansen committed
358 359
          move: {left: undefined, intersectingMainHandler: false, side: undefined},
          resize: {left: undefined, intersectingMainHandler: false, side: undefined}
360
        },
361
        activeHandler: false,
362
        selectedCell: {type: undefined, annotation: undefined}
Anton's avatar
Intial  
Anton committed
363 364
      }
    },
365 366
    computed: {
      ...mapGetters({
christianrhansen's avatar
christianrhansen committed
367
        cachedNewCell: 'mosys/getNewCell',
368
        user: 'auth/getUserState',
369
        // isMobile: 'globalSettings/getIsMobile',
Mathias Bär's avatar
Mathias Bär committed
370
        // editingCells: 'mosys/getEditingCells'
371
        showEditingCells: 'mosys/getShowEditingCells',
372 373
        scrollPositionCache: 'mosys/getScrollPositionCache',
        editMode: 'mosys/getEditMode'
374
      }),
375 376 377 378 379 380
      newCellType () {
        if (this.cachedNewCell) {
          let type = this.cachedNewCell.component
          return type.substr(4, type.length - 4)
        }
      },
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
      cellContextMenuActions () {
        const actions = {
          delete: {
            label: 'Delete',
            handler: this.handleCellContextMenuDelete
          },
          insert_column_left: {
            label: 'Insert Column Left',
            handler: this.handleGridContextMenuInsertColumnLeft
          },
          insert_row_above: {
            label: 'Insert Row Above',
            handler: this.handleGridContextMenuInsertRowAbove
          }
        }
        if (userHasFeature(this.user, 'cssediting')) {
          actions.edit_css_classname = {
            label: 'Edit CSS class name',
            handler: this.handleCellContextMenuEditCSS
          }
        }
        return actions
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
      },
      gridStyle () {
        if (!this.gridDimensions || !this.gridDimensions.full) return {}
        // TODO: fix mobile grid editor view
        const cell = this.gridDimensions.full.cell
        return {
          width: `${this.gridDimensions.full.width}px`,
          height: '100%',
          'grid-auto-columns': `${cell.width}px`,
          'grid-auto-rows': `${cell.height}px`,
          'background-image': `url("data:image/svg+xml;utf8,` +
            `<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%'><defs>` +
            `<pattern id='smallGrid' width='${cell.width}' height='${cell.height}' patternUnits='userSpaceOnUse'>` +
            `<path d='M ${cell.width} 0 L 0 0 0 ${cell.height}' fill='none' stroke='gray' stroke-width='0.5'/>` +
            `</pattern></defs><rect width='100%' height='100%' fill='url(%23smallGrid)' /></svg>")`
        }
419 420
      }
    },
Anton's avatar
Intial  
Anton committed
421 422
    async mounted () {
      await this.fetchData()
423
      this.resetScrollPosition()
424 425 426
    },
    beforeDestroy () {
      this.observer.disconnect()
Anton's avatar
Intial  
Anton committed
427 428
    },
    watch: {
429
      'cellHandler.move.gridPosition': {
430 431 432 433
        handler: function (obj) {
          if (this.showEditingCells) {
            this.mobileCellMove(this.mobileSelectedCell, obj.column, obj.row)
          }
434 435 436
        },
        deep: true
      },
437 438 439
      'cellHandler.resize.gridPosition': {
        handler: function (obj) {
          if (this.showEditingCells) {
440 441 442
            let w = obj.column - this.cellHandler.move.gridPosition.column + 1
            let h = obj.row - this.cellHandler.move.gridPosition.row + 1
            this.mobileCellResize(this.mobileSelectedCell, w, h)
443 444 445 446
          }
        },
        deep: true
      },
447 448 449 450 451 452 453 454 455 456
      slide (val) {
        let icon
        switch (val) {
        case 0:
          icon = 'open_with'
          break
        case 1:
          icon = 'photo_size_select_small'
          break
        case 2:
457
          icon = 'more_horiz'
458 459 460 461 462
          break
        default:
          icon = 'open_with'
          break
        }
463 464 465
        // this.carousel.slide = val
        // this.carousel.icon = icon
        this.carousel = {slide: val, icon: icon, visibility: this.carousel.visibility}
466
      },
Anton's avatar
Anton committed
467
      annotations () {
468
        this.updateAnnotationUIStates()
Anton's avatar
Intial  
Anton committed
469 470 471 472 473 474
      },
      gridMetadata () {
        this.updateGridDimensions()
      },
      async gridUuid () {
        await this.fetchData()
Mathias Bär's avatar
Mathias Bär committed
475 476
      },
      showEditingCells (val) {
477
        // console.log('show editing cells', val)
Mathias Bär's avatar
Mathias Bär committed
478 479 480
        if (val === false) {
          this.updateAnnotationUIStates()
        }
481 482 483
      },
      tabsAreOpen () {
        this.resetScrollPosition()
Anton's avatar
Intial  
Anton committed
484 485 486
      }
    },
    methods: {
487 488 489 490 491 492 493 494
      clearHandler (target) {
        switch (target) {
        case 'cell':
          Object.keys(this.annotationUIStates).filter((k) => {
            this.annotationUIStates[k].editing = false
          })
          this.$store.commit('mosys/setEditingCells', '')
          break
495 496
        case 'cached cell':
          this.$store.commit('mosys/cacheNewCell', undefined)
497 498 499 500
          this.clearHandler('temp cell')
          break
        case 'temp cell':
          this.mobileTempCell = {x: undefined, y: undefined, width: undefined, height: undefined, onGrid: false, button: false}
501
          break
502 503
        }
      },
504
      intersectionChanged (obj) {
christianrhansen's avatar
christianrhansen committed
505 506
        let _offsetLeft = Math.sign(obj.offsetLeft)

507
        // -------------------- move
508
        if (obj.element === 'move') {
christianrhansen's avatar
christianrhansen committed
509
          this.tempHandler.move.intersectingMainHandler = obj.intersecting
510

christianrhansen's avatar
christianrhansen committed
511
          // behind left side
christianrhansen's avatar
christianrhansen committed
512
          if (_offsetLeft < 0) {
513
            this.tempHandler.move.side = 'left'
514
          }
515
          // intersecting
christianrhansen's avatar
christianrhansen committed
516
          else if (isNaN(_offsetLeft)) {
christianrhansen's avatar
christianrhansen committed
517
            if (this.tempHandler.move.intersectingMainHandler && this.tempHandler.move.side === 'right') this.tempHandler.resize.intersectingMainHandler = false
518
          }
christianrhansen's avatar
christianrhansen committed
519
          // behind right side
christianrhansen's avatar
christianrhansen committed
520
          else if (_offsetLeft === 1) {
521
            this.tempHandler.move.side = 'right'
christianrhansen's avatar
christianrhansen committed
522
            this.tempHandler.resize.intersectingMainHandler = true
523
          }
524
        }
525

526
        // -------------------- resize
christianrhansen's avatar
christianrhansen committed
527
        else if (obj.element === 'resize') {
christianrhansen's avatar
christianrhansen committed
528
          this.tempHandler.resize.intersectingMainHandler = obj.intersecting
529

christianrhansen's avatar
christianrhansen committed
530
          // on left side
christianrhansen's avatar
christianrhansen committed
531
          if (_offsetLeft === -1) {
532
            this.tempHandler.resize.side = 'left'
533
          }
christianrhansen's avatar
christianrhansen committed
534
          /*
535
          // intersecting
christianrhansen's avatar
christianrhansen committed
536
          else if (isNaN(Math.sign(obj.offsetLeft))) {
537
          }
christianrhansen's avatar
christianrhansen committed
538
          */
christianrhansen's avatar
christianrhansen committed
539
          // on right side
christianrhansen's avatar
christianrhansen committed
540
          else if (_offsetLeft === 1) {
541
            this.tempHandler.resize.side = 'right'
542
          }
543 544
        }
      },
christianrhansen's avatar
christianrhansen committed
545
      handleMoveCell (obj) {
546 547
        this.cellHandler.move.x = obj.position.left
        this.cellHandler.move.y = obj.position.top
548

christianrhansen's avatar
christianrhansen committed
549 550
        let res = this.getGridPositionForEvent(obj)

551 552 553
        this.cellHandler.move.gridPosition.row = res.y
        this.cellHandler.move.gridPosition.column = res.x

christianrhansen's avatar
christianrhansen committed
554
        if (obj.isFirst) {
555
          this.activeHandler = true
christianrhansen's avatar
christianrhansen committed
556
          this.mobileTempCell.show = true
557
          // this.mobileTempCell.button = false
558
          this.cellHandler.move.pushed = true
christianrhansen's avatar
christianrhansen committed
559
        }
560

christianrhansen's avatar
christianrhansen committed
561 562 563
        this.mobileTempCell.x = res.x
        this.mobileTempCell.y = res.y

564 565 566
        this.mobileTempCell.ox = res.ox
        this.mobileTempCell.oy = res.oy

567 568
        this.cellHandler.move.x = res.ox
        this.cellHandler.move.y = res.oy
569

christianrhansen's avatar
christianrhansen committed
570
        if (obj.isFinal) {
571
          this.activeHandler = false
christianrhansen's avatar
christianrhansen committed
572
          this.mobileTempCell.onGrid = true
573
          // this.mobileTempCell.button = true
574
          this.mobileTempCell.left = this.gridDimensions.full.cell.width * (res.x - 1)
575 576 577 578
          this.cellHandler.move.pushed = false
          // this.cellHandler.move.y = this.gridDimensions.full.cell.height * (res.y - 1) + 8 + 59 + 20
          this.cellHandler.move.x = this.gridDimensions.full.cell.width * (this.mobileTempCell.x - 1) + 8 + 20
          this.cellHandler.move.y = this.gridDimensions.full.cell.height * (this.mobileTempCell.y - 1) + 8 + 20
579

580 581
          this.cellHandler.resize.x = this.gridDimensions.full.cell.width * (res.x + this.mobileTempCell.width - 1) - 8 - 20
          this.cellHandler.resize.y = this.gridDimensions.full.cell.height * (res.y + this.mobileTempCell.height - 1) - 8 - 20
christianrhansen's avatar
christianrhansen committed
582 583
        }
      },
christianrhansen's avatar
christianrhansen committed
584
      handleResizeCell (obj) {
christianrhansen's avatar
christianrhansen committed
585
        // this.cursor = {x: obj.position.left, y: obj.position.top}
586 587 588
        // this.cellHandler.resize = {x: obj.position.left, y: obj.position.top}
        this.cellHandler.resize.x = obj.position.left
        this.cellHandler.resize.y = obj.position.top
589

590 591 592
        // ---> panGrid
        let res = this.getGridPositionForEvent(obj)

593 594 595
        this.cellHandler.resize.gridPosition.row = res.y
        this.cellHandler.resize.gridPosition.column = res.x

596
        if (obj.isFirst) {
597
          this.activeHandler = true
598
          this.mobileTempCell.show = true
599
          // this.mobileTempCell.button = false
600
          this.cellHandler.resize.pushed = true
601 602 603 604 605
        }

        this.mobileTempCell.width = res.x - this.mobileTempCell.x + 1
        this.mobileTempCell.height = res.y - this.mobileTempCell.y + 1

606 607
        this.cellHandler.resize.x = res.ox
        this.cellHandler.resize.y = res.oy
608

609
        if (obj.isFinal) {
610
          this.activeHandler = false
611
          this.mobileTempCell.onGrid = true
612
          // this.mobileTempCell.button = true
613
          this.cellHandler.resize.pushed = false
614 615
          // this.addMobileCell(obj)
          // this.mobileTempCell.show = false
616 617
          this.cellHandler.resize.x = this.gridDimensions.full.cell.width * res.x - 8 - 20
          this.cellHandler.resize.y = this.gridDimensions.full.cell.height * res.y - 8 - 20
618 619
        }
      },
620 621
      handleCellEdit (event, annotation) {
        console.log('handleCellEdit', annotation)
622 623 624
        this.touchMobileCell(event, annotation)
        this.handleModal()
      },
625 626 627 628
      getCarouselIcon (val) {
        console.log(val)
      },
      carouselVisibility () {
629 630 631 632
        console.log(this.carousel.slide)
        if (this.$refs.carousel) {
          this.$refs.carousel.goToSlide(this.carousel.slide)
        }
633 634
        this.carousel.visibility = !this.carousel.visibility
      },
635 636 637
      handleModal () {
        this.modal = !this.modal
      },
638
      panGrid (obj) {
639
        if (this.cachedNewCell && !this.mobileTempCell.onGrid) {
640
          // console.log('hhhhhhhhhhhhhhhhh', obj)
641 642 643 644
          let res = this.getGridPositionForEvent(obj)

          if (obj.isFirst) {
            this.mobileTempCell.show = true
645
            // this.mobileTempCell.button = false
646 647 648 649 650 651 652 653
            this.mobileTempCell.x = res.x
            this.mobileTempCell.y = res.y
          }

          this.mobileTempCell.width = res.x - this.mobileTempCell.x + 1
          this.mobileTempCell.height = res.y - this.mobileTempCell.y + 1

          if (obj.isFinal) {
654
            this.mobileTempCell.onGrid = true
655
            // this.mobileTempCell.button = true
656 657
            // this.addMobileCell(obj)
            // this.mobileTempCell.show = false
658 659
            this.cellHandler.move.x = this.gridDimensions.full.cell.width * (this.mobileTempCell.x - 1) + 8 + 20
            this.cellHandler.move.y = this.gridDimensions.full.cell.height * (this.mobileTempCell.y - 1) + 8 + 20
660

661 662
            this.cellHandler.resize.x = this.gridDimensions.full.cell.width * res.x - 8 - 20
            this.cellHandler.resize.y = this.gridDimensions.full.cell.height * res.y - 8 - 20
663
          }
664
        }
665
      },
666
      async cellHold (event, annotation) {
667 668
        this.$store.commit('mosys/setEditingCells', '')

669
        this.$q.notify({
670
          message: 'Copied.',
671
          color: 'dark',
672 673
          textColor: 'white',
          position: 'bottom-right'
674 675 676 677 678 679 680 681 682 683
        })

        const _cell = await this.$store.dispatch('cells/get', annotation.body.source.id)
        const resourceCell = {
          data: { content: '' },
          config: {},
          component: _cell.component
        }
        this.$store.commit('mosys/cacheNewCell', resourceCell)
      },
christianrhansen's avatar
christianrhansen committed
684 685
      moveCachedCell (obj) {
        this.touch.position = {top: obj.position.top, left: obj.position.left}
686 687 688 689 690 691 692 693 694
        /*
        if (obj.isFinal) {
          console.log(obj.isFinal)
          console.log(window.event)
          console.log(this.touch.position)
          console.log('--->->->', this.getGridPositionForEvent(event))
        }
        */
        // console.log('--->>>', this.getGridPositionForEvent(event))
christianrhansen's avatar
christianrhansen committed
695
      },
696
      addMobileCell (event) {
christianrhansen's avatar
christianrhansen committed
697
        if (this.cachedNewCell) {
698
          this.handleGridDrop(event)
christianrhansen's avatar
christianrhansen committed
699
          this.$store.commit('mosys/cacheNewCell', undefined)
700 701
          this.$q.notify({
            message: 'Cell was added.',
702 703 704
            color: 'dark',
            position: 'center',
            timeout: 50
705
          })
christianrhansen's avatar
christianrhansen committed
706 707
        }
      },
708
      touchMobileCell (event, cell) {
709
        if (!this.mobileTempCell.onGrid && cell) {
710 711 712 713 714 715 716 717 718
          Object.keys(this.annotationUIStates).filter((k) => {
            if (k === cell._uuid && this.annotationUIStates[k].editing) console.log(k, cell._uuid)
            else this.annotationUIStates[k].editing = false
          })
          this.annotationUIStates[cell._uuid].editing = !this.annotationUIStates[cell._uuid].editing
          this.updateEditingCells()
          this.$root.$emit('mosys_saveScrollPosition')
          // this.handleCellEditClick(event, annotation)
        }
719
      },
christianrhansen's avatar
christianrhansen committed
720
      handleCellTouch (event, annotation) {
721
        console.log('handleCellTouch', annotation)
722
        if (!this.cachedNewCell) {
723 724 725 726 727 728 729 730 731 732 733 734 735 736
          let
            parsed = annotation.target.selector.parse(),
            sliced = parsed.xywh.slice(0, 4),
            x = sliced[0],
            y = sliced[1],
            w = sliced[2],
            h = sliced[3]

          this.cellHandler.move.x = this.gridDimensions.full.cell.width * (x - 1) + 8 + 20
          this.cellHandler.move.y = this.gridDimensions.full.cell.height * (y - 1) + 8 + 20

          this.cellHandler.resize.x = this.gridDimensions.full.cell.width * (x + w - 1) - 8 - 20
          this.cellHandler.resize.y = this.gridDimensions.full.cell.height * (y + h - 1) - 8 - 20

737
          this.mobileSelectedCell = annotation
738
          this.getCellType(annotation)
739
        }
christianrhansen's avatar
christianrhansen committed
740
      },
741 742 743 744 745
      async getCellType (annotation) {
        let cell = await this.$store.dispatch('cells/get', annotation.body.source.id)
        let cellType = cell.component
        this.selectedCell.type = cellType.substr(4, cellType.length - 4)
      },
746 747 748
      // async mobileCellMove (annotation, _x, _y) {
      async mobileCellMove (annotation, x, y) {
        // this.$el.scrollLeft = this.$el.scrollLeft + (this.gridDimensions.full.cell.width * _x)
749

750
        let
751 752
          parsed = annotation.target.selector.parse()
          /*
753
          sliced = parsed.xywh.slice(0, 4),
754
          x = sliced[0],
755 756 757
          y = sliced[1],
          w = sliced[2],
          h = sliced[3]
758
          */
759

760
        /*
761 762 763 764 765 766 767
        // ----- x
        if (_x === -1) if (x > 1) x += _x
        if (_x === 1 && x < this.grid.config.columns - w + 1) x += _x

        // ----- y
        if (_y === -1) if (y > 1) y += _y
        if (_y === 1 && y < this.grid.config.rows - h + 1) y += _y
768
        */
769 770 771 772

        // x += _x
        // y += _y

773 774 775 776 777 778 779 780
        let target = this.grid.get2DArea([x, y], parsed.xywh.slice(2))
        annotation.target.selector.value = target.selector.value
        await this.$store.dispatch('annotations/patch', [annotation.id, {
          target: {
            selector: { value: target.selector.value }
          }
        }])
      },
781
      async mobileCellResize (annotation, _w, _h) {
782 783 784
        let
          parsed = annotation.target.selector.parse(),
          [x, y, w, h] = parsed.xywh
785 786
        console.log('mobileCellResize', w, h)
        /*
787 788 789 790 791 792 793
        // ----- w
        if (_w === -1) if (w > 1) w += _w
        if (_w === 1 && x < this.grid.config.columns - w + 1) w += _w

        // ----- h
        if (_h === -1) if (h > 1) h += _h
        if (_h === 1 && y < this.grid.config.rows - h + 1) h += _h
794
        */
795 796 797 798

        // w += _w
        // h += _h

799
        const value = { xywh: [x, y, _w, _h] }
800 801 802 803 804 805 806
        annotation.target.selector.value = value

        await this.$store.dispatch('annotations/patch', [annotation.id, { target: { selector: { value } } }])
      },
      setEditMode (mode) {
        this.$store.commit('mosys/setEditMode', mode)
      },
807 808 809 810
      //
      // DATA
      //

Anton's avatar
Intial  
Anton committed
811 812 813
      async fetchData () {
        if (this.gridUuid) {
          this.grid = await this.$store.dispatch('maps/get', this.gridUuid)
814 815 816 817 818 819 820 821
          if (!Object.keys(this.grid.config).length) {
            this.grid.config = {
              columns: 10,
              rows: 6,
              ratio: 16 / 9.0
            }
            await this.updateGridMetadataStore()
          }
Anton's avatar
Intial  
Anton committed
822
          this.updateGridDimensions()
823 824 825 826 827 828
          const { items } = await this.$store.dispatch('annotations/find', {
            'target.id': this.grid.id,
            'body.purpose': 'linking',
            'body.type': 'Cell'
          })
          this.annotations = items
Anton's avatar
Intial  
Anton committed
829 830
        }
      },
831 832 833
      async updateGridMetadataStore () {
        await this.$store.dispatch('maps/patch', [this.grid.id, { config: this.grid.config }])
        this.updateGridDimensions()
Anton's avatar
Intial  
Anton committed
834
      },
835 836 837 838 839
      updateSelectedCells () {
        const _this = this
        let selectedCells = Object.keys(this.annotationUIStates).filter(k => {
          return _this.annotationUIStates[k].selected
        }).map(k => {
Christian Hansen's avatar
Christian Hansen committed
840 841
          // return _this.cells.find(c => c._uuid === k)
          return _this.annotations.find(c => c._uuid === k)
842 843
        })
        this.$store.commit('mosys/setSelectedCells', selectedCells)
Anton's avatar
Intial  
Anton committed
844
      },
Mathias Bär's avatar
Mathias Bär committed
845 846 847 848 849 850 851 852
      updateEditingCells () {
        const _this = this
        let editingCells = Object.keys(this.annotationUIStates).filter(k => {
          return _this.annotationUIStates[k].editing
        }).map(k => {
          // return _this.cells.find(c => c._uuid === k)
          return _this.annotations.find(c => c._uuid === k)
        })
853 854 855 856 857 858 859
        /*
        console.log('this.annotationUIStates: ', this.annotationUIStates)
        console.log('editingCells: ', editingCells)
        if (this.isMobile) {
          console.log('MOBILE')
        }
        */
Mathias Bär's avatar
Mathias Bär committed
860 861
        this.$store.commit('mosys/setEditingCells', editingCells)
      },
862 863 864 865 866
      updateAnnotationUIStates () {
        let newAnnotationUIStates = {}
        this.annotations.forEach(a => {
          newAnnotationUIStates[a._uuid] = {
            selected: false,
Mathias Bär's avatar
Mathias Bär committed
867
            editing: false,
868
            beingResized: false,
Mathias Bär's avatar
Mathias Bär committed
869
            beginDragged: false,
870
            annotation: a
Anton's avatar
Intial  
Anton committed
871
          }
872 873
        })
        this.annotationUIStates = newAnnotationUIStates
Anton's avatar
Intial  
Anton committed
874
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
875
        this.updateEditingCells()
876
      },
877 878 879 880 881

      //
      // GRID DRAG & DROP HANDLERS
      //

882
      async handleGridDragOver (event) {
Anton's avatar
Intial  
Anton committed
883 884 885
        let _this = this
        if (this.resizingGrid) {
          const position = this.getGridPositionForEvent(event)
886 887
          this.grid.config.ratio = position.ox / (position.oy * 1.0)
          await this.updateGridMetadataStore()
Anton's avatar
Intial  
Anton committed
888 889
        }
        else {
890 891
          let annotation = this.annotations.filter(annotation => {
            if (!_this.annotationUIStates[annotation._uuid]) return false
Mathias Bär's avatar
Mathias Bär committed
892
            return _this.annotationUIStates[annotation._uuid].beingDragged ||
893
              _this.annotationUIStates[annotation._uuid].beingResized
Anton's avatar
Intial  
Anton committed
894 895
          }).shift()
          let offset, position
896 897 898 899
          if (!annotation) {
            annotation = {
              target: this.grid.get2DArea([1, 1], [1, 1])
            }
Anton's avatar
Intial  
Anton committed
900 901 902
            position = this.getGridPositionForEvent(event)
          }
          else {
903
            offset = this.annotationUIStates[annotation._uuid].draggingOffset
Anton's avatar
Intial  
Anton committed
904 905
            position = this.getGridPositionForEvent(event, offset)
          }
906 907
          if (!this.tmpObjects.length) this.tmpObjects.push(annotation)
          const parsed = annotation.target.selector.parse()
Anton's avatar
Intial  
Anton committed
908
          if (event.dataTransfer.types.includes('text/plain')) {
909 910
            parsed.xywh[0] = position.x
            parsed.xywh[1] = position.y
Anton's avatar
Intial  
Anton committed
911 912 913
            event.preventDefault()
          }
          else {
914 915
            parsed.xywh[2] = Math.max(1, 1 + position.x - parsed.xywh[0])
            parsed.xywh[3] = Math.max(1, 1 + position.y - parsed.xywh[1])
Anton's avatar
Intial  
Anton committed
916
          }
917
          annotation.target.selector.value = parsed
Anton's avatar
Intial  
Anton committed
918 919 920
        }
      },
      handleGridDragEnd () {
921
        this.tmpObjects = []
Anton's avatar
Intial  
Anton committed
922
      },
923
      async handleGridDrop (event) {
924 925 926 927 928
        let dropData
        if (event.dataTransfer) dropData = event.dataTransfer.getData('text/plain')
        if (!dropData) dropData = JSON.stringify(this.cachedNewCell)
        // console.log('handleGridDrop - event', event)
        // console.log('handleGridDrop - dropData', dropData)
929 930
        if (dropData) {
          dropData = JSON.parse(dropData)
931
          let annotation = this.annotations.find(a => a.id === dropData.id)
932 933 934 935 936
          const { x, y } = this.getGridPositionForEvent(
            event,
            annotation ? this.annotationUIStates[annotation._uuid].draggingOffset : undefined
          )
          if (annotation) {
937 938 939
            const
              parsed = annotation.target.selector.parse(),
              target = this.grid.get2DArea([x, y], parsed.xywh.slice(2))
940 941 942 943 944 945
            annotation.target.selector.value = target.selector.value
            await this.$store.dispatch('annotations/patch', [annotation.id, {
              target: {
                selector: { value: target.selector.value }
              }
            }])
Anton's avatar
Intial  
Anton committed
946 947
          }
          else {
948 949
            if (this.mobileTempCell.x) console.log('this.mobileTempCell', this.mobileTempCell)
            let test = this.grid.get2DArea([this.mobileTempCell.x, this.mobileTempCell.y], [this.mobileTempCell.width, this.mobileTempCell.height])
950 951 952 953 954 955 956 957 958 959 960
            const
              { data, config, component } = dropData,
              cell = await this.$store.dispatch('cells/post', { data, config, component })
            annotation = await this.$store.dispatch('annotations/post', {
              body: {
                type: 'Cell',
                purpose: 'linking',
                source: {
                  id: cell.id
                }
              },
961 962
              // target: this.grid.get2DArea([x, y], [1, 1])
              target: test
963
            })
964
            this.annotations.push(annotation)
Anton's avatar
Anton committed
965
            this.updateAnnotationUIStates()
Anton's avatar
Intial  
Anton committed
966
          }
967

968
          this.tmpObjects = []
Anton's avatar
Intial  
Anton committed
969 970
          event.preventDefault()
        }
971
        this.clearHandler('temp cell')
Anton's avatar
Intial  
Anton committed
972
      },
973 974 975 976

      //
      // CELL DRAG & DROP HANDLERS
      //
Mathias Bär's avatar
Mathias Bär committed
977 978 979
      handleCellEditClick (event, cell) {
        this.annotationUIStates[cell._uuid].editing = !this.annotationUIStates[cell._uuid].editing
        this.updateEditingCells()
980
        this.$root.$emit('mosys_saveScrollPosition')
Mathias Bär's avatar
Mathias Bär committed
981
      },
982
      /*
983 984 985 986
      handleCellClick (event, cell) {
        this.annotationUIStates[cell._uuid].selected = !this.annotationUIStates[cell._uuid].selected
        this.updateSelectedCells()
      },
987
      */
988
      handleCellDragStart (event, annotation) {
christianrhansen's avatar
christianrhansen committed
989
        console.log('§§§§§§§§', annotation)
990 991 992 993 994 995 996 997 998 999 1000 1001
        if (!this.isMobile) {
          if (!this.annotationUIStates[annotation._uuid].beingResized) {
            event.dataTransfer.setData('text/plain', JSON.stringify(annotation))
            event.dataTransfer.setDragImage(nullImage, 0, 0)
            let elContainerBoundingBox = this.$el.getBoundingClientRect()
            let elBoundingBox = event.target.getBoundingClientRect()
            let offset = {
              x: (event.clientX - elContainerBoundingBox.x) - (elBoundingBox.x - elContainerBoundingBox.x),
              y: (event.clientY - elContainerBoundingBox.y) - (elBoundingBox.y - elContainerBoundingBox.y)
            }
            this.annotationUIStates[annotation._uuid].draggingOffset = offset
            this.annotationUIStates[annotation._uuid].beingDragged = true
1002
          }
1003
          this.tmpObjects.push(annotation)
1004 1005 1006
        }
      },
      handleCellDragEnd (event, annotation) {
1007 1008 1009
        if (!this.mobile) {
          this.annotationUIStates[annotation._uuid].beingDragged = false
        }
1010 1011 1012 1013
      },
      async handleCellContextMenuDelete (event, annotation) {
        this.annotationUIStates[annotation._uuid].selected = false
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
1014
        this.updateEditingCells()
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
        await this.$store.dispatch('cells/delete', annotation.body.source.id)
        await this.$store.dispatch('annotations/delete', annotation.id)
        this.annotations = this.annotations