diff --git a/canvas-10-feb/package.json b/canvas-10-feb/package.json index eaf706528e736d7aa85da76867ec49af77df74cf..7c1c6a14b5a8f82633b099f24ce6fd0665ac36d1 100644 --- a/canvas-10-feb/package.json +++ b/canvas-10-feb/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "core-js": "^3.6.4", + "marked": "^0.8.0", "pouchdb": "^7.2.1", "pouchdb-find": "^7.2.1", "vue": "^2.6.11", diff --git a/canvas-10-feb/src/components/ControlsLayer.vue b/canvas-10-feb/src/components/ControlsLayer.vue index 426cbb13e4112502f5688cc1c0908cda4b27cf87..e85e77afcf25fbbfdba3a2fc0201c390282c13a8 100644 --- a/canvas-10-feb/src/components/ControlsLayer.vue +++ b/canvas-10-feb/src/components/ControlsLayer.vue @@ -1,7 +1,10 @@ <template> <div class="controls"> <div class="btn-row"> - <button on:click="popups.showPane = !popups.showPane">Button</button> + <!-- <button on:click="popups.showPane = !popups.showPane"> --> + <button @click="addNode()"> + Create Node + </button> </div> <!-- <div class="popup" v-if="popups.showPane"> @@ -13,7 +16,19 @@ </div> </template> -<script></script> +<script> +export default { + data() { + return {} + }, + methods: { + addNode() { + this.$store.dispatch('addNode') + // this.$store.dispatch('shortcutsState', true) + } + } +} +</script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> diff --git a/canvas-10-feb/src/components/DeBug.vue b/canvas-10-feb/src/components/DeBug.vue new file mode 100644 index 0000000000000000000000000000000000000000..ddef7bcc5b279800e3413be6302347df8f172f7b --- /dev/null +++ b/canvas-10-feb/src/components/DeBug.vue @@ -0,0 +1,87 @@ +<template> + <div class="debug"> + <hr /> + <!-- <h2>Debug Options</h2> --> + <h4>LAST UPDATE 24th Feb 2020.</h4> + <p>You need to know what these buttons do before you press them.</p> + <button class="danger" @click="removeLocal()"> + Join another microcosm + </button> + <!-- <button @click="exportStorage()">Export my contributions</button> + <button class="danger" v-on:click="deleteClient"> + Delete my contributions (inc. attachments) permanently + </button> + <button @click="handleConnection()">Online check</button> --> + <p>That's why they are red.</p> + </div> +</template> + +<script> +var serverUrl = 'https://nodenogg.in' + +export default { + mounted() { + window.addEventListener('online', this.handleConnection) + window.addEventListener('offline', this.handleConnection) + }, + methods: { + exportStorage: function() { + // Save local indexeddb document-store to JSON file + // or export state.notes to JSON file + }, + removeLocal: function() { + localStorage.removeItem('myNNClient') + localStorage.removeItem('mylastMicrocosm') + // Hardcoded in thye case that a URL had parameters the reload fails + location.assign('https://alpha.nodenogg.in/') + //location.assign('http://localhost:8080/') + }, + + deleteClient() { + this.$store.dispatch('deleteClient') + }, + handleConnection: function() { + var ref = this + if (navigator.onLine) { + this.isReachable(this.getServerUrl()).then(function(online) { + if (online) { + // handle online status + console.log('online') + location.reload() + } else { + console.log('no connectivity') + } + }) + } else { + // handle offline status + console.log('offline') + ref.$emit('offlineTriggered') + } + }, + isReachable: function(url) { + return fetch(url, { method: 'HEAD', mode: 'no-cors' }) + .then(function(resp) { + return resp && (resp.ok || resp.type === 'opaque') + }) + .catch(function(err) { + console.warn('[conn test failure]:', err) + }) + }, + getServerUrl: function() { + return serverUrl || window.location.origin + } + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this component only --> +<style scoped> +li:before { + content: ''; +} + +b { + background-color: yellow; + padding-right: 2em; +} +</style> diff --git a/canvas-10-feb/src/components/NodesLayer.vue b/canvas-10-feb/src/components/NodesLayer.vue index be4a4a4dd548f49bc53b9f08715c759e21c6a532..f5725d1cdeaf920d6ed6207096b7a9d1901cc20b 100644 --- a/canvas-10-feb/src/components/NodesLayer.vue +++ b/canvas-10-feb/src/components/NodesLayer.vue @@ -5,6 +5,7 @@ :h="200" @dragging="onDrag" @resizing="onResize" + @dragstop="onDragstop" style="background-color: rgb(205, 234, 255);" > <form> @@ -16,30 +17,33 @@ :id="nodeid" ></textarea> </div> - + <div v-for="(value, index) in configPositions" v-bind:key="index"> + <p v-if="nodeid == value.nodeid">{{ x }}, {{ y }}</p> + </div> <p>markdown supported</p> - <button>delete</button> + <button class="danger" @click="deleteFlag()"> + Delete + </button> </form> </vue-draggable-resizable> </div> </template> <script> -//import { drag } from './mixins/drag.js' import { mapState } from 'vuex' export default { name: 'NodesLayer', - // mixins: [drag], - props: { nodeid: String, nodetext: String }, + + props: { nodeid: String, nodetext: String, xpos: Number, ypos: Number }, data() { return { thistext: this.nodetext, width: 0, height: 0, - x: 0, - y: 0 + x: this.xpos, + y: this.ypos } }, @@ -48,19 +52,30 @@ export default { // this.makeDraggable(nodes) }, computed: mapState({ - myNodes: state => state.myNodes + myNodes: state => state.myNodes, + configPositions: state => state.configPositions }), methods: { - onResize: function(x, y, width, height) { + onResize(x, y, width, height) { this.x = x this.y = y this.width = width this.height = height }, - onDrag: function(x, y) { + onDrag(x, y) { this.x = x this.y = y }, + onDragstop(x, y) { + var localnodeid = this.nodeid + // console.log(x) + // console.log(y) + // console.log(localnodeid) + this.$store.dispatch('movePos', { localnodeid, x, y }) + }, + // end DRAG update the right positions in DB + // this.$store.dispatch('movePos', {this.nodeid, this.x, this.y}) + setFocus() { // this.$refs.nodetext.focus() }, @@ -69,7 +84,10 @@ export default { var nodetext = e.target.value this.$store.dispatch('editNode', { nodeid, nodetext }) }, - deleteFlag() {} + deleteFlag(e) { + e = this.nodeid + this.$store.dispatch('deleteFlag', { e }) + } } } </script> diff --git a/canvas-10-feb/src/components/otherNodeslayer.vue b/canvas-10-feb/src/components/otherNodeslayer.vue index 291d99f453b3758d0bab871d7fabb500f96a9f5f..071951705f578be9dfec5cc1d2c460866b1e8b82 100644 --- a/canvas-10-feb/src/components/otherNodeslayer.vue +++ b/canvas-10-feb/src/components/otherNodeslayer.vue @@ -7,14 +7,14 @@ @resizing="onResize" style="border: 1px solid black; background-color: rgb(205, 234, 255);" > - <p :id="nodeid">{{ nodetext }}</p> - <p>markdown supported</p> + <p :id="nodeid" :inner-html.prop="nodetext | marked"></p> </vue-draggable-resizable> </div> </template> <script> //import { drag } from './mixins/drag.js' +import marked from 'marked' export default { name: 'otherNodeslayer', @@ -31,6 +31,10 @@ export default { } }, + filters: { + marked: marked + }, + mounted() { // var othernodes = this.$refs.othernodes // this.makeDraggable(othernodes) diff --git a/canvas-10-feb/src/store/index.js b/canvas-10-feb/src/store/index.js index 65fb09ef4fb2322ae6592bc6442d2964c7f97372..a707475ca72df626ad43685fcda275a5f62519ba 100644 --- a/canvas-10-feb/src/store/index.js +++ b/canvas-10-feb/src/store/index.js @@ -162,12 +162,12 @@ const store = new Vuex.Store({ { // FIXME: these values are here as GET_ALL_NODES cant hunt a blank // this shouldnt need to be here - index: uniqueid, + nodeid: uniqueid, - nodetext: state.myclient, + nodetext: 'Ignore this node' + state.myclient, nodeowner: state.myclient, content_type: 'sheet', - // TEMP: this hides this node card as its effectivly auto deleted + // TEMP: this hides the first node card as its effectivly auto deleted deleted: true, attachment_name: '' } @@ -194,9 +194,42 @@ const store = new Vuex.Store({ }) }, - MOVE_POS() {}, + MOVE_POS(state, e) { + console.log(e.localnodeid) + var i + for (i = 0; i < Object.keys(state.configPositions).length; i++) { + if (e.localnodeid == state.configPositions[i].nodeid) { + state.configPositions[i].xpos = e.x + state.configPositions[i].ypos = e.y + } + } + + pouchdb + .get(state.global_pos_name) + .then(function(doc) { + // console.log(doc) + // put the store into pouchdb + return pouchdb.bulkDocs([ + { + _id: state.global_pos_name, + _rev: doc._rev, + positions: state.configPositions + } + ]) + }) + .then(function() { + return pouchdb.get(state.global_pos_name).then(function(doc) { + state.configPositions = doc.positions + }) + }) + .catch(function(err) { + if (err.status == 404) { + // pouchdb.put({ }) + } + }) + }, - ADD_DOC(state, e) { + ADD_NODE(state, e) { var uniqueid = Math.random() .toString(36) @@ -209,7 +242,6 @@ const store = new Vuex.Store({ pouchdb.get(state.myclient).then(function(doc) { if (e == undefined) { doc.nodes.push({ - index: uniqueid, nodeid: uniqueid, nodetext: '', nodeowner: state.myclient, @@ -224,7 +256,6 @@ const store = new Vuex.Store({ _id: state.myclient, _rev: doc._rev, _attachments: doc._attachments, - index: doc.uniqueid, nodes: doc.nodes }) .then(function() { @@ -294,6 +325,38 @@ const store = new Vuex.Store({ // pouchdb.put({ }) } }) + }, + + DELETE_FLAG(state, e) { + var i + for (i = 0; i < Object.keys(state.myNodes).length; i++) { + if (e.e == state.myNodes[i].nodeid) { + state.myNodes[i].deleted = true + } + } + 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({ }) + } + }) } }, actions: { @@ -337,8 +400,20 @@ const store = new Vuex.Store({ setClient: ({ commit }, e) => { commit('SET_CLIENT', e) }, + + movePos: ({ commit }, nodeid, xpos, ypos) => { + commit('MOVE_POS', nodeid, xpos, ypos) + }, + + addNode: ({ commit }, e) => { + commit('ADD_NODE', e) + }, editNode: ({ commit }, { nodeid, nodetext }) => { commit('EDIT_NODE', { nodeid, nodetext }) + }, + deleteFlag: ({ commit }, e) => { + // var text = e.target.value + commit('DELETE_FLAG', e) } }, modules: {} diff --git a/canvas-10-feb/src/views/Home.vue b/canvas-10-feb/src/views/Home.vue index ee177861e615887fe571e5c187d29e7844df71ff..b54ef6763fe0e71234e95e9b4126ffc13520bfd6 100644 --- a/canvas-10-feb/src/views/Home.vue +++ b/canvas-10-feb/src/views/Home.vue @@ -7,6 +7,7 @@ v-bind:nodeid="value.nodeid" v-bind:nodetext="value.nodetext" /> + <NodesLayer v-for="value in myNodes" v-bind:key="value.nodeid" @@ -15,6 +16,7 @@ /> <CanvasLayer /> + <DeBug /> <ControlsLayer /> </div> <OnBoard v-else @clientAdded="clientAdded()" /> @@ -27,6 +29,7 @@ import OnBoard from '@/components/OnBoard.vue' import CanvasLayer from '@/components/CanvasLayer.vue' import NodesLayer from '@/components/NodesLayer.vue' import OtherNodeslayer from '@/components/OtherNodeslayer.vue' +import DeBug from '@/components/DeBug.vue' import ControlsLayer from '@/components/ControlsLayer.vue' import { mapState } from 'vuex' @@ -36,7 +39,8 @@ export default { data: function() { return { - clientset: false + clientset: false, + offline: false } }, @@ -45,15 +49,24 @@ export default { CanvasLayer, NodesLayer, OtherNodeslayer, + DeBug, ControlsLayer }, computed: mapState({ myNodes: state => state.myNodes, - otherNodes: state => state.otherNodes + otherNodes: state => state.otherNodes, + configPositions: state => state.configPositions }), methods: { clientAdded() { this.clientset = !this.clientset + }, + + offlineTriggered() { + this.offline = true + }, + onlineTriggered() { + this.offline = false } } } diff --git a/canvas-10-feb/yarn.lock b/canvas-10-feb/yarn.lock index ba0df1de4047543ea84eee24f2cfe618c5aa6227..bc8b8d3bafd26ad9b9ae21661c856da16503d9b0 100644 --- a/canvas-10-feb/yarn.lock +++ b/canvas-10-feb/yarn.lock @@ -4476,6 +4476,10 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +marked@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.8.0.tgz#ec5c0c9b93878dc52dd54be8d0e524097bd81a99" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"