smooth moves
This commit is contained in:
parent
413aa0f63c
commit
ea1e1a91a3
7 changed files with 159 additions and 3 deletions
19
routes/api/index.js
Normal file
19
routes/api/index.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
const verifyAuth = require('../../middlewares/verifyAuth');
|
||||||
|
const express = require('express');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = ({ db, config }) => {
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.use(verifyAuth())
|
||||||
|
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.send({
|
||||||
|
api: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
router.use('/wishlist', require('./wishlist')({ db }));
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
42
routes/api/wishlist/index.js
Normal file
42
routes/api/wishlist/index.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
const verifyAuth = require('../../../middlewares/verifyAuth')
|
||||||
|
const express = require('express')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = ({ db, config }) => {
|
||||||
|
const router = express.Router()
|
||||||
|
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.send({
|
||||||
|
route: 'wishlist'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post('/:user/:id/move/:direction', async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (req.user._id !== req.params.user) return res.json({ error: 'Not correct user' })
|
||||||
|
const doc = await db.get(req.user._id)
|
||||||
|
const wishlist = doc.wishlist
|
||||||
|
if (req.params.direction === 'up') wishlist.reverse()
|
||||||
|
let moveFromIndex
|
||||||
|
wishlist.forEach(wish => {
|
||||||
|
if (wish.id === req.params.id) return moveFromIndex = wishlist.indexOf(wish)
|
||||||
|
})
|
||||||
|
const moveToIndex = wishlist.findIndex(wish => {
|
||||||
|
return ( wishlist.indexOf(wish) > moveFromIndex && wish.addedBy === req.user._id )
|
||||||
|
})
|
||||||
|
if (moveToIndex < 0 || moveToIndex > wishlist.length) return res.send({ error: 'Invalid move '})
|
||||||
|
const original = wishlist[moveToIndex]
|
||||||
|
wishlist[moveToIndex] = wishlist[moveFromIndex]
|
||||||
|
wishlist[moveFromIndex] = original
|
||||||
|
if (req.params.direction === 'up') wishlist.reverse()
|
||||||
|
doc.wishlist = wishlist
|
||||||
|
await db.put(doc)
|
||||||
|
res.send({ error: false })
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
res.send({ error: error.message })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
|
@ -22,6 +22,8 @@ module.exports = ({ db, config }) => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.use('/api', require('./api')({ db }))
|
||||||
|
|
||||||
router.use('/setup', require('./setup')(db));
|
router.use('/setup', require('./setup')(db));
|
||||||
|
|
||||||
router.use('/login', require('./login')());
|
router.use('/login', require('./login')());
|
||||||
|
|
78
static/js/wishlist.js
Normal file
78
static/js/wishlist.js
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
function animateCSS(node, animationName) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
node.classList.add('animated', animationName)
|
||||||
|
|
||||||
|
function handleAnimationEnd() {
|
||||||
|
node.classList.remove('animated', animationName)
|
||||||
|
node.removeEventListener('animationend', handleAnimationEnd)
|
||||||
|
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
node.addEventListener('animationend', handleAnimationEnd)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// These move function are stolen from
|
||||||
|
// https://stackoverflow.com/a/34914096
|
||||||
|
function moveUp(element) {
|
||||||
|
if(element.previousElementSibling)
|
||||||
|
element.parentNode.insertBefore(element, element.previousElementSibling);
|
||||||
|
}
|
||||||
|
function moveDown(element) {
|
||||||
|
if(element.nextElementSibling)
|
||||||
|
element.parentNode.insertBefore(element.nextElementSibling, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function listen(element, upOrDown) {
|
||||||
|
element.addEventListener('submit', async event => {
|
||||||
|
try {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
const tr = event.currentTarget.parentElement.parentElement
|
||||||
|
const otherTr = upOrDown === 'up' ? tr.previousSibling : tr.nextSibling
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
animateCSS(tr, 'zoomOut'),
|
||||||
|
animateCSS(otherTr, 'zoomOut')
|
||||||
|
])
|
||||||
|
|
||||||
|
tr.style.visibility = 'hidden'
|
||||||
|
otherTr.style.visibility = 'hidden'
|
||||||
|
|
||||||
|
const data = await fetch(`/api/wishlist/${document.querySelector('[type="data/user_id"]').textContent}/${tr.id}/move/${upOrDown}`, {
|
||||||
|
method: 'post',
|
||||||
|
credentials: 'include'
|
||||||
|
})
|
||||||
|
.then(res => res.json())
|
||||||
|
|
||||||
|
if (data.error) throw new Error(data.error)
|
||||||
|
|
||||||
|
upOrDown === 'up' ? moveUp(tr) : moveDown(tr)
|
||||||
|
|
||||||
|
for (const tr of document.querySelector('tbody').children) {
|
||||||
|
tr.querySelector('.upForm > div > div > button').disabled = !tr.previousElementSibling
|
||||||
|
tr.querySelector('.downForm > div > div > button').disabled = !tr.nextElementSibling
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.style.visibility = 'visible'
|
||||||
|
otherTr.style.visibility = 'visible'
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
animateCSS(tr, 'zoomIn'),
|
||||||
|
animateCSS(otherTr, 'zoomIn')
|
||||||
|
])
|
||||||
|
|
||||||
|
return false
|
||||||
|
} catch (error) {
|
||||||
|
alert(error.message)
|
||||||
|
throw error
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
document.querySelectorAll('.upForm').forEach(element => listen(element, 'up'))
|
||||||
|
document.querySelectorAll('.downForm').forEach(element => listen(element, 'down'))
|
||||||
|
}, 0)
|
11
static/libraries/animate.min.css
vendored
Normal file
11
static/libraries/animate.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -17,9 +17,11 @@ html(lang='en')
|
||||||
href='https://use.fontawesome.com/releases/v5.5.0/css/all.css',
|
href='https://use.fontawesome.com/releases/v5.5.0/css/all.css',
|
||||||
crossorigin='anonymous'
|
crossorigin='anonymous'
|
||||||
)
|
)
|
||||||
|
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css')
|
||||||
else
|
else
|
||||||
link(rel='stylesheet', href='/libraries/bulma.min.css')
|
link(rel='stylesheet', href='/libraries/bulma.min.css')
|
||||||
link(rel='stylesheet', href='/libraries/fontawesome/css/all.css')
|
link(rel='stylesheet', href='/libraries/fontawesome/css/all.css')
|
||||||
|
link(rel='stylesheet', href='/libraries/animate.min.css')
|
||||||
link(rel='stylesheet', href='/css/main.css')
|
link(rel='stylesheet', href='/css/main.css')
|
||||||
body
|
body
|
||||||
include includes/navbar.pug
|
include includes/navbar.pug
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
extends layout.pug
|
extends layout.pug
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
script(type='data/user_id')= req.user._id
|
||||||
if process.env.TABLE !== 'false'
|
if process.env.TABLE !== 'false'
|
||||||
.box
|
.box
|
||||||
table.table.has-mobile-cards
|
table.table.has-mobile-cards
|
||||||
|
@ -18,7 +19,7 @@ block content
|
||||||
tbody
|
tbody
|
||||||
each item, index in wishlist
|
each item, index in wishlist
|
||||||
if req.user._id === item.addedBy || req.params.user !== req.user._id
|
if req.user._id === item.addedBy || req.params.user !== req.user._id
|
||||||
tr
|
tr(id=item.id)
|
||||||
if item.url
|
if item.url
|
||||||
td.ugc(data-label='Name')
|
td.ugc(data-label='Name')
|
||||||
a(
|
a(
|
||||||
|
@ -44,7 +45,7 @@ block content
|
||||||
td.ugc(data-label='Added By')= item.addedBy
|
td.ugc(data-label='Added By')= item.addedBy
|
||||||
if req.params.user === req.user._id
|
if req.params.user === req.user._id
|
||||||
td(data-label='Move Item Up')
|
td(data-label='Move Item Up')
|
||||||
form.inline(method='POST', action=`/wishlist/${req.params.user}/move/up/${item.id}`)
|
form.upForm.inline(method='POST', action=`/wishlist/${req.params.user}/move/up/${item.id}`)
|
||||||
.field.inline
|
.field.inline
|
||||||
.control.inline
|
.control.inline
|
||||||
button.button.is-text(
|
button.button.is-text(
|
||||||
|
@ -55,7 +56,7 @@ block content
|
||||||
span.icon
|
span.icon
|
||||||
i.fas.fa-arrow-up
|
i.fas.fa-arrow-up
|
||||||
td(data-label='Move Item Down')
|
td(data-label='Move Item Down')
|
||||||
form.inline(method='POST', action=`/wishlist/${req.params.user}/move/down/${item.id}`)
|
form.downForm.inline(method='POST', action=`/wishlist/${req.params.user}/move/down/${item.id}`)
|
||||||
.field.inline
|
.field.inline
|
||||||
.control.inline
|
.control.inline
|
||||||
button.button.is-text(
|
button.button.is-text(
|
||||||
|
@ -173,3 +174,4 @@ block content
|
||||||
.field
|
.field
|
||||||
.control
|
.control
|
||||||
input.button(type='submit' value=(req.user._id === req.params.user ? 'Add item to wishlist' : 'Pledge item'))
|
input.button(type='submit' value=(req.user._id === req.params.user ? 'Add item to wishlist' : 'Pledge item'))
|
||||||
|
script(src='/js/wishlist.js')
|
Loading…
Reference in a new issue