GridEditor.vue 51.8 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

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

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

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

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

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

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

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

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

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

      template(v-if="!resizingGrid")

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

          //----- cell
70
          // v-touch-hold="event => {cellCopy(event, annotation)}",
Anton's avatar
Intial  
Anton committed
71
          .cell-item(
72 73 74 75 76 77 78 79 80 81
          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}`")

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

98
            //----- selecting cells disabled because it has no use currently
99 100 101 102 103 104 105 106
            // 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
107
            //----- resize-handler (desktop only)
108
            .desktop-only.cell-item-resize-handle(
109 110 111 112
            draggable="true",
            @dragstart="event => {handleCellResizerDragStart(event, annotation)}",
            @dragend="event => {handleCellResizerDragEnd(event, annotation)}",
            @dragexit="event => {handleCellResizerDragEnd(event, annotation)}")
113
              q-icon.q-ma-xs(name="network cell")
114

115 116 117
            //----- context menu for cells (desktop only)
            // TODO: needs revision
            q-context-menu.desktop-only
118 119 120 121 122 123 124
              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
125

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

christianrhansen's avatar
christianrhansen committed
131
        //-------------------------------------------------------------------------------------- temporary cell (mobile)
132
        template(v-if="mobileTempCell.show && cachedNewCell")
133

134 135 136
          .cell-item.cell-item-tmp-mobile.row.justify-center.items-center(
          ref="_mobileTempCell",
          :style="mobileTempCellStyle(mobileTempCell)")
137

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

140 141 142 143 144
            //
              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")
145

146 147 148 149 150 151 152 153 154 155 156 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
        //------------------------------------------------------------------------------------------------- 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;")
184

christianrhansen's avatar
christianrhansen committed
185
      // ---------------------------------------------------------------------------------------------------------------
Anton's avatar
Intial  
Anton committed
186
      template(v-else)
187
        .cell-item(:style="getAnnotationStyle({x:0,y:0,width:1,height:1})", key="cell-grid-resizer")
Anton's avatar
Intial  
Anton committed
188
          div.cell-item-resize-handle(
189 190 191 192 193
          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
194

Mathias Bär's avatar
Mathias Bär committed
195
      //template(v-if="!isMobile")
196 197 198 199 200
        .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
201
      //template(v-if="isMobile")
Mathias Bär's avatar
Mathias Bär committed
202 203 204 205 206
        .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
207

208
    // ------------------------------------------------------------------------------------------ edit box (mobile only)
209

210
    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
211
    v-if="isMobile",
212
    :class="[{'show-full' : carousel.visibility && showEditingCells}, {'show-minimized' : showEditingCells}]",
213
    style="border-radius: .5rem;",
214
    position="bottom-right")
christianrhansen's avatar
christianrhansen committed
215

216
      //------------------------- buttons
217 218
      // .row.text-dark(style="background-color: rgba(0, 0, 0, .2);")
      .row.text-dark(style="background-color: rgba(255, 150, 150, .3);")
219 220 221

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

226 227
        //----- toggle edit-box
        .col.text-right
christianrhansen's avatar
christianrhansen committed
228
          q-btn.q-py-none.q-pr-sm.q-mr-xs(@click="carouselVisibility()", flat, no-ripple)
christianrhansen's avatar
christianrhansen committed
229 230
            q-icon(v-if="carousel.visibility", name="keyboard_arrow_down")
            q-icon(v-else, name="keyboard_arrow_up")
231

christianrhansen's avatar
christianrhansen committed
232
      //q-item-separator.q-ma-none
233 234 235 236 237 238

      //------------------------- 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
239 240
        // q-carousel-slide.q-py-sm
        q-carousel-slide.q-py-none
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
          .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
256 257
        // q-carousel-slide.q-py-sm
        q-carousel-slide.q-py-none
258 259 260 261 262 263 264 265 266 267 268 269 270
          .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
271 272 273 274
</template>

<script>
  import Cell from './Cell'
275 276
  import { userHasFeature } from 'mbjs-quasar/src/lib'
  import { mapGetters } from 'vuex'
277
  import GridEditorEditingCellsMobile from './/GridEditorEditingCellsMobile'
278
  import CellHandlerMobile from './CellHandlerMobile'
Anton's avatar
Intial  
Anton committed
279 280 281 282 283 284

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

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

495
        // -------------------- move
496
        if (obj.element === 'move') {
christianrhansen's avatar
christianrhansen committed
497
          this.tempHandler.move.intersectingMainHandler = obj.intersecting
498

christianrhansen's avatar
christianrhansen committed
499
          // behind left side
christianrhansen's avatar
christianrhansen committed
500
          if (_offsetLeft < 0) {
501
            this.tempHandler.move.side = 'left'
502
          }
503
          // intersecting
christianrhansen's avatar
christianrhansen committed
504
          else if (isNaN(_offsetLeft)) {
christianrhansen's avatar
christianrhansen committed
505
            if (this.tempHandler.move.intersectingMainHandler && this.tempHandler.move.side === 'right') this.tempHandler.resize.intersectingMainHandler = false
506
          }
christianrhansen's avatar
christianrhansen committed
507
          // behind right side
christianrhansen's avatar
christianrhansen committed
508
          else if (_offsetLeft === 1) {
509
            this.tempHandler.move.side = 'right'
christianrhansen's avatar
christianrhansen committed
510
            this.tempHandler.resize.intersectingMainHandler = true
511
          }
512
        }
513

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

christianrhansen's avatar
christianrhansen committed
518
          // on left side
christianrhansen's avatar
christianrhansen committed
519
          if (_offsetLeft === -1) {
520
            this.tempHandler.resize.side = 'left'
521
          }
christianrhansen's avatar
christianrhansen committed
522
          /*
523
          // intersecting
christianrhansen's avatar
christianrhansen committed
524
          else if (isNaN(Math.sign(obj.offsetLeft))) {
525
          }
christianrhansen's avatar
christianrhansen committed
526
          */
christianrhansen's avatar
christianrhansen committed
527
          // on right side
christianrhansen's avatar
christianrhansen committed
528
          else if (_offsetLeft === 1) {
529
            this.tempHandler.resize.side = 'right'
530
          }
531 532
        }
      },
christianrhansen's avatar
christianrhansen committed
533
      handleMoveCell (obj) {
534 535
        this.cellHandler.move.x = obj.position.left
        this.cellHandler.move.y = obj.position.top
536

christianrhansen's avatar
christianrhansen committed
537 538
        let res = this.getGridPositionForEvent(obj)

539 540 541
        this.cellHandler.move.gridPosition.row = res.y
        this.cellHandler.move.gridPosition.column = res.x

christianrhansen's avatar
christianrhansen committed
542
        if (obj.isFirst) {
543
          this.activeHandler = true
christianrhansen's avatar
christianrhansen committed
544
          this.mobileTempCell.show = true
545
          // this.mobileTempCell.button = false
546
          this.cellHandler.move.pushed = true
christianrhansen's avatar
christianrhansen committed
547
        }
548

christianrhansen's avatar
christianrhansen committed
549 550 551
        this.mobileTempCell.x = res.x
        this.mobileTempCell.y = res.y

552 553 554
        this.mobileTempCell.ox = res.ox
        this.mobileTempCell.oy = res.oy

555 556
        this.cellHandler.move.x = res.ox
        this.cellHandler.move.y = res.oy
557

christianrhansen's avatar
christianrhansen committed
558
        if (obj.isFinal) {
559
          this.activeHandler = false
christianrhansen's avatar
christianrhansen committed
560
          this.mobileTempCell.onGrid = true
561
          // this.mobileTempCell.button = true
562
          this.mobileTempCell.left = this.gridDimensions.full.cell.width * (res.x - 1)
563 564 565 566
          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
567

568 569
          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
570 571
        }
      },
christianrhansen's avatar
christianrhansen committed
572
      handleResizeCell (obj) {
christianrhansen's avatar
christianrhansen committed
573
        // this.cursor = {x: obj.position.left, y: obj.position.top}
574 575 576
        // 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
577

578 579 580
        // ---> panGrid
        let res = this.getGridPositionForEvent(obj)

581 582 583
        this.cellHandler.resize.gridPosition.row = res.y
        this.cellHandler.resize.gridPosition.column = res.x

584
        if (obj.isFirst) {
585
          this.activeHandler = true
586
          this.mobileTempCell.show = true
587
          // this.mobileTempCell.button = false
588
          this.cellHandler.resize.pushed = true
589 590 591 592 593
        }

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

594 595
        this.cellHandler.resize.x = res.ox
        this.cellHandler.resize.y = res.oy
596

597
        if (obj.isFinal) {
598
          this.activeHandler = false
599
          this.mobileTempCell.onGrid = true
600
          // this.mobileTempCell.button = true
601
          this.cellHandler.resize.pushed = false
602 603
          // this.addMobileCell(obj)
          // this.mobileTempCell.show = false
604 605
          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
606 607
        }
      },
608 609
      handleCellEdit (event, annotation) {
        console.log('handleCellEdit', annotation)
610 611 612
        this.touchMobileCell(event, annotation)
        this.handleModal()
      },
613 614 615 616
      getCarouselIcon (val) {
        console.log(val)
      },
      carouselVisibility () {
617 618 619 620
        console.log(this.carousel.slide)
        if (this.$refs.carousel) {
          this.$refs.carousel.goToSlide(this.carousel.slide)
        }
621 622
        this.carousel.visibility = !this.carousel.visibility
      },
623 624 625
      handleModal () {
        this.modal = !this.modal
      },
626
      panGrid (obj) {
627
        if (this.cachedNewCell && !this.mobileTempCell.onGrid) {
628
          // console.log('hhhhhhhhhhhhhhhhh', obj)
629 630 631 632
          let res = this.getGridPositionForEvent(obj)

          if (obj.isFirst) {
            this.mobileTempCell.show = true
633
            // this.mobileTempCell.button = false
634 635 636 637 638 639 640 641
            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) {
642
            this.mobileTempCell.onGrid = true
643
            // this.mobileTempCell.button = true
644 645
            // this.addMobileCell(obj)
            // this.mobileTempCell.show = false
646 647
            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
648

649 650
            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
651
          }
652
        }
653
      },
654
      async cellCopy (event, annotation) {
655 656
        this.$store.commit('mosys/setEditingCells', '')

657
        this.$q.notify({
658
          message: 'Copied.',
659
          color: 'dark',
660 661
          textColor: 'white',
          position: 'bottom-right'
662 663 664 665 666 667 668 669 670 671
        })

        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
672 673
      moveCachedCell (obj) {
        this.touch.position = {top: obj.position.top, left: obj.position.left}
674 675 676 677 678 679 680 681 682
        /*
        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
683
      },
684
      addMobileCell (event) {
christianrhansen's avatar
christianrhansen committed
685
        if (this.cachedNewCell) {
686
          this.handleGridDrop(event)
christianrhansen's avatar
christianrhansen committed
687
          this.$store.commit('mosys/cacheNewCell', undefined)
688 689
          this.$q.notify({
            message: 'Cell was added.',
690 691 692
            color: 'dark',
            position: 'center',
            timeout: 50
693
          })
christianrhansen's avatar
christianrhansen committed
694 695
        }
      },
696
      touchMobileCell (event, cell) {
697
        if (!this.mobileTempCell.onGrid && cell) {
698 699 700 701 702 703 704 705 706
          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)
        }
707
      },
christianrhansen's avatar
christianrhansen committed
708
      handleCellTouch (event, annotation) {
709
        console.log('handleCellTouch', annotation)
710
        if (!this.cachedNewCell) {
711 712 713 714 715 716 717 718 719 720 721 722 723 724
          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

725
          this.mobileSelectedCell = annotation
726
          this.getCellType(annotation)
727
        }
christianrhansen's avatar
christianrhansen committed
728
      },
729 730 731 732 733
      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)
      },
734 735 736
      // async mobileCellMove (annotation, _x, _y) {
      async mobileCellMove (annotation, x, y) {
        // this.$el.scrollLeft = this.$el.scrollLeft + (this.gridDimensions.full.cell.width * _x)
737

738
        let
739 740
          parsed = annotation.target.selector.parse()
          /*
741
          sliced = parsed.xywh.slice(0, 4),
742
          x = sliced[0],
743 744 745
          y = sliced[1],
          w = sliced[2],
          h = sliced[3]
746
          */
747

748
        /*
749 750 751 752 753 754 755
        // ----- 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
756
        */
757 758 759 760

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

761 762 763 764 765 766 767 768
        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 }
          }
        }])
      },
769
      async mobileCellResize (annotation, _w, _h) {
770 771 772
        let
          parsed = annotation.target.selector.parse(),
          [x, y, w, h] = parsed.xywh
773 774
        console.log('mobileCellResize', w, h)
        /*
775 776 777 778 779 780 781
        // ----- 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
782
        */
783 784 785 786

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

787
        const value = { xywh: [x, y, _w, _h] }
788 789 790 791 792 793 794
        annotation.target.selector.value = value

        await this.$store.dispatch('annotations/patch', [annotation.id, { target: { selector: { value } } }])
      },
      setEditMode (mode) {
        this.$store.commit('mosys/setEditMode', mode)
      },
795 796 797 798
      //
      // DATA
      //

Anton's avatar
Intial  
Anton committed
799 800 801
      async fetchData () {
        if (this.gridUuid) {
          this.grid = await this.$store.dispatch('maps/get', this.gridUuid)
802 803 804 805 806 807 808 809
          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
810
          this.updateGridDimensions()
811 812 813 814 815 816
          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
817 818
        }
      },
819 820 821
      async updateGridMetadataStore () {
        await this.$store.dispatch('maps/patch', [this.grid.id, { config: this.grid.config }])
        this.updateGridDimensions()
Anton's avatar
Intial  
Anton committed
822
      },
823 824 825 826 827
      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
828 829
          // return _this.cells.find(c => c._uuid === k)
          return _this.annotations.find(c => c._uuid === k)
830 831
        })
        this.$store.commit('mosys/setSelectedCells', selectedCells)
Anton's avatar
Intial  
Anton committed
832
      },
Mathias Bär's avatar
Mathias Bär committed
833 834 835 836 837 838 839 840
      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)
        })
841 842 843 844 845 846 847
        /*
        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
848 849
        this.$store.commit('mosys/setEditingCells', editingCells)
      },
850 851 852 853 854
      updateAnnotationUIStates () {
        let newAnnotationUIStates = {}
        this.annotations.forEach(a => {
          newAnnotationUIStates[a._uuid] = {
            selected: false,
Mathias Bär's avatar
Mathias Bär committed
855
            editing: false,
856
            beingResized: false,
Mathias Bär's avatar
Mathias Bär committed
857
            beginDragged: false,
858
            annotation: a
Anton's avatar
Intial  
Anton committed
859
          }
860 861
        })
        this.annotationUIStates = newAnnotationUIStates
Anton's avatar
Intial  
Anton committed
862
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
863
        this.updateEditingCells()
864
      },
865 866 867 868 869

      //
      // GRID DRAG & DROP HANDLERS
      //

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

956
          this.tmpObjects = []
Anton's avatar
Intial  
Anton committed
957 958
          event.preventDefault()
        }
959
        this.clearHandler('temp cell')
Anton's avatar
Intial  
Anton committed
960
      },
961 962 963 964

      //
      // CELL DRAG & DROP HANDLERS
      //
Mathias Bär's avatar
Mathias Bär committed
965 966 967
      handleCellEditClick (event, cell) {
        this.annotationUIStates[cell._uuid].editing = !this.annotationUIStates[cell._uuid].editing
        this.updateEditingCells()
968
        this.$root.$emit('mosys_saveScrollPosition')
Mathias Bär's avatar
Mathias Bär committed
969
      },
970
      /*
971 972 973 974
      handleCellClick (event, cell) {
        this.annotationUIStates[cell._uuid].selected = !this.annotationUIStates[cell._uuid].selected
        this.updateSelectedCells()
      },
975
      */
976
      handleCellDragStart (event, annotation) {
christianrhansen's avatar
christianrhansen committed
977
        console.log('§§§§§§§§', annotation)
978 979 980 981 982 983 984 985 986 987 988 989
        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
990
          }
991
          this.tmpObjects.push(annotation)
992 993 994
        }
      },
      handleCellDragEnd (event, annotation) {
995 996 997
        if (!this.mobile) {
          this.annotationUIStates[annotation._uuid].beingDragged = false
        }
998 999 1000 1001
      },
      async handleCellContextMenuDelete (event, annotation) {
        this.annotationUIStates[annotation._uuid].selected = false
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
1002
        this.updateEditingCells()
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 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
        await this.$store.dispatch('cells/delete', annotation.body.source.id)
        await this.$store.dispatch('annotations/delete', annotation.id)
        this.annotations = this.annotations.filter(a => a.id !== annotation.id)
      },

      //
      // GRID RESIZE HANDLERS

      handleGridResizerDragStart (event) {
        event.dataTransfer.setDragImage(nullImage, 0, 0)
      },
      async handleGridResizerDragEnd () {
        await this.updateGridMetadataStore()
      },

      //
      // CELL RESIZE HANDLERS
      //

      handleCellResizerDragStart (event, annotation) {
        event.dataTransfer.setDragImage(nullImage, 0, 0)
        this.annotationUIStates[annotation._uuid].beingResized = true
        this.tmpObjects.push(annotation)
      },
      async handleCellResizerDragEnd (event, annotation) {
        let position = this.getGridPositionForEvent(event)
        let
          parsed = annotation.target.selector.parse(),
          [x, y, w, h] = parsed.xywh
        w = Math.max(1, 1 + position.x - x)
        h = Math.max(1, 1 + position.y - y)
        const value = { xywh: [x, y, w, h] }
        annotation.target.selector.value = value
        this.annotationUIStates[annotation._uuid].beingResized = false
        this.tmpObjects = []
        await this.$store.dispatch('annotations/patch', [annotation.id, { target: { selector: { value } } }])
      },

      //
      // CELL CONTEXT MENU
      //

      handleCellContextMenu (event) {
Anton's avatar
Intial  
Anton committed
1046 1047
        this.contextMenuClickPosition = this.getGridPositionForEvent(event)
      },
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061