pull/35/head
			
			
		
		
							parent
							
								
									7aca9ded60
								
							
						
					
					
						commit
						9ca3b93847
					
				@ -1,193 +0,0 @@ | 
				
			||||
<template> | 
				
			||||
  <div> | 
				
			||||
    <input type="hidden" :name="name" :value="JSON.stringify(columns)"> | 
				
			||||
    <table class="editor-table"> | 
				
			||||
      <thead> | 
				
			||||
        <tr> | 
				
			||||
          <th></th> | 
				
			||||
          <th>Name</th> | 
				
			||||
          <th>Type</th> | 
				
			||||
          <th>Title</th> | 
				
			||||
          <th></th> | 
				
			||||
        </tr> | 
				
			||||
      </thead> | 
				
			||||
      <transition-group name="col-list" tag="tbody" ref="col-list"> | 
				
			||||
        <tr v-for="(col, i) in columns" :key="col.id" :ref="'col' + i" :class="{dragging: col._dragging}"> | 
				
			||||
          <td class="btn-group"> | 
				
			||||
            <button class="btn btn-outline-secondary drag-btn" @mousedown="beginDrag(i, $event)"> | 
				
			||||
              <v-icon class="fa-bars" alt="Drag" /> | 
				
			||||
            </button> | 
				
			||||
            <a href="" :class="['btn', 'btn-outline-secondary', {disabled: i==0}]" @click.prevent="move(i, -1)"> | 
				
			||||
              <v-icon class="fa-chevron-up" alt="Move Up" /> | 
				
			||||
            </a><a href="" :class="['btn', 'btn-outline-secondary', {disabled: i == (columns.length-1)}]" @click.prevent="move(i, 1)"> | 
				
			||||
              <v-icon class="fa-chevron-down" alt="Move Down" /> | 
				
			||||
            </a> | 
				
			||||
          </td> | 
				
			||||
 | 
				
			||||
          <td> | 
				
			||||
            <input v-model="col.name" class="form-control" type="text" style="width: 140px"> | 
				
			||||
          </td> | 
				
			||||
 | 
				
			||||
          <td> | 
				
			||||
            <select v-model="col.type" class="form-control custom-select" style="width: 110px"> | 
				
			||||
              <option v-for="t in colTypes" :value="t">{{t}}</option> | 
				
			||||
            </select> | 
				
			||||
          </td> | 
				
			||||
 | 
				
			||||
          <td> | 
				
			||||
            <input v-model="col.title" class="form-control" type="text" style="width: 170px"> | 
				
			||||
          </td> | 
				
			||||
 | 
				
			||||
          <td class="text-nowrap"> | 
				
			||||
            <a href="" :class="['mr-1', 'btn', 'btn-outline-secondary', 'delete-btn', {disabled: i==0}]" @click.prevent="delCol(i)"> | 
				
			||||
              <v-icon class="fa-trash-o" alt="Delete column" /> | 
				
			||||
            </a><!-- | 
				
			||||
            --><a href="" class="btn btn-outline-secondary" v-if="i === columns.length - 1" | 
				
			||||
                  @click.prevent="addCol()"> | 
				
			||||
              <v-icon class="fa-plus" alt="Add Column" /> | 
				
			||||
            </a> | 
				
			||||
          </td> | 
				
			||||
        </tr> | 
				
			||||
      </transition-group> | 
				
			||||
    </table> | 
				
			||||
  </div> | 
				
			||||
</template> | 
				
			||||
 | 
				
			||||
<style lang="scss" scoped> | 
				
			||||
  @import "base"; | 
				
			||||
 | 
				
			||||
  table { | 
				
			||||
    border-collapse: collapse; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  td, th { | 
				
			||||
    @include pr(1); | 
				
			||||
    @include py(1); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  tr.dragging { | 
				
			||||
    position: relative; | 
				
			||||
    z-index: 1; | 
				
			||||
    background-color: $body-bg; | 
				
			||||
  } | 
				
			||||
  tr.dragging .drag-btn { | 
				
			||||
    // fake hover | 
				
			||||
    background-color: $secondary; | 
				
			||||
    color: color-yiq($secondary); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  .col-list-enter-active { | 
				
			||||
    transition: all .3s cubic-bezier(.2, .3, 0, 1); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  .col-list-enter { | 
				
			||||
    opacity: 0; | 
				
			||||
    transform: translateY(100%); | 
				
			||||
  } | 
				
			||||
  .col-list-leave { | 
				
			||||
    // approximate position of delete button | 
				
			||||
    clip-path: circle(calc(100% + 5em) at calc(100% - 4em) 50%); | 
				
			||||
  } | 
				
			||||
  .col-list-leave-active .delete-btn { | 
				
			||||
    animation: col-list-leave-delete-btn .3s forwards; | 
				
			||||
  } | 
				
			||||
  .col-list-leave-active { | 
				
			||||
    transition: all .3s cubic-bezier(.4, .1, .6, .9); | 
				
			||||
  } | 
				
			||||
  .col-list-leave-to { | 
				
			||||
    clip-path: circle(0 at calc(100% - 4em) 50%); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  @keyframes col-list-leave-delete-btn { | 
				
			||||
    0% { | 
				
			||||
      transition-timing-function: cubic-bezier(.2, .4, .6, .9); | 
				
			||||
    } | 
				
			||||
    50% { | 
				
			||||
      transition-timing-function: cubic-bezier(.5, 0, .8, .5); | 
				
			||||
      transform: scale(1.1); | 
				
			||||
      opacity: 1; | 
				
			||||
    } | 
				
			||||
    100% { | 
				
			||||
      transform: scale(0); | 
				
			||||
      opacity: 0; | 
				
			||||
    } | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  .col-list-move { | 
				
			||||
    transition: transform .3s cubic-bezier(.2, .3, 0, 1); | 
				
			||||
  } | 
				
			||||
</style> | 
				
			||||
 | 
				
			||||
<script> | 
				
			||||
export default { | 
				
			||||
  props: { | 
				
			||||
    name: String, | 
				
			||||
    initialColumns: Array, | 
				
			||||
  }, | 
				
			||||
  data: function() { | 
				
			||||
    return { | 
				
			||||
      columns: this.initialColumns, | 
				
			||||
      colTypes: ['string', 'int', 'float', 'bool'], | 
				
			||||
    } | 
				
			||||
  }, | 
				
			||||
  methods: { | 
				
			||||
    delCol(n) { | 
				
			||||
      if (n == 0) return | 
				
			||||
 | 
				
			||||
      this.columns.splice(n, 1) | 
				
			||||
    }, | 
				
			||||
    addCol() { | 
				
			||||
      this.columns.push({ | 
				
			||||
        id: Math.random().toString(), | 
				
			||||
        name: '', | 
				
			||||
        type: 'string', | 
				
			||||
        title: '', | 
				
			||||
      }) | 
				
			||||
    }, | 
				
			||||
    move(i, dir) { | 
				
			||||
      let cur = this.columns[i]; | 
				
			||||
      let next = this.columns[i+dir]; | 
				
			||||
      this.$set(this.columns, i, next); | 
				
			||||
      this.$set(this.columns, i+dir, cur); | 
				
			||||
    }, | 
				
			||||
    beginDrag(i, evt) { | 
				
			||||
      const column = this.columns[i]; | 
				
			||||
      column._dragging = true; | 
				
			||||
      this.$set(this.columns, i, column); // notify vue | 
				
			||||
 | 
				
			||||
      let currentIndex = i; | 
				
			||||
 | 
				
			||||
      const dragMoveListener = e => { | 
				
			||||
        let cursorIndex = 0; | 
				
			||||
 | 
				
			||||
        // find cursor index by going through the list and adding the li | 
				
			||||
        // heights (can’t use their positions because they may be animating at | 
				
			||||
        // that moment) | 
				
			||||
        let accumY = this.$refs['col-list'].$el.getBoundingClientRect().top; | 
				
			||||
        for (let i = 0; i < this.columns.length; i++) { | 
				
			||||
          if (e.clientY > accumY) { | 
				
			||||
            cursorIndex = i; | 
				
			||||
          } | 
				
			||||
          accumY += $(this.$refs['col' + i]).outerHeight(true); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (cursorIndex !== currentIndex) { | 
				
			||||
          this.move(currentIndex, cursorIndex - currentIndex); | 
				
			||||
          currentIndex = cursorIndex; | 
				
			||||
        } | 
				
			||||
      } | 
				
			||||
 | 
				
			||||
      const dragEndListener = e => { | 
				
			||||
        column._dragging = false; | 
				
			||||
        this.$set(this.columns, currentIndex, column); // notify vue | 
				
			||||
 | 
				
			||||
        $(window).off('mousemove', dragMoveListener); | 
				
			||||
        $(window).off('mouseup', dragEndListener); | 
				
			||||
      }; | 
				
			||||
 | 
				
			||||
      $(window).on('mousemove', dragMoveListener); | 
				
			||||
      $(window).on('mouseup', dragEndListener); | 
				
			||||
    } | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
</script> | 
				
			||||
@ -0,0 +1,20 @@ | 
				
			||||
function busy (yes) { | 
				
			||||
  $('#draft-busy').css('opacity', yes ? 1 : 0) | 
				
			||||
} | 
				
			||||
 | 
				
			||||
function query (route, data, sucfn, erfn) { | 
				
			||||
  busy(true) | 
				
			||||
  if (!sucfn) sucfn = () => {} | 
				
			||||
  if (!sucfn) erfn = () => {} | 
				
			||||
  window.axios.post(route, data).then(sucfn).catch((error) => { | 
				
			||||
    console.error(error.message) | 
				
			||||
    erfn(error.response.data) | 
				
			||||
  }).then(() => { | 
				
			||||
    busy(false) | 
				
			||||
  }) | 
				
			||||
} | 
				
			||||
 | 
				
			||||
export { | 
				
			||||
  busy, | 
				
			||||
  query | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue