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

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

12 13 14 15 16 17
    // this needs to stay for adding cells on mobile for whatever reason (strangest bug ever...)
    // FIXME: find the problem and fix it
    .mobile-only.fixed-top-left.q-caption.z-max.hidden
      .bg-red {{ cachedNewCell }}
      .bg-green {{ mobileTempCell }}

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

christianrhansen's avatar
christianrhansen committed
20
    // ------------------------------------------------------------------------------------------------- new cell header
21 22
    #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
23
        q-item-main
24
          strong New {{ newCellType }}
25

26
        q-item-side
27 28 29 30 31
          q-btn.text-white(
          @click="event => {addMobileCell(event)}", round, flat,
          style="background-color: rgba(0, 0, 0, 0);")
            q-icon(name="check")

32 33
          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
34
            q-icon(name="clear")
35

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

42
        q-item-side
43
          q-btn.text-white.q-px-sm(@click="event => {handleCellInfoTouch(event, selectedCell.annotation)}", flat)
44 45
            q-icon(name="edit")

46
          q-btn.text-white.q-px-sm.on-right.on-left(@click="event => {handleCellContextMenuDelete(event, mobileSelectedCell)}",
47
          flat)
48
            q-icon(name="delete")
49

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

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

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

      template(v-if="!resizingGrid")

77
        template(v-for="(annotation, index) in annotations")
christianrhansen's avatar
christianrhansen committed
78 79

          //----- cell
80
          // v-touch-hold="event => {cellHold(event, annotation)}",
Anton's avatar
Intial  
Anton committed
81
          .cell-item(
82 83 84 85 86 87 88 89 90 91
          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}`")

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

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

115 116 117 118 119
              //----- invisible edit-modal handler
              //
                q-btn.absolute-top-left.bg-blue(
                @click.prevent="event => {handleCellInfoTouch(event, annotation)}", flat, style="opacity: 0") bla
                // @click.prevent="handleModal()", flat, style="opacity: 0") bla
120

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

138 139 140
            //----- context menu for cells (desktop only)
            // TODO: needs revision
            q-context-menu.desktop-only
141 142 143 144 145 146 147
              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
148

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

christianrhansen's avatar
christianrhansen committed
154
        //-------------------------------------------------------------------------------------- temporary cell (mobile)
155
        template(v-if="mobileTempCell.show && cachedNewCell")
156

157 158 159
          .cell-item.cell-item-tmp-mobile.row.justify-center.items-center(
          ref="_mobileTempCell",
          :style="mobileTempCellStyle(mobileTempCell)")
160

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

163 164 165 166 167
            //
              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")
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 202 203 204 205 206
        //------------------------------------------------------------------------------------------------- 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;")
207

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

Mathias Bär's avatar
Mathias Bär committed
218
      //template(v-if="!isMobile")
219 220 221 222 223
        .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
224
      //template(v-if="isMobile")
Mathias Bär's avatar
Mathias Bär committed
225 226 227 228 229
        .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
230

231
    // ------------------------------------------------------------------------------------------ edit box (mobile only)
232

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

239
      //------------------------- buttons
240 241
      // .row.text-dark(style="background-color: rgba(0, 0, 0, .2);")
      .row.text-dark(style="background-color: rgba(255, 150, 150, .3);")
242 243 244

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

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

christianrhansen's avatar
christianrhansen committed
255
      //q-item-separator.q-ma-none
256 257 258 259 260 261

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

<script>
  import Cell from './Cell'
298 299
  import { userHasFeature } from 'mbjs-quasar/src/lib'
  import { mapGetters } from 'vuex'
300
  import GridEditorEditingCellsMobile from './/GridEditorEditingCellsMobile'
301
  import CellHandlerMobile from './CellHandlerMobile'
Anton's avatar
Intial  
Anton committed
302 303 304 305 306 307

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

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

516
        // -------------------- move
517
        if (obj.element === 'move') {
christianrhansen's avatar
christianrhansen committed
518
          this.tempHandler.move.intersectingMainHandler = obj.intersecting
519

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

535
        // -------------------- resize
christianrhansen's avatar
christianrhansen committed
536
        else if (obj.element === 'resize') {
christianrhansen's avatar
christianrhansen committed
537
          this.tempHandler.resize.intersectingMainHandler = obj.intersecting
538

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

christianrhansen's avatar
christianrhansen committed
558 559
        let res = this.getGridPositionForEvent(obj)

560 561 562
        this.cellHandler.move.gridPosition.row = res.y
        this.cellHandler.move.gridPosition.column = res.x

christianrhansen's avatar
christianrhansen committed
563 564 565
        if (obj.isFirst) {
          this.mobileTempCell.show = true
          this.mobileTempCell.button = false
566
          this.cellHandler.move.pushed = true
christianrhansen's avatar
christianrhansen committed
567
        }
568

christianrhansen's avatar
christianrhansen committed
569 570 571
        this.mobileTempCell.x = res.x
        this.mobileTempCell.y = res.y

572 573 574
        this.mobileTempCell.ox = res.ox
        this.mobileTempCell.oy = res.oy

575 576
        this.cellHandler.move.x = res.ox
        this.cellHandler.move.y = res.oy
577

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      //
      // GRID DRAG & DROP HANDLERS
      //

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

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

      //
      // CELL DRAG & DROP HANDLERS
      //
Mathias Bär's avatar
Mathias Bär committed
982 983 984
      handleCellEditClick (event, cell) {
        this.annotationUIStates[cell._uuid].editing = !this.annotationUIStates[cell._uuid].editing
        this.updateEditingCells()
985
        this.$root.$emit('mosys_saveScrollPosition')
Mathias Bär's avatar
Mathias Bär committed
986
      },
987 988 989 990 991
      handleCellClick (event, cell) {
        this.annotationUIStates[cell._uuid].selected = !this.annotationUIStates[cell._uuid].selected
        this.updateSelectedCells()
      },
      handleCellDragStart (event, annotation) {
christianrhansen's avatar
christianrhansen committed
992
        console.log('§§§§§§§§', annotation)
993 994 995 996 997 998 999 1000 1001 1002 1003 1004
        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
1005
          }
1006
          this.tmpObjects.push(annotation)
1007 1008 1009
        }
      },
      handleCellDragEnd (event, annotation) {
1010 1011 1012
        if (!this.mobile) {
          this.annotationUIStates[annotation._uuid].beingDragged = false
        }
1013 1014 1015 1016
      },
      async handleCellContextMenuDelete (event, annotation) {
        this.annotationUIStates[annotation._uuid].selected = false
        this.updateSelectedCells()
Mathias Bär's avatar
Mathias Bär committed
1017
        this.updateEditingCells()
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
        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
1061 1062
        this.contextMenuClickPosition = this.getGridPositionForEvent(event)
      },
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
      async handleCellContextMenuEditCSS (event, annotation) {
        try {
          let styleClass = await this.$q.dialog({
            title: this.$t('forms.edit_css_class.title'),
            ok: this.$t('buttons.set_css_class'),
            cancel: this.$t('buttons.cancel'),
            prompt: {
              model: annotation.styleClass,
              type: 'text'
            }
          })
          if (styleClass) {
            if (!styleClass.length) styleClass = undefined
            else if (styleClass.indexOf('.') === 0) styleClass = styleClass.substr(1)
          }
          annotation.styleClass = styleClass
          this.$store.dispatch('annotations/patch', [annotation._uuid, { target: { styleClass: styleClass || null } }])
Anton's avatar
Intial  
Anton committed
1080
        }
1081 1082 1083 1084 1085 1086 1087 1088 1089
        catch (e) { /* dialog canceled */ }
      },

      //
      // GRID CONTEXT MENU
      //

      handleGridContextMenu (event) {
        this.contextMenuClickPosition = this.getGridPositionForEvent(event)
Anton's avatar
Intial  
Anton committed
1090 1091