/ src / components / Stack.vue
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>