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

3
  // :class="{'overflow-hidden': mobileTempCell.show && cachedNewCell && !mobileTempCell.button}",
4
  div.cell-grid-container(
5
  :class="{'overflow-hidden': activeHandler}",
6
  style="overflow-y: hidden; scroll-behavior: smooth;")
7
    q-modal(v-model="modal", minimized, content-css="background-color: #eee; border-radius: .75rem;")
8
      grid-editor-editing-cells-mobile
9 10 11
      //
        q-btn.absolute-top-right.q-ma-sm.bg-dark(@click="handleModal()", round, size="sm", flat)
          q-icon(name="clear")
12

13
    q-window-resize-observable(@resize="updateGridDimensions")
Anton's avatar
Intial  
Anton committed
14

christianrhansen's avatar
christianrhansen committed
15
    // ------------------------------------------------------------------------------------------------- new cell header
16 17
    #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
18
        q-item-main
19
          strong New {{ newCellType }}
20

21
        q-item-side
22 23 24 25 26
          q-btn.text-white(
          @click="event => {addMobileCell(event)}", round, flat,
          style="background-color: rgba(0, 0, 0, 0);")
            q-icon(name="check")

27 28
          q-btn.text-white.q-px-md.q-mr-md.on-right(@click="clearHandler('cached cell')", flat,
            style="border-radius: .5rem; width: 42px; border: 1px solid rgba(255, 255, 255, .3);")
christianrhansen's avatar
christianrhansen committed
29
            q-icon(name="clear")
30

31 32
    // -------------------------------------------------------------------------------------------- selected cell header
    #selected-cell-header.fixed-top.z-top.bg-dark.text-white.transition(:class="{'show': showEditingCells}")
33
      q-item.q-pl-md.q-pr-none.q-py-none.full-height(v-if="!modal")
34
        q-item-main
35
          strong {{ selectedCell.type }}
36

37
        q-item-side
38
          q-btn.text-white.q-px-sm(@click="event => {handleCellEdit(event, selectedCell.annotation)}", flat)
39 40
            q-icon(name="edit")

41
          q-btn.text-white.q-px-sm.on-right.on-left(@click="event => {handleCellContextMenuDelete(event, mobileSelectedCell)}",
42
          flat)
43
            q-icon(name="delete")
44

45
          q-btn.text-white.q-px-md.q-mr-md.on-right(@click="clearHandler('cell')", flat,
46 47 48
          style="border-radius: .5rem; width: 42px; border: 1px solid rgba(255, 255, 255, .3);")
            q-icon(name="clear")

49
    // ------------------------------------------------------------------------------------------------------------ grid
50
      @click="event => {addMobileCell(event)}",
51
    div.cell-grid.relative-position(
52
    v-touch-pan="panGrid",
53 54 55 56 57 58
    @dragenter="handleGridDragOver",
    @dragover="handleGridDragOver",
    @dragleave="handleGridDragEnd",
    @drop="handleGridDrop",
    @contextmenu="handleGridContextMenu",
    :style="gridStyle")
Anton's avatar
Intial  
Anton committed
59

60 61
      // context menu grid (desktop only)
      q-context-menu.desktop-only(ref="gridmenu")
Anton's avatar
Intial  
Anton committed
62 63
        q-list(link, separator, no-border, style="min-width: 150px; max-height: 300px;")
          q-item(
64 65 66 67 68
          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
69 70 71

      template(v-if="!resizingGrid")

72
        template(v-for="(annotation, index) in annotations")
christianrhansen's avatar
christianrhansen committed
73 74

          //----- cell
75
          // v-touch-hold="event => {cellHold(event, annotation)}",
Anton's avatar
Intial  
Anton committed
76
          .cell-item(
77 78 79 80 81 82 83 84 85 86
          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}`")

87
            //--------------------------------------------------------------------------------------- edit-/close-button
88
            // TODO: find a more elegant solution
89
            //-------------------------------------------------------------------------------------------------- desktop
90
            .desktop-only
Mathias Bär's avatar
Mathias Bär committed
91
              q-btn.edit-button.absolute-top-right(
92 93 94 95 96
              @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"
              )
97
            //--------------------------------------------------------------------------------------------------- mobile
98
            .mobile-only
99
              .edit-button.absolute.fit.bg-transparent(
100
              v-touch-hold="event => {handleCellEdit(event, annotation)}",
101
              @click.prevent="event => {touchMobileCell(event, annotation)}")
102

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

110 111 112
              //----- invisible edit-modal handler
              //
                q-btn.absolute-top-left.bg-blue(
113
                @click.prevent="event => {handleCellEdit(event, annotation)}", flat, style="opacity: 0") bla
114
                // @click.prevent="handleModal()", flat, style="opacity: 0") bla
115

116
            //----- selecting cells disabled because it has no use currently
117 118 119 120 121 122 123 124
            // 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
125
            //----- resize-handler (desktop only)
126
            .desktop-only.cell-item-resize-handle(
127 128 129 130
            draggable="true",
            @dragstart="event => {handleCellResizerDragStart(event, annotation)}",
            @dragend="event => {handleCellResizerDragEnd(event, annotation)}",
            @dragexit="event => {handleCellResizerDragEnd(event, annotation)}")
131
              q-icon.q-ma-xs(name="network cell")
132

133 134 135
            //----- context menu for cells (desktop only)
            // TODO: needs revision
            q-context-menu.desktop-only
136 137 138 139 140 141 142
              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
143

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

christianrhansen's avatar
christianrhansen committed
149
        //-------------------------------------------------------------------------------------- temporary cell (mobile)
150
        template(v-if="mobileTempCell.show && cachedNewCell")
151

152 153 154
          .cell-item.cell-item-tmp-mobile.row.justify-center.items-center(
          ref="_mobileTempCell",
          :style="mobileTempCellStyle(mobileTempCell)")
155

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

158 159 160 161 162
            //
              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")
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 196 197 198 199 200 201
        //------------------------------------------------------------------------------------------------- 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;")
202

christianrhansen's avatar
christianrhansen committed
203
      // ---------------------------------------------------------------------------------------------------------------
Anton's avatar
Intial  
Anton committed
204
      template(v-else)
205
        .cell-item(:style="getAnnotationStyle({x:0,y:0,width:1,height:1})", key="cell-grid-resizer")
Anton's avatar
Intial  
Anton committed
206
          div.cell-item-resize-handle(
207 208 209 210 211
          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
212

Mathias Bär's avatar
Mathias Bär committed
213
      //template(v-if="!isMobile")
214 215 216 217 218
        .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
219
      //template(v-if="isMobile")
Mathias Bär's avatar
Mathias Bär committed
220 221 222 223 224
        .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
225

226
    // ------------------------------------------------------------------------------------------ edit box (mobile only)
227

228
    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
229
    v-if="isMobile",
230
    :class="[{'show-full' : carousel.visibility && showEditingCells}, {'show-minimized' : showEditingCells}]",
231
    style="border-radius: .5rem;",
232
    position="bottom-right")
christianrhansen's avatar
christianrhansen committed
233

234
      //------------------------- buttons
235 236
      // .row.text-dark(style="background-color: rgba(0, 0, 0, .2);")
      .row.text-dark(style="background-color: rgba(255, 150, 150, .3);")
237 238 239

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

244 245
        //----- toggle edit-box
        .col.text-right
christianrhansen's avatar
christianrhansen committed
246
          q-btn.q-py-none.q-pr-sm.q-mr-xs(@click="carouselVisibility()", flat, no-ripple)
christianrhansen's avatar
christianrhansen committed
247 248
            q-icon(v-if="carousel.visibility", name="keyboard_arrow_down")
            q-icon(v-else, name="keyboard_arrow_up")
249

christianrhansen's avatar
christianrhansen committed
250
      //q-item-separator.q-ma-none
251 252 253 254 255 256

      //------------------------- 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
257 258
        // q-carousel-slide.q-py-sm
        q-carousel-slide.q-py-none
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
          .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
274 275
        // q-carousel-slide.q-py-sm
        q-carousel-slide.q-py-none
276 277 278 279 280 281 282 283 284 285 286 287 288
          .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
289 290 291 292
</template>

<script>
  import Cell from './Cell'
293 294
  import { userHasFeature } from 'mbjs-quasar/src/lib'
  import { mapGetters } from 'vuex'
295
  import GridEditorEditingCellsMobile from './/GridEditorEditingCellsMobile'
296
  import CellHandlerMobile from './CellHandlerMobile'
Anton's avatar
Intial  
Anton committed
297 298 299 300 301 302

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

  export default {
    components: {
303
      Cell,
304 305
      GridEditorEditingCellsMobile,
      CellHandlerMobile
Anton's avatar
Intial  
Anton committed
306
    },
307
    props: ['gridUuid', 'tabsAreOpen'],
Anton's avatar
Intial  
Anton committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
    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,
333
        annotations: undefined,
334
        tmpObjects: [],
335
        annotationUIStates: {},
Anton's avatar
Anton committed
336
        gridDimensions: { gridWidth: 0, gridHeight: 0, cellWidth: 0, cellHeight: 0 },
Anton's avatar
Intial  
Anton committed
337
        contextMenuClickPosition: {},
338
        resizingGrid: false,
christianrhansen's avatar
christianrhansen committed
339
        mobileSelectedCell: undefined,
340
        touch: {position: {top: undefined, left: undefined}},
341
        isMobile: this.$q.platform.is.mobile,
342 343 344 345 346 347 348 349 350 351 352 353
        mobileTempCell: {
          x: 0,
          y: 0,
          ox: 0,
          oy: 0,
          width: 1,
          height: 1,
          left: 0,
          show: false,
          onGrid: false,
          button: false
        },
354
        slide: undefined,
355
        modal: false,
356
        carousel: {visibility: false, icon: 'open_with', slide: 0},
christianrhansen's avatar
christianrhansen committed
357
        // cursor: {x: undefined, y: undefined},
358
        cellHandler: {
359
          size: {width: 40, height: 40},
360
          move: {x: 20, y: undefined, gridPosition: {row: undefined, column: undefined}, pushed: false, pos: undefined, inViewport: undefined, onLeft: undefined, onRight: undefined, dataLeft: undefined},
361
          resize: {x: undefined, y: undefined, gridPosition: {row: undefined, column: undefined}, pushed: false, pos: undefined}
362
        },
363
        tempHandler: {
christianrhansen's avatar
christianrhansen committed
364 365
          move: {left: undefined, intersectingMainHandler: false, side: undefined},
          resize: {left: undefined, intersectingMainHandler: false, side: undefined}
366
        },
367
        activeHandler: false,
368
        selectedCell: {type: undefined, annotation: undefined}
Anton's avatar
Intial  
Anton committed
369 370
      }
    },
371 372
    computed: {
      ...mapGetters({
christianrhansen's avatar
christianrhansen committed
373
        cachedNewCell: 'mosys/getNewCell',
374
        user: 'auth/getUserState',
375
        // isMobile: 'globalSettings/getIsMobile',
Mathias Bär's avatar
Mathias Bär committed
376
        // editingCells: 'mosys/getEditingCells'
377
        showEditingCells: 'mosys/getShowEditingCells',
378 379
        scrollPositionCache: 'mosys/getScrollPositionCache',
        editMode: 'mosys/getEditMode'
380
      }),
381 382 383 384 385 386
      newCellType () {
        if (this.cachedNewCell) {
          let type = this.cachedNewCell.component
          return type.substr(4, type.length - 4)
        }
      },
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
      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
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
      },
      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>")`
        }
425 426
      }
    },
Anton's avatar
Intial  
Anton committed
427 428
    async mounted () {
      await this.fetchData()
429
      this.resetScrollPosition()
430 431 432
    },
    beforeDestroy () {
      this.observer.disconnect()
Anton's avatar
Intial  
Anton committed
433 434
    },
    watch: {
435
      'cellHandler.move.gridPosition': {
436 437 438 439
        handler: function (obj) {
          if (this.showEditingCells) {
            this.mobileCellMove(this.mobileSelectedCell, obj.column, obj.row)
          }
440 441 442
        },
        deep: true
      },
443 444 445
      'cellHandler.resize.gridPosition': {
        handler: function (obj) {
          if (this.showEditingCells) {
446 447 448
            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)
449 450 451 452
          }
        },
        deep: true
      },
453 454 455 456 457 458 459 460 461 462
      slide (val) {
        let icon
        switch (val) {
        case 0:
          icon = 'open_with'
          break
        case 1:
          icon = 'photo_size_select_small'
          break
        case 2:
463
          icon = 'more_horiz'
464 465 466 467 468
          break
        default:
          icon = 'open_with'
          break
        }
469 470 471
        // this.carousel.slide = val
        // this.carousel.icon = icon
        this.carousel = {slide: val, icon: icon, visibility: this.carousel.visibility}
472
      },
Anton's avatar
Anton committed
473
      annotations () {
474
        this.updateAnnotationUIStates()
Anton's avatar
Intial  
Anton committed
475 476 477 478 479 480
      },
      gridMetadata () {
        this.updateGridDimensions()
      },
      async gridUuid () {
        await this.fetchData()
Mathias Bär's avatar
Mathias Bär committed
481 482
      },
      showEditingCells (val) {
483
        // console.log('show editing cells', val)
Mathias Bär's avatar
Mathias Bär committed
484 485 486
        if (val === false) {
          this.updateAnnotationUIStates()
        }
487 488 489
      },
      tabsAreOpen () {
        this.resetScrollPosition()
Anton's avatar
Intial  
Anton committed
490 491 492
      }
    },
    methods: {
493 494 495 496 497 498 499 500
      clearHandler (target) {
        switch (target) {
        case 'cell':
          Object.keys(this.annotationUIStates).filter((k) => {
            this.annotationUIStates[k].editing = false
          })
          this.$store.commit('mosys/setEditingCells', '')
          break
501 502
        case 'cached cell':
          this.$store.commit('mosys/cacheNewCell', undefined)
503 504 505 506
          this.clearHandler('temp cell')
          break
        case 'temp cell':
          this.mobileTempCell = {x: undefined, y: undefined, width: undefined, height: undefined, onGrid: false, button: false}
507
          break
508 509
        }
      },
510
      intersectionChanged (obj) {
christianrhansen's avatar
christianrhansen committed
511 512
        let _offsetLeft = Math.sign(obj.offsetLeft)

513
        // -------------------- move
514
        if (obj.element === 'move') {
christianrhansen's avatar
christianrhansen committed
515
          this.tempHandler.move.intersectingMainHandler = obj.intersecting
516

christianrhansen's avatar
christianrhansen committed
517
          // behind left side
christianrhansen's avatar
christianrhansen committed
518
          if (_offsetLeft < 0) {
519
            this.tempHandler.move.side = 'left'
520
          }
521
          // intersecting
christianrhansen's avatar
christianrhansen committed
522
          else if (isNaN(_offsetLeft)) {
christianrhansen's avatar
christianrhansen committed
523
            if (this.tempHandler.move.intersectingMainHandler && this.tempHandler.move.side === 'right') this.tempHandler.resize.intersectingMainHandler = false
524
          }
christianrhansen's avatar
christianrhansen committed
525
          // behind right side
christianrhansen's avatar
christianrhansen committed
526
          else if (_offsetLeft === 1) {
527
            this.tempHandler.move.side = 'right'
christianrhansen's avatar
christianrhansen committed
528
            this.tempHandler.resize.intersectingMainHandler = true
529
          }
530
        }
531

532
        // -------------------- resize
christianrhansen's avatar
christianrhansen committed
533
        else if (obj.element === 'resize') {
christianrhansen's avatar
christianrhansen committed
534
          this.tempHandler.resize.intersectingMainHandler = obj.intersecting
535

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

christianrhansen's avatar
christianrhansen committed
555 556
        let res = this.getGridPositionForEvent(obj)

557 558 559
        this.cellHandler.move.gridPosition.row = res.y
        this.cellHandler.move.gridPosition.column = res.x

christianrhansen's avatar
christianrhansen committed
560
        if (obj.isFirst) {
561
          this.activeHandler = true
christianrhansen's avatar
christianrhansen committed
562
          this.mobileTempCell.show = true
563
          // this.mobileTempCell.button = false
564
          this.cellHandler.move.pushed = true
christianrhansen's avatar
christianrhansen committed
565
        }
566

christianrhansen's avatar
christianrhansen committed
567 568 569
        this.mobileTempCell.x = res.x
        this.mobileTempCell.y = res.y

570 571 572
        this.mobileTempCell.ox = res.ox
        this.mobileTempCell.oy = res.oy

573 574
        this.cellHandler.move.x = res.ox
        this.cellHandler.move.y = res.oy
575

christianrhansen's avatar
christianrhansen committed
576
        if (obj.isFinal) {
577
          this.activeHandler = false
christianrhansen's avatar
christianrhansen committed
578
          this.mobileTempCell.onGrid = true
579
          // this.mobileTempCell.button = true
580
          this.mobileTempCell.left = this.gridDimensions.full.cell.width * (res.x - 1)
581 582 583 584
          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
585

586 587
          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
588 589
        }
      },
christianrhansen's avatar
christianrhansen committed
590
      handleResizeCell (obj) {
christianrhansen's avatar
christianrhansen committed
591
        // this.cursor = {x: obj.position.left, y: obj.position.top}
592 593 594
        // 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
595

596 597 598
        // ---> panGrid
        let res = this.getGridPositionForEvent(obj)

599 600 601
        this.cellHandler.resize.gridPosition.row = res.y
        this.cellHandler.resize.gridPosition.column = res.x

602
        if (obj.isFirst) {
603
          this.activeHandler = true
604
          this.mobileTempCell.show = true
605
          // this.mobileTempCell.button = false
606
          this.cellHandler.resize.pushed = true
607 608 609 610 611
        }

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

612 613
        this.cellHandler.resize.x = res.ox
        this.cellHandler.resize.y = res.oy
614

615
        if (obj.isFinal) {
616
          this.activeHandler = false
617
          this.mobileTempCell.onGrid = true
618
          // this.mobileTempCell.button = true
619
          this.cellHandler.resize.pushed = false
620 621
          // this.addMobileCell(obj)
          // this.mobileTempCell.show = false
622 623
          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
624 625
        }
      },
626 627
      handleCellEdit (event, annotation) {
        console.log('handleCellEdit', annotation)
628 629 630
        this.touchMobileCell(event, annotation)
        this.handleModal()
      },
631 632 633 634
      getCarouselIcon (val) {
        console.log(val)
      },
      carouselVisibility () {
635 636 637 638
        console.log(this.carousel.slide)
        if (this.$refs.carousel) {
          this.$refs.carousel.goToSlide(this.carousel.slide)
        }
639 640
        this.carousel.visibility = !this.carousel.visibility
      },
641 642 643
      handleModal () {
        this.modal = !this.modal
      },
644
      panGrid (obj) {
645
        if (this.cachedNewCell && !this.mobileTempCell.onGrid) {
646
          // console.log('hhhhhhhhhhhhhhhhh', obj)
647 648 649 650
          let res = this.getGridPositionForEvent(obj)

          if (obj.isFirst) {
            this.mobileTempCell.show = true
651
            // this.mobileTempCell.button = false
652 653 654 655 656 657 658 659
            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) {
660
            this.mobileTempCell.onGrid = true
661
            // this.mobileTempCell.button = true
662 663
            // this.addMobileCell(obj)
            // this.mobileTempCell.show = false
664 665
            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
666

667 668
            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
669
          }
670
        }
671
      },
672
      async cellHold (event, annotation) {
673 674
        this.$store.commit('mosys/setEditingCells', '')

675
        this.$q.notify({
676
          message: 'Copied.',
677
          color: 'dark',
678 679
          textColor: 'white',
          position: 'bottom-right'
680 681 682 683 684 685 686 687 688 689
        })

        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
690 691
      moveCachedCell (obj) {
        this.touch.position = {top: obj.position.top, left: obj.position.left}
692 693 694 695 696 697 698 699 700
        /*
        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
701
      },
702
      addMobileCell (event) {
christianrhansen's avatar
christianrhansen committed
703
        if (this.cachedNewCell) {
704
          this.handleGridDrop(event)
christianrhansen's avatar
christianrhansen committed
705
          this.$store.commit('mosys/cacheNewCell', undefined)
706 707
          this.$q.notify({
            message: 'Cell was added.',
708 709 710
            color: 'dark',
            position: 'center',
            timeout: 50
711
          })
christianrhansen's avatar
christianrhansen committed
712 713
        }
      },
714
      touchMobileCell (event, cell) {
715
        if (!this.mobileTempCell.onGrid && cell) {
716 717 718 719 720 721 722 723 724
          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)
        }
725
      },
christianrhansen's avatar
christianrhansen committed
726
      handleCellTouch (event, annotation) {
727
        console.log('handleCellTouch', annotation)
728
        if (!this.cachedNewCell) {
729 730 731 732 733 734 735 736 737 738 739 740 741 742
          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

743
          this.mobileSelectedCell = annotation
744
          this.getCellType(annotation)
745
        }
christianrhansen's avatar
christianrhansen committed
746
      },
747 748 749 750 751
      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)
      },
752 753 754
      // async mobileCellMove (annotation, _x, _y) {
      async mobileCellMove (annotation, x, y) {
        // this.$el.scrollLeft = this.$el.scrollLeft + (this.gridDimensions.full.cell.width * _x)
755

756
        let
757 758
          parsed = annotation.target.selector.parse()
          /*
759
          sliced = parsed.xywh.slice(0, 4),
760
          x = sliced[0],
761 762 763
          y = sliced[1],
          w = sliced[2],
          h = sliced[3]
764
          */
765

766
        /*
767 768 769 770 771 772 773
        // ----- 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
774
        */
775 776 777 778

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

779 780 781 782 783 784 785 786
        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 }
          }
        }])
      },
787
      async mobileCellResize (annotation, _w, _h) {
788 789 790
        let
          parsed = annotation.target.selector.parse(),
          [x, y, w, h] = parsed.xywh
791 792
        console.log('mobileCellResize', w, h)
        /*
793 794 795 796 797 798 799
        // ----- 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
800
        */
801 802 803 804

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

805
        const value = { xywh: [x, y, _w, _h] }
806 807 808 809 810 811 812
        annotation.target.selector.value = value

        await this.$store.dispatch('annotations/patch', [annotation.id, { target: { selector: { value } } }])
      },
      setEditMode (mode) {
        this.$store.commit('mosys/setEditMode', mode)
      },
813 814 815 816
      //
      // DATA
      //

Anton's avatar
Intial  
Anton committed
817 818 819
      async fetchData () {
        if (this.gridUuid) {
          this.grid = await this.$store.dispatch('maps/get', this.gridUuid)
820 821 822 823 824 825 826 827
          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
828
          this.updateGridDimensions()
829 830 831 832 833 834
          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
835 836
        }
      },
837 838 839
      async updateGridMetadataStore () {
        await this.$store.dispatch('maps/patch', [this.grid.id, { config: this.grid.config }])
        this.updateGridDimensions()
Anton's avatar
Intial  
Anton committed
840
      },
841 842 843 844 845
      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
846 847
          // return _this.cells.find(c => c._uuid === k)
          return _this.annotations.find(c => c._uuid === k)
848 849
        })
        this.$store.commit('mosys/setSelectedCells', selectedCells)
Anton's avatar
Intial  
Anton committed
850
      },
Mathias Bär's avatar
Mathias Bär committed
851 852 853 854 855 856 857 858
      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)
        })
859 860 861 862 863 864 865
        /*
        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
866 867
        this.$store.commit('mosys/setEditingCells', editingCells)
      },
868 869 870 871 872
      updateAnnotationUIStates () {
        let newAnnotationUIStates = {}
        this.annotations.forEach(a => {
          newAnnotationUIStates[a._uuid] = {
            selected: false,
Mathias Bär's avatar
Mathias Bär committed
873
            editing: false,
874
            beingResized: false,
Mathias Bär's avatar
Mathias Bär committed
875
            beginDragged: false,
876
            annotation: a
Anton's avatar
Intial  
Anton committed
877
          }
878 879
        })
        this.annotationUIStates = newAnnotationUIStates
Anton's avatar
Intial  
Anton committed
880
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
881
        this.updateEditingCells()
882
      },
883 884 885 886 887

      //
      // GRID DRAG & DROP HANDLERS
      //

888
      async handleGridDragOver (event) {
Anton's avatar
Intial  
Anton committed
889 890 891
        let _this = this
        if (this.resizingGrid) {
          const position = this.getGridPositionForEvent(event)
892 893
          this.grid.config.ratio = position.ox / (position.oy * 1.0)
          await this.updateGridMetadataStore()
Anton's avatar
Intial  
Anton committed
894 895
        }
        else {
896 897
          let annotation = this.annotations.filter(annotation => {
            if (!_this.annotationUIStates[annotation._uuid]) return false
Mathias Bär's avatar
Mathias Bär committed
898
            return _this.annotationUIStates[annotation._uuid].beingDragged ||
899
              _this.annotationUIStates[annotation._uuid].beingResized
Anton's avatar
Intial  
Anton committed
900 901
          }).shift()
          let offset, position
902 903 904 905
          if (!annotation) {
            annotation = {
              target: this.grid.get2DArea([1, 1], [1, 1])
            }
Anton's avatar
Intial  
Anton committed
906 907 908
            position = this.getGridPositionForEvent(event)
          }
          else {
909
            offset = this.annotationUIStates[annotation._uuid].draggingOffset
Anton's avatar
Intial  
Anton committed
910 911
            position = this.getGridPositionForEvent(event, offset)
          }
912 913
          if (!this.tmpObjects.length) this.tmpObjects.push(annotation)
          const parsed = annotation.target.selector.parse()
Anton's avatar
Intial  
Anton committed
914
          if (event.dataTransfer.types.includes('text/plain')) {
915 916
            parsed.xywh[0] = position.x
            parsed.xywh[1] = position.y
Anton's avatar
Intial  
Anton committed
917 918 919
            event.preventDefault()
          }
          else {
920 921
            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
922
          }
923
          annotation.target.selector.value = parsed
Anton's avatar
Intial  
Anton committed
924 925 926
        }
      },
      handleGridDragEnd () {
927
        this.tmpObjects = []
Anton's avatar
Intial  
Anton committed
928
      },
929
      async handleGridDrop (event) {
930 931 932 933 934
        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)
935 936
        if (dropData) {
          dropData = JSON.parse(dropData)
937
          let annotation = this.annotations.find(a => a.id === dropData.id)
938 939 940 941 942
          const { x, y } = this.getGridPositionForEvent(
            event,
            annotation ? this.annotationUIStates[annotation._uuid].draggingOffset : undefined
          )
          if (annotation) {
943 944 945
            const
              parsed = annotation.target.selector.parse(),
              target = this.grid.get2DArea([x, y], parsed.xywh.slice(2))
946 947 948 949 950 951
            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
952 953
          }
          else {
954 955
            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])
956 957 958 959 960 961 962 963 964 965 966
            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
                }
              },
967 968
              // target: this.grid.get2DArea([x, y], [1, 1])
              target: test
969
            })
970
            this.annotations.push(annotation)
Anton's avatar
Anton committed
971
            this.updateAnnotationUIStates()
Anton's avatar
Intial  
Anton committed
972
          }
973

974
          this.tmpObjects = []
Anton's avatar
Intial  
Anton committed
975 976
          event.preventDefault()
        }
977
        this.clearHandler('temp cell')
Anton's avatar
Intial  
Anton committed
978
      },
979 980 981 982

      //
      // CELL DRAG & DROP HANDLERS
      //
Mathias Bär's avatar
Mathias Bär committed
983 984 985
      handleCellEditClick (event, cell) {
        this.annotationUIStates[cell._uuid].editing = !this.annotationUIStates[cell._uuid].editing
        this.updateEditingCells()
986
        this.$root.$emit('mosys_saveScrollPosition')
Mathias Bär's avatar
Mathias Bär committed
987
      },
988
      /*
989 990 991 992
      handleCellClick (event, cell) {
        this.annotationUIStates[cell._uuid].selected = !this.annotationUIStates[cell._uuid].selected
        this.updateSelectedCells()
      },
993
      */
994
      handleCellDragStart (event, annotation) {
christianrhansen's avatar
christianrhansen committed
995
        console.log('§§§§§§§§', annotation)
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
        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
1008
          }
1009
          this.tmpObjects.push(annotation)
1010 1011 1012
        }
      },
      handleCellDragEnd (event, annotation) {
1013 1014 1015
        if (!this.mobile) {
          this.annotationUIStates[annotation._uuid].beingDragged = false
        }
1016 1017 1018 1019
      },
      async handleCellContextMenuDelete (event, annotation) {
        this.annotationUIStates[annotation._uuid].selected = false
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
1020
        this.updateEditingCells()
1021 1022 1023 1024 1025 1026 1027 1028 1029