Skip to content
Snippets Groups Projects
NodesLayer.vue 12 KiB
Newer Older
Adam Procter's avatar
Adam Procter committed
<template>
Adam Procter's avatar
Adam Procter committed
  <div ref="nodes" class="node">
Adam Procter's avatar
Adam Procter committed
    <div v-for="(value, index) in configPositions" v-bind:key="index">
Adam Procter's avatar
Adam Procter committed
      <div v-if="toolmode == 'move'">
        <vue-draggable-resizable
          class="innernode"
          v-if="nodeid == value.node_id && deleted == false"
Adam Procter's avatar
Adam Procter committed
          :w="value.width"
          :h="value.height"
          :x="value.x_pos"
          :y="value.y_pos"
          :z="value.z_index"
Adam Procter's avatar
Adam Procter committed
          :draggable="false"
Adam Procter's avatar
Adam Procter committed
          :resizable="false"
Adam Procter's avatar
Adam Procter committed
          style="border: 2px dashed black; background-color: rgb(155, 194, 216)"
          :min-width="200"
          :min-height="220"
Adam Procter's avatar
Adam Procter committed
        >
          <form>
Adam Procter's avatar
Adam Procter committed
            <div v-if="value.read_mode == false">
Adam Procter's avatar
Adam Procter committed
              <div v-for="value in $options.myArray" v-bind:key="value.node_id">
Adam Procter's avatar
Adam Procter committed
                <textarea
                  v-if="nodeid == value.node_id"
                  @focus="editTrue(true)"
                  @blur="editTrue(false)"
Adam Procter's avatar
Adam Procter committed
                  v-model="value.node_text"
Adam Procter's avatar
Adam Procter committed
                  autofocus
                  @input="editNode"
                  :id="nodeid"
                  class="drag-cancel"
                  ref="nodetext"
Adam Procter's avatar
Adam Procter committed
                  placeholder="Idea goes here! (auto saved every keystroke)"
Adam Procter's avatar
Adam Procter committed
                ></textarea>
              </div>
Adam Procter's avatar
Adam Procter committed
              <p class="info">*markdown supported &amp; autosaves</p>
Adam Procter's avatar
Adam Procter committed
            </div>
Adam Procter's avatar
Adam Procter committed
            <div v-if="value.read_mode == true">
              <p
                class="read"
                :id="nodeid"
                :inner-html.prop="nodetext | marked"
              ></p>
Adam Procter's avatar
Adam Procter committed
            </div>

Adam Procter's avatar
Adam Procter committed
            <!-- <h3>Reactions</h3> -->
Adam Procter's avatar
Adam Procter committed

Adam Procter's avatar
Adam Procter committed
            <div class="allemoji">
              <div
                class="eachemoji"
                v-for="(emojis, index) in configEmoji"
                :key="index"
              >
                <p v-if="nodeid == emojis.node_id">
                  {{ emojis.emoji_text }}
                </p>
              </div>
Adam Procter's avatar
Adam Procter committed
            </div>
Adam Procter's avatar
Adam Procter committed

Adam Procter's avatar
Adam Procter committed
            <div class="btn-row">
              <!-- <BaseButton buttonClass="danger" @click="deleteFlag()"
Adam Procter's avatar
Adam Procter committed
                >Delete</BaseButton
              <!-- <div v-if="value.read_mode == true">
Adam Procter's avatar
Adam Procter committed
                <BaseButton
                  class="read"
                  buttonClass="action"
                  @click="readFlag()"
Adam Procter's avatar
Adam Procter committed
                  >Edit Mode
Adam Procter's avatar
Adam Procter committed
                </BaseButton>
              </div>
              <div v-else>
                <BaseButton
                  class="read"
                  buttonClass="action"
                  @click="readFlag()"
Adam Procter's avatar
Adam Procter committed
                  >Read Mode</BaseButton
Adam Procter's avatar
Adam Procter committed
                >
Adam Procter's avatar
Adam Procter committed
            </div>
          </form>
        </vue-draggable-resizable>
      </div>

Adam Procter's avatar
Adam Procter committed
      <!-- Same code as above when in any other mode other than move so you can drag nodes-->

Adam Procter's avatar
Adam Procter committed
      <div v-else>
        <vue-draggable-resizable
          class="innernode"
          v-if="nodeid == value.node_id && deleted == false"
Adam Procter's avatar
Adam Procter committed
          :w="value.width"
          :h="value.height"
          :x="value.x_pos"
          :y="value.y_pos"
          :z="value.z_index"
Adam Procter's avatar
Adam Procter committed
          @activated="onActivated"
          @dragging="onDrag"
          @resizing="onResize"
          @dragstop="onDragstop"
          @resizestop="onResizestop"
          :drag-cancel="'.drag-cancel'"
Adam Procter's avatar
Adam Procter committed
          style="border: 2px dashed black; background-color: rgb(155, 194, 216)"
          :min-width="200"
          :min-height="220"
Adam Procter's avatar
Adam Procter committed
        >
          <form>
Adam Procter's avatar
Adam Procter committed
            <div v-if="value.read_mode == false">
Adam Procter's avatar
Adam Procter committed
              <div v-for="value in $options.myArray" v-bind:key="value.node_id">
                <div v-if="nodeid == value.node_id">
                  <textarea
                    @focus="editTrue(true)"
                    @blur="editTrue(false)"
                    autofocus
Adam Procter's avatar
Adam Procter committed
                    v-model="value.node_text"
                    @input="editNode"
                    :id="nodeid"
                    class="drag-cancel"
                    ref="nodetext"
                    placeholder="Idea goes here! (auto saved every keystroke)"
Adam Procter's avatar
Adam Procter committed
                  >
                  </textarea>
Adam Procter's avatar
Adam Procter committed
              </div>
Adam Procter's avatar
Adam Procter committed
              <p class="info">*markdown supported &amp; autosaves</p>
            </div>
Adam Procter's avatar
Adam Procter committed
            <div v-if="value.read_mode == true">
              <p
                class="read"
                :id="nodeid"
                :inner-html.prop="nodetext | marked"
              ></p>
Adam Procter's avatar
Adam Procter committed
            </div>

Adam Procter's avatar
Adam Procter committed
            <!-- <h3>Reactions</h3> -->
Adam Procter's avatar
Adam Procter committed
            <div class="allemoji">
              <div
                class="eachemoji"
                v-for="(emojis, index) in configEmoji"
                :key="index"
              >
                <p v-if="nodeid == emojis.node_id">
                  {{ emojis.emoji_text }}
                </p>
              </div>
Adam Procter's avatar
Adam Procter committed
            </div>
            <div class="btn-row">
              <BaseButton buttonClass="danger" @click="deleteFlag()"
                >Discard</BaseButton
Adam Procter's avatar
Adam Procter committed
              >
Adam Procter's avatar
Adam Procter committed
              <div v-if="value.read_mode == true">
Adam Procter's avatar
Adam Procter committed
                <BaseButton
                  class="read"
                  buttonClass="action"
                  @click="readFlag()"
Adam Procter's avatar
Adam Procter committed
                  >Edit Mode
Adam Procter's avatar
Adam Procter committed
                </BaseButton>
              </div>
              <div v-else>
                <BaseButton
                  class="read"
                  buttonClass="action"
                  @click="readFlag()"
Adam Procter's avatar
Adam Procter committed
                  >Read Mode</BaseButton
Adam Procter's avatar
Adam Procter committed
                >
              </div>
Adam Procter's avatar
Adam Procter committed
            </div>
          </form>
        </vue-draggable-resizable>
      </div>
Adam Procter's avatar
Adam Procter committed
    </div>
Adam Procter's avatar
Adam Procter committed
  </div>
</template>

<script>
Adam Procter's avatar
Adam Procter committed
import { mapState } from 'vuex'
Adam Procter's avatar
Adam Procter committed
import marked from 'marked'
Adam Procter's avatar
Adam Procter committed
//import lodash from 'lodash'
var readmode
Adam Procter's avatar
Adam Procter committed

export default {
  name: 'NodesLayer',
  props: {
    nodeid: String,
    nodetext: String,
    nodewidth: Number,
Adam Procter's avatar
Adam Procter committed
    nodeheight: Number,
Adam Procter's avatar
Adam Procter committed
    deleted: Boolean,
Adam Procter's avatar
Adam Procter committed

Adam Procter's avatar
Adam Procter committed
  data() {
    return {
      pickupz: 1,
Adam Procter's avatar
Adam Procter committed
      localreadmode: false,
      mode: '',
Adam Procter's avatar
Adam Procter committed
      // firstload: true,
Adam Procter's avatar
Adam Procter committed

  filters: {
Adam Procter's avatar
Adam Procter committed
    marked: marked,
Adam Procter's avatar
Adam Procter committed
  },

Adam Procter's avatar
Adam Procter committed
  // FIXME: how do we know how to focus on the newest node ?
  // FIXME: Tab between them would also be good
  // var delay = 100
  // var input
  // mounted() {
  //   setTimeout(this.setFocus, delay)
  //   input = this.$refs.nodetext
Adam Procter's avatar
Adam Procter committed
  //   // console.log(input)
Adam Procter's avatar
Adam Procter committed
  // },
  // method
  // setFocus() {
  //   this.$refs.nodetext.focus()
  // },
Adam Procter's avatar
Adam Procter committed

Adam Procter's avatar
Adam Procter committed
  computed: mapState({
Adam Procter's avatar
Adam Procter committed
    myNodes: (state) => state.myNodes,
    configPositions: (state) => state.configPositions,
Adam Procter's avatar
Adam Procter committed
    configConnections: (state) => state.configConnections,
Adam Procter's avatar
Adam Procter committed
    configEmoji: (state) => state.configEmoji,
    toolmode: (state) => state.ui.mode,
Adam Procter's avatar
Adam Procter committed
  }),
Adam Procter's avatar
Adam Procter committed
  myArray: null,
  created() {
    //access the custom option using $options
    this.$options.myArray = this.myNodes
  },

Adam Procter's avatar
Adam Procter committed
  methods: {
    onActivated() {
      var i
      for (i = 0; i < Object.keys(this.configPositions).length; i++) {
        if (this.configPositions[i].node_id == this.nodeid) {
          this.width = this.configPositions[i].width
          this.height = this.configPositions[i].height
        }
      }
    },
    onResize(x, y, width, height) {
Adam Procter's avatar
Adam Procter committed
      this.localx = x
      this.localy = y
Adam Procter's avatar
Adam Procter committed
      this.width = width
      this.height = height
    },
    onResizestop(x, y, width, height, zindex) {
      var localnodeid = this.nodeid
      var i
      for (i = 0; i < Object.keys(this.configPositions).length; i++) {
        if (this.configPositions[i].node_id == this.nodeid) {
          this.width = this.configPositions[i].width
          this.height = this.configPositions[i].height
          this.pickupz = this.configPositions[i].z_index
        }
      }
      this.width = width
      this.height = height
      this.$store.dispatch('movePos', {
        localnodeid,
        x,
        y,
        width,
        height,
Adam Procter's avatar
Adam Procter committed
        zindex,
    onDrag(x, y) {
Adam Procter's avatar
Adam Procter committed
      this.localx = x
      this.localy = y
Adam Procter's avatar
Adam Procter committed
    },
    onDragstop(x, y, width, height, zindex) {
      var localnodeid = this.nodeid
      width = this.width
      height = this.height
Adam Procter's avatar
Adam Procter committed
      var i
Adam Procter's avatar
Adam Procter committed
      // FIXME: What is this for loop doing ??
Adam Procter's avatar
Adam Procter committed
      for (i = 0; i < Object.keys(this.configPositions).length; i++) {
        if (this.configPositions[i].node_id == this.nodeid) {
          this.localx = this.configPositions[i].x_pos
          this.localy = this.configPositions[i].y_pos
          this.pickupz = this.configPositions[i].z_index
Adam Procter's avatar
Adam Procter committed
        }
      }
      this.$store.dispatch('movePos', {
        localnodeid,
        x,
        y,
        width,
        height,
Adam Procter's avatar
Adam Procter committed
        zindex,
Adam Procter's avatar
Adam Procter committed

      var j
      for (j = 0; j < Object.keys(this.configConnections).length; j++) {
        if (this.configConnections[j].start_id == this.nodeid) {
          this.$store.dispatch('updateConnect', {
            localnodeid,
            x,
            y,
          })
        }
        if (this.configConnections[j].end_id == this.nodeid) {
          this.$store.dispatch('updateConnectTwo', {
            localnodeid,
            x,
            y,
          })
        }
      }
Adam Procter's avatar
Adam Procter committed
    editTrue(e) {
      this.$emit('editTrue', e)
Adam Procter's avatar
Adam Procter committed
      // this.firstload = false
Adam Procter's avatar
Adam Procter committed
      //  // console.log(e)
Adam Procter's avatar
Adam Procter committed
    },
    // _.debounce(function(e) {
    //             this.input = e.target.value;
    //           }, 300)

Adam Procter's avatar
Adam Procter committed
    // editNode(e) {
    //   const el = e.target
    //   const cursorPos = el.selectionStart
    //   console.log(cursorPos)
    //   var nodeid = e.target.id
    //   var nodetext = e.target.value
    //   this.$store.dispatch('editNode', { nodeid, nodetext })

    //   this.$nextTick(() => {
    //     e.target.selectionStart = e.target.selectionEnd = cursorPos
    //   })

    // this.$nextTick(() => {
    //   el.setSelectionRange(cursorPos, cursorPos)
    // })
    //},

    // editNode: lodash.debounce(function (e) {
    //   var nodeid = e.target.id
    //   var nodetext = e.target.value
    //   this.$store.dispatch('editNode', { nodeid, nodetext })
    // }, 600),

Adam Procter's avatar
Adam Procter committed
    // editNode: lodash.debounce(function (e) {
    //   const el = e.target
    //   const cursorPos = el.selectionStart

    //   var nodeid = e.target.id
    //   var nodetext = e.target.value
    //   this.$store.dispatch('editNode', { nodeid, nodetext })
Adam Procter's avatar
Adam Procter committed

Adam Procter's avatar
Adam Procter committed
    //   this.$nextTick(() => {
    //     el.setSelectionRange(cursorPos, cursorPos)
    //   })
    // }, 600),

    editNode(e) {
Adam Procter's avatar
Adam Procter committed
      var nodeid = e.target.id
      var nodetext = e.target.value
      this.$store.dispatch('editNode', { nodeid, nodetext })
Adam Procter's avatar
Adam Procter committed
    },
    deleteFlag(e) {
      e = this.nodeid
Adam Procter's avatar
Adam Procter committed
      if (confirm('Confirm discard?')) {
        this.$store.dispatch('deleteFlag', { e })
      } else {
        // nothing happens
      }
Adam Procter's avatar
Adam Procter committed
    },
    readFlag(e) {
      e = this.nodeid

Adam Procter's avatar
Adam Procter committed
      var i
      for (i = 0; i < Object.keys(this.configPositions).length; i++) {
        if (this.configPositions[i].node_id == this.nodeid) {
          this.localreadmode = this.configPositions[i].read_mode
        }
      }

      if (this.localreadmode == true) {
        readmode = false
        this.$store.dispatch('readFlag', { e, readmode })
Adam Procter's avatar
Adam Procter committed
        this.mode = 'Read'
      } else {
        readmode = true
        this.$store.dispatch('readFlag', { e, readmode })
Adam Procter's avatar
Adam Procter committed
        this.mode = 'Edit'
      }
Adam Procter's avatar
Adam Procter committed
    },
  },
Adam Procter's avatar
Adam Procter committed
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
Adam Procter's avatar
Adam Procter committed
.node {
Adam Procter's avatar
Adam Procter committed
  position: relative;
}

.vdr {
  padding: 0 0.5em;
}

Adam Procter's avatar
Adam Procter committed
.info {
  font-size: 0.8em;
Adam Procter's avatar
Adam Procter committed
  display: inline;
Adam Procter's avatar
Adam Procter committed
}

textarea {
  width: 100%;
Adam Procter's avatar
Adam Procter committed
  height: 175px;
Adam Procter's avatar
Adam Procter committed
  resize: none;
Adam Procter's avatar
Adam Procter committed
  font-size: 18px;
Adam Procter's avatar
Adam Procter committed
  box-sizing: border-box;
  font-family: 'Inter var', Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
Adam Procter's avatar
Adam Procter committed
  margin-top: 1em;
Adam Procter's avatar
Adam Procter committed
  border: none;
  outline: none;
  background-color: rgb(187, 227, 255);
  scrollbar-color: yellow rgb(187, 227, 255);
Adam Procter's avatar
Adam Procter committed
}

.btn-row {
  position: relative;
  margin-bottom: 5px;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  padding: 0 15px;
  border-radius: 4px;
Adam Procter's avatar
Adam Procter committed
}

.allemoji {
  font-size: 2em;
Adam Procter's avatar
Adam Procter committed
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(0, auto));

Adam Procter's avatar
Adam Procter committed
  /* float: left; */
Adam Procter's avatar
Adam Procter committed
.eachemoji p {
  margin: 0em;
}

img {
  width: 100%;
}
/* .dragging {
  transform: scale(0.7);
} */
Adam Procter's avatar
Adam Procter committed
</style>