Stack.vue
1 <template lang='pug'> 2 3 #tasks 4 img.oodd(v-if='c.length >= 1' draggable='false' src='../assets/images/open.svg', ref='swipebar' :ondrop='drop' :ondragover="allowDrop" :ondragleave='dragLeave') 5 .ptr(:ondrop='drop' :ondragover="allowDrop" :ondragleave='dragLeave') 6 span.third.dot(:class='{hidden:open || c.length <= 1}' ref='previous') 7 span.third(ref='mandelorb' draggable="true" :ondragstart='dragStart') 8 .donut(:class='{pileselected: $store.state.upgrades.color === stack, pileopen: $store.getters.contextCard.stackView[stack] === -1, dropping:dropping}') 9 .fixedstatus(v-if='c.length > 1 && sanePosition !== -1' ) {{ sanePosition + 1 }} of {{ c.length }} 10 .fixedstatus(v-else-if='c.length === 1') 1 11 .fixedstatus(v-else-if='c.length === 0') - 12 .fixedstatus(v-else-if='sanePosition === -1') {{c.length}} 13 span.third.dot(:class='{hidden:open || c.length <= 1}' ref='next') 14 .open(v-if='open') 15 div(v-for='(b, i) in c' :key="b.taskId") 16 .orby(v-if='i > 0' @click='orbswap(b.taskId)' :class='{hidden:!$store.getters.member.guides}') 17 .donut.hidden 18 hypercard(:b="b" :key="b.taskId" :inId='taskId' :c='panelIds') 19 .box(v-else) 20 hypercard(:b="c[sanePosition]" :inId='taskId' :key='c[sanePosition].taskId') 21 .piledrop(v-if='c.length < 1' :ondrop='drop' :ondragover="allowDrop" :ondragleave='dragLeave' :class='{dropping:dropping}' @click='stackTap') 22 23 24 </template> 25 26 <script> 27 import Hammer from 'hammerjs' 28 import Propagating from 'propagating-hammerjs' 29 import Hypercard from "./Card.vue" 30 31 export default { 32 props: ['stack', 'position', 'taskId'], 33 mounted(){ 34 let orbel = this.$refs.mandelorb 35 if(!orbel) return 36 let orbmc = Propagating(new Hammer.Manager(orbel)) 37 38 let orbTap = new Hammer.Tap({ time: 400 }) 39 orbmc.add(orbTap) 40 orbmc.on('tap', (e) => { 41 this.stackTap() 42 e.stopPropagation() 43 }) 44 45 let barel = this.$refs.swipebar 46 if(!barel) return 47 let barmc = Propagating(new Hammer.Manager(barel)) 48 49 let barSwipe = new Hammer.Swipe({ threshold: 50 }) 50 barmc.add(barSwipe) 51 52 barmc.add(orbTap) 53 54 barmc.on('tap', (e) => { 55 this.stackTap() 56 e.stopPropagation() 57 }) 58 59 60 barmc.on('swipeleft', (e) => { 61 this.previous() 62 e.stopPropagation() 63 }) 64 65 barmc.on('swiperight', (e) => { 66 this.next() 67 e.stopPropagation() 68 }) 69 70 barmc.on('swipeup', (e) => { 71 this.$store.dispatch("makeEvent" , { 72 type: "task-prioritized", 73 taskId: this.topCard.taskId, 74 inId: this.$store.getters.contextCard.taskId, 75 fromId: this.topCard.taskId 76 }) 77 e.stopPropagation() 78 }) 79 80 barmc.on('swipedown', (e) => { 81 this.$store.dispatch("makeEvent" , { 82 type: "task-de-sub-tasked", 83 inId: this.$store.getters.contextCard.taskId, 84 taskId: this.topCard.taskId 85 }) 86 e.stopPropagation() 87 }); 88 89 let orbPress = new Hammer.Press({ time: 400 }) 90 orbmc.add(orbPress) 91 orbmc.on('press', (e) => { 92 e.stopPropagation() 93 this.stackTap() 94 }) 95 96 let prevel = this.$refs.previous 97 if(!prevel) return 98 let prevmc = Propagating(new Hammer.Manager(prevel)) 99 100 let prevTap = new Hammer.Tap({ time: 400 }) 101 prevmc.add(prevTap) 102 prevmc.on('tap', (e) => { 103 this.previous() 104 e.stopPropagation() 105 }) 106 107 let prevPress = new Hammer.Press({ time: 400 }) 108 prevmc.add(prevPress) 109 prevmc.on('press', (e) => { 110 111 this.first() 112 e.stopPropagation() 113 }) 114 115 let nextel = this.$refs.next 116 if(!nextel) return 117 let nextmc = Propagating(new Hammer.Manager(nextel)) 118 119 let nextTap = new Hammer.Tap({ time: 400 }) 120 nextmc.add(nextTap) 121 nextmc.on('tap', (e) => { 122 this.next() 123 e.stopPropagation() 124 }) 125 126 let nextPress = new Hammer.Press({ time: 400 }) 127 nextmc.add(nextPress) 128 nextmc.on('press', (e) => { 129 130 this.last() 131 e.stopPropagation() 132 }) 133 134 }, 135 data(){ 136 return { 137 orbuuid: crypto.randomUUID(), 138 componentKey: 0, 139 dropping: false, 140 } 141 }, 142 methods:{ 143 dragStart(ev){ 144 ev.dataTransfer.setData("taskId", this.c.map(t => t.taskId)) 145 }, 146 stackTap(){ 147 if (this.c.length > 1){ 148 this.toggleOpen() 149 } 150 this.$store.commit('setColor', this.stack) 151 }, 152 dragLeave(){ 153 this.dropping = false 154 }, 155 allowDrop(ev){ 156 ev.preventDefault() 157 this.dropping = true 158 }, 159 drop(ev){ 160 ev.preventDefault(); 161 var data = ev.dataTransfer.getData("taskId") 162 this.$store.commit('rollStackPull', data) 163 this.$store.dispatch("makeEvent", { 164 type: 'task-colored', 165 inId: this.$store.getters.contextCard.taskId, 166 taskId: data, 167 color: this.stack 168 }) 169 setTimeout(() => this.dropping = false, 444) 170 }, 171 toggleOpen(){ 172 this.$store.commit('setColor', this.stack) 173 if (this.position !== -1){ 174 let touchyOpen = { 175 type: 'task-touched', 176 taskId: this.$store.getters.contextCard.taskId, 177 stack: this.stack, 178 position: -1 179 } 180 this.$store.dispatch("makeEvent", touchyOpen) 181 this.$store.commit("applyEvent", touchyOpen) 182 } else { 183 this.first() 184 } 185 }, 186 first() { 187 let touchyTop = { 188 type: 'task-touched', 189 taskId: this.$store.getters.contextCard.taskId, 190 stack: this.stack, 191 position: 0 192 } 193 this.$store.dispatch("makeEvent", touchyTop) 194 this.$store.commit("applyEvent", touchyTop) 195 196 }, 197 previous(){ 198 if (this.position <= 0){ 199 return this.last() 200 } 201 let touchyBack = { 202 type: 'task-touched', 203 taskId: this.$store.getters.contextCard.taskId, 204 stack: this.stack, 205 position:this.sanePosition - 1, 206 } 207 this.$store.dispatch("makeEvent", touchyBack) 208 this.$store.commit("applyEvent", touchyBack) 209 }, 210 next(){ 211 if (this.position + 1 >= this.c.length){ 212 return this.first() 213 } 214 let touchyForward = { 215 type: 'task-touched', 216 taskId: this.$store.getters.contextCard.taskId, 217 stack: this.stack, 218 position: this.sanePosition + 1 219 } 220 221 this.$store.dispatch("makeEvent", touchyForward) 222 this.$store.commit("applyEvent", touchyForward) 223 }, 224 last() { 225 let touchyLast = { 226 type: 'task-touched', 227 taskId: this.$store.getters.contextCard.taskId, 228 stack: this.stack, 229 position: this.c.length - 1 230 } 231 this.$store.dispatch("makeEvent", touchyLast) 232 this.$store.commit("applyEvent", touchyLast) 233 }, 234 orbswap(swapId1){ 235 let swapId2 = this.panelIds[ this.panelIds.indexOf(swapId1) - 1 ] 236 let touchyOrby = { 237 type: 'task-swapped', 238 taskId: this.taskId, 239 swapId1, 240 swapId2, 241 } 242 this.$store.dispatch("makeEvent", touchyOrby) 243 this.$store.commit("applyEvent", touchyOrby) // causes doubleback 244 245 }, 246 swap(direction){ 247 let cardIndex 248 this.c.forEach((t, i) => { 249 if(t.taskId === this.topCard.taskId) { 250 cardIndex = i 251 } 252 }) 253 let swapIndex = (cardIndex + direction) % this.c.length 254 if (swapIndex === -1) { 255 swapIndex = this.c.length - 1 256 } else if (swapIndex > this.c.length - 1) { 257 swapIndex = 0 258 } 259 let touchySwap = { 260 type: 'task-swapped', 261 taskId: this.taskId, 262 swapId1: this.topCard.taskId, 263 swapId2: this.c[swapIndex].taskId, 264 } 265 this.$store.dispatch("makeEvent", touchySwap) 266 this.$store.commit("applyEvent", touchySwap) // causes doubleback 267 268 }, 269 }, 270 computed: { 271 sanePosition(){ 272 return Math.min(Math.max(this.position, -1), this.c.length - 1) 273 }, 274 c(){ 275 let c = this.$store.getters[this.stack] 276 if (!c){ 277 return [] 278 } 279 return c 280 }, 281 open(){ 282 return this.sanePosition === -1 283 }, 284 topCard(){ 285 let end = this.c.length - 1 286 if (!this.c || end < 0){ 287 console.log('no top?') 288 return false 289 } else{ 290 return this.c[this.sanePosition] 291 } 292 }, 293 panelIds() { 294 return this.c.map(g => g.taskId) 295 } 296 }, 297 components:{ 298 Hypercard, 299 }, 300 } 301 302 </script> 303 304 <style lang="stylus" scoped> 305 306 @import '../styles/colours' 307 @import '../styles/button' 308 @import '../styles/donut' 309 310 .oodd 311 float: right 312 position: relative 313 margin-bottom:-5em 314 display: none; 315 width: 100% 316 317 318 .dot 319 font-size: 1.9em 320 color: softGrey 321 z-index: 1 322 content-align: center 323 text-align: center 324 padding-top: 0.3em 325 326 .dot:before 327 content: "\2022" 328 329 .piledrop 330 min-height: 7.987em 331 332 .orby 333 height: 2.72em 334 margin-top: -0.41em 335 margin-bottom: -0.41em 336 cursor: pointer 337 .orby .donut 338 position: relative; 339 left: 33% 340 341 #tasks 342 width: 100% 343 344 .spaceroom 345 height:2.9em 346 347 .ptr 348 cursor: pointer 349 width: 100% 350 margin: 0 351 margin-bottom: -.6em 352 margin-bottom: -.6em; 353 display: flex 354 355 .box 356 min-height: 1em 357 358 .center 359 text-align: center 360 361 .hidden 362 opacity: 0 363 364 .third 365 flex-grow: 1 366 text-align: center 367 .third .donut 368 position: relative; 369 left: calc(50% - 1.7em) 370 371 .fixedstatus 372 color: lightGrey 373 pointer-events: none; 374 opacity: 0.5; 375 font-size: 0.81em; 376 text-align: center 377 position: absolute 378 padding-bottom: 1.5em; 379 height: 0; 380 position: relative; 381 top: -2.7em; 382 .donut.pileselected 383 border-color: lightGrey 384 385 .donut.pileopen 386 border-bottom-style: none 387 388 .donut.dropping 389 border-color: blue 390 391 </style>