diff --git a/.DS_Store b/.DS_Store index b0eee8d15eb1587d64d8230196b56ce74d0727bb..a60aef9a74828569b9d446436c2f527514292dbd 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/CHANGELOG.md b/CHANGELOG.md index cc8df6898552d83cd3e43a062e57a9dac6f58b7f..67e2aa3ad1d2f6af8e91b2489bd704f6ad2ee744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 0.1.38 + +_5th December 2020_ + +### Changed + +- read mode is now attached to each node instead of positions. +- node text and positioning is now using a computed filter - so the iterating should be less CPU intensive. + # 0.1.37 _30th November 2020_ diff --git a/app/package.json b/app/package.json index e3f7a8f55909069d1a6b6ca3cf921f1d6ea0fb4a..3e86fb645c9bc54c7d4a7d056a16b9dec1b304ea 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "nodenogg.in", - "version": "0.1.37", + "version": "0.1.38", "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/app/src/components/CardsLayer.vue b/app/src/components/CardsLayer.vue index b1d9fb42e215b0222df57b2efd61fda6f4086b23..0ec9a4d63e9c405825d9554ff23883cbfe6da9a2 100644 --- a/app/src/components/CardsLayer.vue +++ b/app/src/components/CardsLayer.vue @@ -1,54 +1,48 @@ <template> - <div> - <div v-for="(value, index) in configPositions" v-bind:key="index"> - <div class="nodes" v-if="nodeid == value.node_id && deleted == false"> - <form> - <div v-if="value.read_mode == false"> - <div v-for="value in $options.myArray" v-bind:key="value.node_id"> - <textarea - v-if="nodeid == value.node_id" - @focus="editTrue(true)" - @blur="editTrue(false)" - autofocus - v-model="value.node_text" - @input="editNode" - :id="nodeid" - ref="nodetext" - placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" - ></textarea> - </div> - <p class="info">*markdown supported & autosaves</p> + <div class="grid"> + <div v-for="(nodes, index) in nodes_filtered" v-bind:key="index"> + <form class="nodes"> + <template v-if="nodes.read_mode == false"> + <textarea + @focus="editTrue(true)" + @blur="editTrue(false)" + autofocus + v-model="nodes.node_text" + @input="editNode" + :id="nodes.node_id" + ref="nodetext" + placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" + ></textarea> + </template> + <template v-else> + <p + :id="nodes.node_id" + :inner-html.prop="nodes.node_text | marked" + ></p> + </template> + <div class="btn-row"> + <SvgButton + buttonClass="nodes" + @click.prevent="deleteFlag(nodes.node_id)" + /> + <SvgButton2 + buttonClass="nodes" + @click.prevent="readFlag(nodes.node_id, nodes.read_mode)" + /> + </div> + + <div class="allemoji"> + <div + class="eachemoji" + v-for="(emojis, index) in configEmoji" + :key="index" + > + <template v-if="emojis.node_id == nodes.node_id">{{ + emojis.emoji_text + }}</template> </div> - <div class="readmode" v-if="value.read_mode && deleted == false"> - <p :id="nodeid" :inner-html.prop="nodetext | marked"></p> - </div> - <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> - </div> - - <div class="btn-row"> - <SvgButton buttonClass="nodes" @click.prevent="deleteFlag()" /> - <div v-if="value.read_mode == true && deleted == false"> - <SvgButton2 buttonClass="nodes" @click.prevent="readFlag()" /> - - <!-- <BaseButton class="read" buttonClass="action" @click="readFlag()" - >Edit Mode - </BaseButton> --> - </div> - <div v-else> - <SvgButton2 buttonClass="nodes" @click.prevent="readFlag()" /> - </div> - </div> - </form> - </div> + </div> + </form> </div> </div> </template> @@ -69,26 +63,28 @@ export default { } }, - props: { - nodeid: String, - nodetext: String, - deleted: Boolean, - }, - filters: { marked: marked, }, + computed: { + ...mapState({ + myNodes: (state) => state.myNodes, + configPositions: (state) => state.configPositions, + configEmoji: (state) => state.configEmoji, + }), + + nodes_filtered: function () { + return this.myNodes.filter((nodes) => { + return nodes.deleted == false + }) + }, + }, - computed: mapState({ - myNodes: (state) => state.myNodes, - configPositions: (state) => state.configPositions, - configEmoji: (state) => state.configEmoji, - }), - + // this is to stop sync chasing bug myArray: null, - created() { - this.$options.myArray = this.myNodes - this.readFlag + mounted() { + //access the custom option using $options + this.$options.myArray = this.nodes_filtered }, methods: { @@ -110,29 +106,17 @@ export default { // nothing happens } }, - readFlag(e) { - e = this.nodeid - - 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 - } - } + readFlag(e, f) { + readmode = f + readmode = !readmode + this.$store.dispatch('readFlag', { e, readmode }) - if (this.localreadmode == true) { - readmode = false - this.$store.dispatch('readFlag', { e, readmode }) + if (readmode == true) { this.mode = 'Read' } else { - readmode = true - this.$store.dispatch('readFlag', { e, readmode }) this.mode = 'Edit' } }, - // setFocus() { - // this.$refs.nodetext.focus() - // }, }, components: { SvgButton, @@ -142,6 +126,10 @@ export default { </script> <style lang="css" scoped> +.grid { + display: flex; + flex-wrap: wrap; +} .nodes { min-width: 343px; max-width: 343px; diff --git a/app/src/components/ListLayer.vue b/app/src/components/ListLayer.vue index 80287dc605a0fc1f04431eadc4a0c626ac7552b2..fe48288b8423c4d65ae45150dafc2fac89b64fcd 100644 --- a/app/src/components/ListLayer.vue +++ b/app/src/components/ListLayer.vue @@ -1,51 +1,49 @@ <template> <div> - <div v-for="(value, index) in configPositions" v-bind:key="index"> - <div v-if="nodeid == value.node_id && deleted == false"> - <form class="nodes"> - <div v-if="value.read_mode == false"> - <div v-for="value in $options.myArray" v-bind:key="value.node_id"> - <textarea - v-if="nodeid == value.node_id" - @focus="editTrue(true)" - @blur="editTrue(false)" - autofocus - v-model="value.node_text" - @input="editNode" - :id="nodeid" - ref="nodetext" - placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" - ></textarea> - </div> - <p class="info">*markdown supported & autosaves</p> + <div v-for="(nodes, index) in nodes_filtered" v-bind:key="index"> + <form class="nodes"> + <template v-if="nodes.read_mode == false"> + <textarea + @focus="editTrue(true)" + @blur="editTrue(false)" + autofocus + v-model="nodes.node_text" + @input="editNode" + :id="nodes.node_id" + placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" + ></textarea> + <p class="info">*markdown supported & autosaves</p> + </template> + <template v-else> + <p + :id="nodes.node_id" + :inner-html.prop="nodes.node_text | marked" + ></p> + </template> + + <div class="btn-row"> + <SvgButton + buttonClass="nodes" + @click.prevent="deleteFlag(nodes.node_id)" + /> + <SvgButton2 + buttonClass="nodes" + @click.prevent="readFlag(nodes.node_id, nodes.read_mode)" + /> + </div> + + <div class="allemoji"> + <div + class="eachemoji" + v-for="(emojis, index) in configEmoji" + :key="index" + > + <template v-if="emojis.node_id == nodes.node_id">{{ + emojis.emoji_text + }}</template> </div> - <div class="readmode" v-if="value.read_mode && deleted == false"> - <p :id="nodeid" :inner-html.prop="nodetext | marked"></p> - </div> - - <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> - </div> - - <div class="btn-row"> - <SvgButton buttonClass="nodes" @click.prevent="deleteFlag()" /> - <div v-if="value.read_mode == true && deleted == false"> - <SvgButton2 buttonClass="nodes" @click.prevent="readFlag()" /> - </div> - <div v-else> - <SvgButton2 buttonClass="nodes" @click.prevent="readFlag()" /> - </div> - </div> - </form> - </div> + </div> + </form> </div> </div> </template> @@ -66,26 +64,29 @@ export default { } }, - props: { - nodeid: String, - nodetext: String, - deleted: Boolean, - }, - filters: { marked: marked, }, - computed: mapState({ - myNodes: (state) => state.myNodes, - configPositions: (state) => state.configPositions, - configEmoji: (state) => state.configEmoji, - }), + computed: { + ...mapState({ + myNodes: (state) => state.myNodes, + configPositions: (state) => state.configPositions, + configEmoji: (state) => state.configEmoji, + }), + + nodes_filtered: function () { + return this.myNodes.filter((nodes) => { + return nodes.deleted == false + }) + }, + }, + // this is to stop sync chasing bug myArray: null, - created() { - this.$options.myArray = this.myNodes - this.readFlag + mounted() { + //access the custom option using $options + this.$options.myArray = this.nodes_filtered }, methods: { @@ -100,31 +101,20 @@ export default { }, deleteFlag(e) { - e = this.nodeid if (confirm('Confirm discard?')) { this.$store.dispatch('deleteFlag', { e }) } else { // nothing happens } }, + readFlag(e, f) { + readmode = f + readmode = !readmode + this.$store.dispatch('readFlag', { e, readmode }) - readFlag(e) { - e = this.nodeid - - 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 }) + if (readmode == true) { this.mode = 'Read' } else { - readmode = true - this.$store.dispatch('readFlag', { e, readmode }) this.mode = 'Edit' } }, @@ -159,7 +149,6 @@ textarea { font-family: 'Inter var', Helvetica, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - border: none; outline: none; background-color: rgb(187, 227, 255); diff --git a/app/src/components/NodesLayer.vue b/app/src/components/NodesLayer.vue index b4367f79ec43175c3323d6ba8c9502c8c2426e85..308d863465b1af38e296de7b2b0e073e07061fad 100644 --- a/app/src/components/NodesLayer.vue +++ b/app/src/components/NodesLayer.vue @@ -1,175 +1,154 @@ <template> <div ref="nodes" class="node"> - <div v-for="(value, index) in configPositions" v-bind:key="index"> - <div v-if="toolmode == 'move'"> - <draggable - class="innernode" - v-if="nodeid == value.node_id && deleted == false" - :w="value.width" - :h="value.height" - :x="value.x_pos" - :y="value.y_pos" - :z="value.z_index" - :scale="scale" - :draggable="false" - :resizable="false" - style="border: 2px dashed black; background-color: rgb(155, 194, 216)" - :min-width="200" - :min-height="220" - > - <form> - <div v-if="value.read_mode == false"> - <div v-for="value in $options.myArray" v-bind:key="value.node_id"> + <div v-if="toolmode == 'move'"> + <div v-for="(value, index) in $options.positionsArray" v-bind:key="index"> + <div v-for="(nodes, index) in $options.myArray" v-bind:key="index"> + <draggable + class="innernode" + v-if="nodes.node_id == value.node_id" + :w="value.width" + :h="value.height" + :x="value.x_pos" + :y="value.y_pos" + :z="value.z_index" + :scale="scale" + @activated="onActivated(nodes.node_id)" + :draggable="false" + :resizable="false" + @dragging="onDrag" + @resizing="onResize" + @dragstop="onDragstop" + @resizestop="onResizestop" + :drag-cancel="'.drag-cancel'" + style=" + border: 2px dashed black; + background-color: rgb(155, 194, 216); + " + :min-width="200" + :min-height="220" + > + <form class="nodes"> + <template v-if="nodes.read_mode == false"> <textarea - v-if="nodeid == value.node_id" @focus="editTrue(true)" @blur="editTrue(false)" - v-model="value.node_text" autofocus + v-model="nodes.node_text" @input="editNode" - :id="nodeid" - class="drag-cancel" - ref="nodetext" + :id="nodes.node_id" placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" ></textarea> - </div> - <p class="info">*markdown supported & autosaves</p> - </div> - <div v-if="value.read_mode == true"> - <p - class="read" - :id="nodeid" - :inner-html.prop="nodetext | marked" - ></p> - </div> - - <!-- <h3>Reactions</h3> --> - - <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> - </div> + <p class="info">*markdown supported & autosaves</p> + </template> + <template v-else> + <p + :id="nodes.node_id" + :inner-html.prop="nodes.node_text | marked" + ></p> + </template> + <template v-if="toolmode == 'select'"> + <div class="btn-row"> + <SvgButton + buttonClass="nodes" + @click.prevent="deleteFlag(nodes.node_id)" + /> + <SvgButton2 + buttonClass="nodes" + @click.prevent="readFlag(nodes.node_id, nodes.read_mode)" + /> + </div> + </template> - <div class="btn-row"> - <!-- <BaseButton buttonClass="danger" @click="deleteFlag()" - >Delete</BaseButton - > --> - <!-- <div v-if="value.read_mode == true"> - <BaseButton - class="read" - buttonClass="action" - @click="readFlag()" - >Edit Mode - </BaseButton> - </div> - <div v-else> - <BaseButton - class="read" - buttonClass="action" - @click="readFlag()" - >Read Mode</BaseButton + <div class="allemoji"> + <div + class="eachemoji" + v-for="(emojis, index) in configEmoji" + :key="index" > - </div> --> - </div> - </form> - </draggable> + <template v-if="emojis.node_id == nodes.node_id">{{ + emojis.emoji_text + }}</template> + </div> + </div> + </form> + </draggable> + </div> </div> + </div> - <!-- Same code as above when in any other mode other than move so you can drag nodes--> - - <div v-else> - <draggable - class="innernode" - v-if="nodeid == value.node_id && deleted == false" - :w="value.width" - :h="value.height" - :x="value.x_pos" - :y="value.y_pos" - :z="value.z_index" - :scale="scale" - @activated="onActivated" - @dragging="onDrag" - @resizing="onResize" - @dragstop="onDragstop" - @resizestop="onResizestop" - :drag-cancel="'.drag-cancel'" - style="border: 2px dashed black; background-color: rgb(155, 194, 216)" - :min-width="200" - :min-height="220" - > - <form> - <div v-if="value.read_mode == false"> - <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 - v-model="value.node_text" - @input="editNode" - :id="nodeid" - class="drag-cancel" - ref="nodetext" - placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" - > - </textarea> + <!-- IF NOT MOVE --> + + <div v-if="toolmode != 'move'"> + <div v-for="(value, index) in $options.positionsArray" v-bind:key="index"> + <div v-for="(nodes, index) in $options.myArray" v-bind:key="index"> + <draggable + class="innernode" + v-if="nodes.node_id == value.node_id" + :w="value.width" + :h="value.height" + :x="value.x_pos" + :y="value.y_pos" + :z="value.z_index" + :scale="scale" + @activated="onActivated(nodes.node_id)" + @dragging="onDrag" + @resizing="onResize" + @dragstop="onDragstop" + @resizestop="onResizestop" + :drag-cancel="'.drag-cancel'" + style=" + border: 2px dashed black; + background-color: rgb(155, 194, 216); + " + :min-width="200" + :min-height="220" + > + <form class="nodes"> + <template v-if="nodes.read_mode == false"> + <textarea + @focus="editTrue(true)" + @blur="editTrue(false)" + autofocus + v-model="nodes.node_text" + @input="editNode" + :id="nodes.node_id" + placeholder="Type your thoughts and ideas here! (auto saved every keystroke)" + ></textarea> + <p class="info">*markdown supported & autosaves</p> + </template> + <template v-else> + <p + :id="nodes.node_id" + :inner-html.prop="nodes.node_text | marked" + ></p> + </template> + <template v-if="toolmode == 'select'"> + <div class="btn-row"> + <SvgButton + buttonClass="nodes" + @click.prevent="deleteFlag(nodes.node_id)" + /> + <SvgButton2 + buttonClass="nodes" + @click.prevent="readFlag(nodes.node_id, nodes.read_mode)" + /> </div> - </div> - <p class="info">*markdown supported & autosaves</p> - </div> - <div v-if="value.read_mode == true"> - <p - class="read" - :id="nodeid" - :inner-html.prop="nodetext | marked" - ></p> - </div> + </template> - <!-- <h3>Reactions</h3> --> - <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> - </div> - <div class="btn-row"> - <!-- <BaseButton buttonClass="danger" @click="deleteFlag()" - >Discard</BaseButton - > --> - <SvgButton buttonClass="nodes" @click.prevent="deleteFlag()" /> - <div v-if="value.read_mode == true"> - <SvgButton2 buttonClass="nodes" @click.prevent="readFlag()" /> - <!-- <BaseButton - class="read" - buttonClass="action" - @click="readFlag()" - >Edit Mode - </BaseButton> --> - </div> - <div v-else> - <SvgButton2 buttonClass="nodes" @click.prevent="readFlag()" /> - <!-- <BaseButton - class="read" - buttonClass="action" - @click="readFlag()" - >Read Mode</BaseButton - > --> + <div class="allemoji"> + <div + class="eachemoji" + v-for="(emojis, index) in configEmoji" + :key="index" + > + <template v-if="emojis.node_id == nodes.node_id">{{ + emojis.emoji_text + }}</template> + </div> </div> - </div> - </form> - </draggable> + </form> + </draggable> + </div> </div> </div> </div> @@ -187,19 +166,12 @@ var readmode export default { name: 'NodesLayer', - props: { - nodeid: String, - nodetext: String, - nodewidth: Number, - nodeheight: Number, - deleted: Boolean, - }, - data() { return { pickupz: 1, localreadmode: false, mode: '', + nodeid: String, // firstload: true, } }, @@ -222,22 +194,52 @@ export default { // this.$refs.nodetext.focus() // }, - computed: mapState({ - scale: (state) => state.ui.scale, - myNodes: (state) => state.myNodes, - configPositions: (state) => state.configPositions, - configConnections: (state) => state.configConnections, - configEmoji: (state) => state.configEmoji, - toolmode: (state) => state.ui.mode, - }), + computed: { + ...mapState({ + scale: (state) => state.ui.scale, + myNodes: (state) => state.myNodes, + configPositions: (state) => state.configPositions, + configConnections: (state) => state.configConnections, + configEmoji: (state) => state.configEmoji, + toolmode: (state) => state.ui.mode, + }), + + nodes_filtered: function () { + return this.myNodes.filter((nodes) => { + return nodes.deleted == false + }) + }, + // this is not working correctly as dragging around moves wrong things + positions_filtered: function () { + return this.configPositions.filter((positions) => { + return this.myNodes.some((node) => { + return positions.node_id == node.node_id + }) + }) + }, + }, + // this is to stop sync chasing bug myArray: null, + positionsArray: null, + // NOTE: ok as created here but NOT if this is the first view to load created() { //access the custom option using $options - this.$options.myArray = this.myNodes + this.$options.myArray = this.nodes_filtered + this.$options.positionsArray = this.positions_filtered + }, + + updated() { + this.$options.positionsArray = this.positions_filtered + + if (this.toolmode == 'addNode') { + this.$options.myArray = this.nodes_filtered + this.$store.commit('ui/setMode', 'select') + } }, methods: { - onActivated() { + onActivated(e) { + this.nodeid = e var i for (i = 0; i < Object.keys(this.configPositions).length; i++) { if (this.configPositions[i].node_id == this.nodeid) { @@ -322,50 +324,8 @@ export default { editTrue(e) { this.$emit('edit-true', e) - // this.firstload = false - // // console.log(e) }, - // _.debounce(function(e) { - // this.input = e.target.value; - // }, 300) - - // 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), - - // 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 }) - - // this.$nextTick(() => { - // el.setSelectionRange(cursorPos, cursorPos) - // }) - // }, 600), - editNode(e) { var nodeid = e.target.id var nodetext = e.target.value @@ -373,30 +333,22 @@ export default { }, deleteFlag(e) { - e = this.nodeid if (confirm('Confirm discard?')) { this.$store.dispatch('deleteFlag', { e }) + this.$options.myArray = this.nodes_filtered } else { // nothing happens } }, - readFlag(e) { - e = this.nodeid - - 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 }) + readFlag(e, f) { + readmode = f + readmode = !readmode + this.$store.dispatch('readFlag', { e, readmode }) + this.$options.myArray = this.nodes_filtered + if (readmode == true) { this.mode = 'Read' } else { - readmode = true - this.$store.dispatch('readFlag', { e, readmode }) this.mode = 'Edit' } }, diff --git a/app/src/components/OtherCardslayer.vue b/app/src/components/OtherCardslayer.vue index f84d7c9025e87121a7a336992567729946c34648..711d1bc4904b785231bac1c526cdee79b43f83c7 100644 --- a/app/src/components/OtherCardslayer.vue +++ b/app/src/components/OtherCardslayer.vue @@ -1,11 +1,11 @@ <template> - <div> - <div v-if="deleted == false"> + <div class="grid"> + <div v-for="(nodes, index) in othernodes_filtered" v-bind:key="index"> <div class="nodes"> - <p :inner-html.prop="nodetext | marked"></p> + <p :inner-html.prop="nodes.node_text | marked"></p> <div class="eeee"> - <input :value="nodeid" name="id" readonly hidden /> + <input :value="nodes.node_id" name="id" readonly hidden /> <input id="emojifield" class="regular-input" @@ -38,7 +38,7 @@ :style="{ top: display.y + 'px', left: display.x + 'px' }" > <div class="emoji-picker__search"> - <input type="text" v-model="search" v-focus /> + <input type="text" v-model="search" /> </div> <div> <div v-for="(emojiGroup, category) in emojis" :key="category"> @@ -47,7 +47,7 @@ <span v-for="(emoji, emojiName) in emojiGroup" :key="emojiName" - @click="insert(emoji), sentReact()" + @click="insert(emoji), sentReact(nodes.node_id)" :title="emojiName" >{{ emoji }}</span > @@ -64,7 +64,7 @@ v-for="(emojis, index) in configEmoji" :key="index" > - <p v-if="nodeid == emojis.node_id"> + <p v-if="nodes.node_id == emojis.node_id"> {{ emojis.emoji_text }} </p> </div> @@ -79,6 +79,10 @@ import { mapState } from 'vuex' import EmojiPicker from 'vue-emoji-picker' import marked from 'marked' + +var nodeid +var emojitext + export default { name: 'OtherCardslayer', @@ -93,16 +97,18 @@ export default { } }, - props: { - nodeid: String, - nodetext: String, - deleted: Boolean, - }, + computed: { + ...mapState({ + otherNodes: (state) => state.otherNodes, + configEmoji: (state) => state.configEmoji, + }), - computed: mapState({ - otherNodes: (state) => state.otherNodes, - configEmoji: (state) => state.configEmoji, - }), + othernodes_filtered: function () { + return this.otherNodes.filter((nodes) => { + return nodes.deleted == false + }) + }, + }, filters: { marked: marked, @@ -112,9 +118,10 @@ export default { append(emoji) { this.input += emoji }, - sentReact(nodeid, emojitext) { + sentReact(e) { emojitext = this.input - nodeid = this.nodeid + nodeid = e + this.$store.dispatch('addEmoji', { nodeid, emojitext, @@ -127,6 +134,10 @@ export default { </script> <style lang="css" scoped> +.grid { + display: flex; + flex-wrap: wrap; +} .nodes { min-width: 343px; max-width: 343px; diff --git a/app/src/components/OtherNodeslayer.vue b/app/src/components/OtherNodeslayer.vue index 35d1234de59da83c53cc46d4061d9b9c312bea21..4bea445da702a2829518cf5375cd45b30aae21f5 100644 --- a/app/src/components/OtherNodeslayer.vue +++ b/app/src/components/OtherNodeslayer.vue @@ -1,211 +1,220 @@ <template> <div ref="othernodes" class="node"> - <div v-for="(value, index) in configPositions" v-bind:key="index"> - <div v-if="toolmode == 'move'"> - <!-- make draggable false as we are panning around --> - <draggable - v-if="nodeid == value.node_id && deleted == false" - :w="value.width" - :h="value.height" - :x="value.x_pos" - :y="value.y_pos" - :z="value.z_index" - :scale="scale" - @activated="onActivated" - @dragging="onDrag" - @resizing="onResize" - :draggable="false" - :resizable="false" - @dragstop="onDragstop" - @resizestop="onResizestop" - style="border: 2px solid black; background-color: rgb(205, 234, 255)" - :min-width="200" - :min-height="220" - > - <p class="read" :id="nodeid" :inner-html.prop="nodetext | marked"></p> - <!-- <h3>Reactions</h3> --> + <div v-if="toolmode == 'move'"> + <div v-for="(value, index) in $options.positionsArray" v-bind:key="index"> + <div v-for="(nodes, index) in othernodes_filtered" v-bind:key="index"> + <draggable + v-if="nodes.node_id == value.node_id" + :w="value.width" + :h="value.height" + :x="value.x_pos" + :y="value.y_pos" + :z="value.z_index" + :scale="scale" + @activated="onActivated(nodes.node_id)" + :draggable="false" + :resizable="false" + @dragging="onDrag" + @resizing="onResize" + @dragstop="onDragstop" + @resizestop="onResizestop" + style=" + border: 2px solid black; + background-color: rgb(205, 234, 255); + " + :min-width="200" + :min-height="220" + > + <p + class="read" + :id="nodes.node_id" + :inner-html.prop="nodes.node_text | marked" + ></p> - <div class="react" v-if="nodeid != undefined"> - <!-- <h2>React</h2> --> - <div class="eeee"> - <input :value="nodeid" name="id" readonly hidden /> - <input - id="emojifield" - class="regular-input" - v-model="input" - readonly - /> - <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> - </div> - <emoji-picker @emoji="append" :search="search"> - <div - class="emoji-invoker" - slot="emoji-invoker" - slot-scope="{ events: { click: clickEvent } }" - @click.stop="clickEvent" - > - <svg - height="24" - viewBox="0 0 24 24" - width="24" - xmlns="http://www.w3.org/2000/svg" + <div class="react"> + <div class="eeee"> + <input :value="nodes.node_id" name="id" readonly hidden /> + <input + id="emojifield" + class="regular-input" + v-model="input" + readonly + /> + + <emoji-picker @emoji="append" :search="search"> + <div + class="emoji-invoker" + slot="emoji-invoker" + slot-scope="{ events: { click: clickEvent } }" + @click.stop="clickEvent" > - <path d="M0 0h24v24H0z" fill="none" /> - <path - d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z" - /> - </svg> - </div> - <div - slot="emoji-picker" - slot-scope="{ emojis, insert, display }" - > + <svg + height="24" + viewBox="0 0 24 24" + width="24" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M0 0h24v24H0z" fill="none" /> + <path + d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z" + /> + </svg> + </div> <div - class="emoji-picker" - :style="{ top: display.y + 'px', left: display.x + 'px' }" + slot="emoji-picker" + slot-scope="{ emojis, insert, display }" > - <div class="emoji-picker__search"> - <input type="text" v-model="search" v-focus /> - </div> - <div> - <div - v-for="(emojiGroup, category) in emojis" - :key="category" - > - <h5>{{ category }}</h5> - <div class="emojis"> - <span - v-for="(emoji, emojiName) in emojiGroup" - :key="emojiName" - @click="insert(emoji)" - :title="emojiName" - >{{ emoji }}</span - > + <div + class="emoji-picker" + :style="{ top: display.y + 'px', left: display.x + 'px' }" + > + <div class="emoji-picker__search"> + <input type="text" v-model="search" /> + </div> + <div> + <div + v-for="(emojiGroup, category) in emojis" + :key="category" + > + <h5>{{ category }}</h5> + <div class="emojis"> + <span + v-for="(emoji, emojiName) in emojiGroup" + :key="emojiName" + @click="insert(emoji), sentReact(nodes.node_id)" + :title="emojiName" + >{{ emoji }}</span + > + </div> </div> </div> </div> </div> + </emoji-picker> + <div class="allemoji"> + <div + class="eachemoji" + v-for="(emojis, index) in configEmoji" + :key="index" + > + <p v-if="nodes.node_id == emojis.node_id"> + {{ emojis.emoji_text }} + </p> + </div> </div> - </emoji-picker> - <!-- <div class="btn-row"> - <BaseButton buttonClass="action" @click="sentReact()" - >Send Reaction</BaseButton - > - </div> --> + </div> </div> - </div> - </draggable> + </draggable> + </div> </div> + </div> - <div v-else> - <draggable - v-if="nodeid == value.node_id && deleted == false" - :w="value.width" - :h="value.height" - :x="value.x_pos" - :y="value.y_pos" - :z="value.z_index" - :scale="scale" - @activated="onActivated" - @dragging="onDrag" - @resizing="onResize" - @dragstop="onDragstop" - @resizestop="onResizestop" - style="border: 2px solid black; background-color: rgb(205, 234, 255)" - :min-width="200" - :min-height="220" - > - <p class="read" :id="nodeid" :inner-html.prop="nodetext | marked"></p> - <!-- <h3>Reactions</h3> --> - <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> - </div> - <div class="react" v-if="nodeid != undefined"> - <!-- <h2>React</h2> --> - <div class="eeee"> - <input :value="nodeid" name="id" readonly hidden /> - <input - id="emojifield" - class="regular-input" - v-model="input" - readonly - /> + <!-- IF NOT MOVE tool --> + + <div v-if="toolmode != 'move'"> + <div v-for="(value, index) in $options.positionsArray" v-bind:key="index"> + <div v-for="(nodes, index) in othernodes_filtered" v-bind:key="index"> + <draggable + v-if="nodes.node_id == value.node_id" + :w="value.width" + :h="value.height" + :x="value.x_pos" + :y="value.y_pos" + :z="value.z_index" + :scale="scale" + @activated="onActivated(nodes.node_id)" + @dragging="onDrag" + @resizing="onResize" + @dragstop="onDragstop" + @resizestop="onResizestop" + style=" + border: 2px solid black; + background-color: rgb(205, 234, 255); + " + :min-width="200" + :min-height="220" + > + <p + class="read" + :id="nodes.node_id" + :inner-html.prop="nodes.node_text | marked" + ></p> - <emoji-picker @emoji="append" :search="search"> - <div - class="emoji-invoker" - slot="emoji-invoker" - slot-scope="{ events: { click: clickEvent } }" - @click.stop="clickEvent" - > - <svg - height="24" - viewBox="0 0 24 24" - width="24" - xmlns="http://www.w3.org/2000/svg" + <div class="react"> + <div class="eeee"> + <input :value="nodes.node_id" name="id" readonly hidden /> + <input + id="emojifield" + class="regular-input" + v-model="input" + readonly + /> + + <emoji-picker @emoji="append" :search="search"> + <div + class="emoji-invoker" + slot="emoji-invoker" + slot-scope="{ events: { click: clickEvent } }" + @click.stop="clickEvent" > - <path d="M0 0h24v24H0z" fill="none" /> - <path - d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z" - /> - </svg> - </div> - <div - slot="emoji-picker" - slot-scope="{ emojis, insert, display }" - > + <svg + height="24" + viewBox="0 0 24 24" + width="24" + xmlns="http://www.w3.org/2000/svg" + > + <path d="M0 0h24v24H0z" fill="none" /> + <path + d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z" + /> + </svg> + </div> <div - class="emoji-picker" - :style="{ top: display.y + 'px', left: display.x + 'px' }" + slot="emoji-picker" + slot-scope="{ emojis, insert, display }" > - <div class="emoji-picker__search"> - <input type="text" v-model="search" v-focus /> - </div> - <div> - <div - v-for="(emojiGroup, category) in emojis" - :key="category" - > - <h5>{{ category }}</h5> - <div class="emojis"> - <span - v-for="(emoji, emojiName) in emojiGroup" - :key="emojiName" - @click="insert(emoji), sentReact()" - :title="emojiName" - >{{ emoji }}</span - > + <div + class="emoji-picker" + :style="{ top: display.y + 'px', left: display.x + 'px' }" + > + <div class="emoji-picker__search"> + <input type="text" v-model="search" /> + </div> + <div> + <div + v-for="(emojiGroup, category) in emojis" + :key="category" + > + <h5>{{ category }}</h5> + <div class="emojis"> + <span + v-for="(emoji, emojiName) in emojiGroup" + :key="emojiName" + @click="insert(emoji), sentReact(nodes.node_id)" + :title="emojiName" + >{{ emoji }}</span + > + </div> </div> </div> </div> </div> + </emoji-picker> + <div class="allemoji"> + <div + class="eachemoji" + v-for="(emojis, index) in configEmoji" + :key="index" + > + <p v-if="nodes.node_id == emojis.node_id"> + {{ emojis.emoji_text }} + </p> + </div> </div> - </emoji-picker> - <!-- <div class="btn-row"> - <BaseButton buttonClass="action" @click="sentReact()" - >Send Reaction</BaseButton - > - </div> --> + </div> </div> - </div> - </draggable> + </draggable> + </div> </div> </div> </div> @@ -224,19 +233,13 @@ export default { draggable, EmojiPicker, }, - props: { - nodeid: String, - nodetext: String, - nodewidth: Number, - nodeheight: Number, - deleted: Boolean, - }, data() { return { input: '', search: '', pickupz: 1, + nodeid: String, } }, @@ -244,17 +247,45 @@ export default { marked: marked, }, - mounted() {}, - computed: mapState({ - scale: (state) => state.ui.scale, - otherNodes: (state) => state.otherNodes, - configPositions: (state) => state.configPositions, - configConnections: (state) => state.configConnections, - configEmoji: (state) => state.configEmoji, - toolmode: (state) => state.ui.mode, - }), + computed: { + ...mapState({ + scale: (state) => state.ui.scale, + otherNodes: (state) => state.otherNodes, + configPositions: (state) => state.configPositions, + configConnections: (state) => state.configConnections, + configEmoji: (state) => state.configEmoji, + toolmode: (state) => state.ui.mode, + }), + + othernodes_filtered: function () { + return this.otherNodes.filter((nodes) => { + return nodes.deleted == false + }) + }, + + positions_filtered: function () { + return this.configPositions.filter((positions) => { + return this.otherNodes.find((node) => { + return positions.node_id == node.node_id + }) + }) + }, + }, + + positionsArray: null, + // NOTE: ok as created here but NOT if this is the first view to load + created() { + //access the custom option using $options + this.$options.positionsArray = this.positions_filtered + }, + + updated() { + this.$options.positionsArray = this.positions_filtered + }, + methods: { - onActivated() { + onActivated(e) { + this.nodeid = e var i for (i = 0; i < Object.keys(this.configPositions).length; i++) { if (this.configPositions[i].node_id == this.nodeid) { @@ -401,7 +432,7 @@ h3 { top: -0.5rem; right: 0.5rem; width: 1.5rem; - height: 1.5rem; + height: 2.5rem; /* transform: scale(1.6); */ /* margin: 0em 0em 1em 0em; */ /* border-radius: 50%; */ diff --git a/app/src/store/index.js b/app/src/store/index.js index 02c929f399dc1edff82f3a0eedce9ca31579db28..0b1f75efaaf5419807e5f3c57316d229b42ca519 100644 --- a/app/src/store/index.js +++ b/app/src/store/index.js @@ -183,7 +183,7 @@ const store = new Vuex.Store({ nodes: [ { // FIXME: these values are here as GET_ALL_NODES cant hunt a blank - // this shouldnt need to be here though + // this shouldn't need to be here though node_id: startup, node_text: '## Welcome \n This node was automatically by the system as a workaround for an iOS and URL routing bug, just ignore for now please \n ## 🤦ðŸ»â€â™‚ï¸', @@ -390,23 +390,21 @@ const store = new Vuex.Store({ // state.connectionstate = e // }, - ADD_NODE(state, e) { + ADD_NODE(state) { var uniqueid = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) state.localnodeid = uniqueid pouchdb.get(state.myclient).then(function (doc) { - if (e == undefined) { - doc.nodes.push({ - node_id: uniqueid, - node_text: '', - node_owner: state.myclient, - content_type: 'sheet', - deleted: false, - attachment_name: e, - }) - } + doc.nodes.push({ + node_id: uniqueid, + node_text: '', + node_owner: state.myclient, + content_type: 'sheet', + deleted: false, + read_mode: false, + }) return pouchdb .put({ @@ -578,6 +576,38 @@ const store = new Vuex.Store({ }, READ_FLAG(state, e) { + var i + for (i = 0; i < Object.keys(state.myNodes).length; i++) { + if (e.e == state.myNodes[i].node_id) { + state.myNodes[i].read_mode = e.readmode + } + } + pouchdb + .get(state.myclient) + .then(function (doc) { + // put the store into pouchdb + return pouchdb.bulkDocs([ + { + _id: state.myclient, + _rev: doc._rev, + _attachments: doc._attachments, + nodes: state.myNodes, + }, + ]) + }) + .then(function () { + return pouchdb.get(state.myclient).then(function (doc) { + state.myNodes = doc.nodes + }) + }) + .catch(function (err) { + if (err.status == 404) { + // pouchdb.put({ }) + } + }) + }, + + LEGACY_READ_FLAG(state, e) { var i // console.log(e.e) for (i = 0; i < Object.keys(state.configPositions).length; i++) { @@ -720,6 +750,11 @@ const store = new Vuex.Store({ commit('UPDATE_CONNECT_TWO', tonode, xposend, yposend) }, + legacyreadFlag: ({ commit }, e) => { + // var text = e.target.value + commit('LEGACY_READ_FLAG', e) + }, + readFlag: ({ commit }, e) => { // var text = e.target.value commit('READ_FLAG', e) diff --git a/app/src/views/Cards.vue b/app/src/views/Cards.vue index 35e6fe6b5a4ef9a25c1976428b713248d374ec52..13ad2aea68c06eb603f0437435f733d479ff2058 100644 --- a/app/src/views/Cards.vue +++ b/app/src/views/Cards.vue @@ -3,24 +3,9 @@ <div v-if="clientset"> <h1 class="mobile">All nodes - card view</h1> - <div class="grid"> - <CardsLayer - @editTrue="(e) => editTrue(e)" - v-for="value in myNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> + <CardsLayer @editTrue="(e) => editTrue(e)" /> - <OtherCardslayer - v-for="value in otherNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> - </div> + <OtherCardslayer /> <div class="btn-row"> <!-- <BaseButton class="new" buttonClass="action" @click="addNode()" @@ -156,11 +141,6 @@ export default { </script> <style lang="css" scoped> -.grid { - display: flex; - flex-wrap: wrap; -} - .mobile { margin-left: 1em; font-size: 1em; diff --git a/app/src/views/Collect.vue b/app/src/views/Collect.vue index daba60a5b36e092f38d1028d5ac6e6192d4b2757..c20497054c6e7c963f8ab955a469a2bcff94b9ba 100644 --- a/app/src/views/Collect.vue +++ b/app/src/views/Collect.vue @@ -3,14 +3,7 @@ <div v-if="clientset"> <div id="listwrapper"> <ModesCard /> - <ListLayer - @edit-true="(e) => editTrue(e)" - v-for="value in myNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> + <ListLayer @edit-true="(e) => editTrue(e)" /> <div class="btn-row"> <!-- <BaseButton class="new" buttonClass="action" @click="addNode()" >Create Node</BaseButton diff --git a/app/src/views/Organise.vue b/app/src/views/Organise.vue index 89de3b4888fed86a7d1174dd86974c58bca39d2d..77df0612a1242d2c68da39e199adfe0761627281 100644 --- a/app/src/views/Organise.vue +++ b/app/src/views/Organise.vue @@ -35,47 +35,21 @@ v-bind:translation="translation" > <div v-if="clientset"> - <OtherNodeslayer - v-for="value in otherNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> - <NodesLayer - @edit-true="(e) => editTrue(e)" - v-for="value in myNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> + <OtherNodeslayer /> + <NodesLayer @edit-true="(e) => editTrue(e)" /> <TipsLayer /> <ModeCardorg /> - <ConnectionsLayer /> + <!-- <ConnectionsLayer /> --> </div> <div v-else> - <OtherNodeslayer - v-for="value in otherNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> - <NodesLayer - @edit-true="(e) => editTrue(e)" - v-for="value in myNodes" - v-bind:key="value.node_id" - v-bind:nodeid="value.node_id" - v-bind:nodetext="value.node_text" - v-bind:deleted="value.deleted" - /> + <OtherNodeslayer /> + <NodesLayer @edit-true="(e) => editTrue(e)" /> <OnBoard @client-added="clientAdded()" @edit-true="(e) => editTrue(e)" /> - <ConnectionsLayer /> + <!-- <ConnectionsLayer /> --> </div> <ScribbleLayer v-bind:drawready="drawready"></ScribbleLayer> </PanZoomContainer> @@ -102,7 +76,7 @@ <script> import PanZoomContainer from '@/experimental/PanZoomContainer' -import ConnectionsLayer from '@/components/ConnectionsLayer' +// import ConnectionsLayer from '@/components/ConnectionsLayer' import NodesLayer from '@/components/NodesLayer' import OffLine from '@/components/OffLine' @@ -238,7 +212,7 @@ export default { // SelectionLayer, NodesLayer, OtherNodeslayer, - ConnectionsLayer, + // ConnectionsLayer, OnBoard, // ToolBar, OffLine,