Browse Source

albums sidebar in dashboard is now collapsible

they'll also be collapsed on initial page load

this uses a new client-side dependency, bulma-collapsible
https://github.com/creativebulma/bulma-collapsible

/api/albums to fetch albums list now support simple reply, where only
their ids and names will be returned.
this simple reply will also return all of the user's albums, instead of
being limited to only 9 or 25 entires like before.

fixed add to album in dashboard, and album selector in homepage uploader
being limited to only 25 albums.
master
Bobby Wibowo 10 months ago
parent
commit
c5647cb8bf
No known key found for this signature in database GPG Key ID: 51C3A1E1E22D26CF
  1. 5
      controllers/albumsController.js
  2. 21
      public/libs/bulma-collapsible/LICENSE
  3. 1
      public/libs/bulma-collapsible/bulma-collapsible.min.css
  4. 1
      public/libs/bulma-collapsible/bulma-collapsible.min.js
  5. 11
      src/css/dashboard.scss
  6. 58
      src/js/dashboard.js
  7. 7
      src/js/home.js
  8. 2
      src/js/player.js
  9. 7
      views/dashboard.njk

5
controllers/albumsController.js

@ -73,7 +73,7 @@ self.list = async (req, res, next) => {
if (!user) return
const all = req.headers.all === '1'
const sidebar = req.headers.sidebar
const simple = req.headers.simple
const ismoderator = perms.is(user, 'moderator')
if (all && !ismoderator) return res.status(403).end()
@ -97,10 +97,9 @@ self.list = async (req, res, next) => {
const fields = ['id', 'name']
let albums
if (sidebar) {
if (simple) {
albums = await db.table('albums')
.where(filter)
.limit(9)
.select(fields)
return res.json({ success: true, albums, count })

21
public/libs/bulma-collapsible/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Wikiki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1
public/libs/bulma-collapsible/bulma-collapsible.min.css

@ -0,0 +1 @@
@-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.is-collapsible{height:0;overflow-y:hidden;transition:height .2s ease}.is-collapsible.is-active{transition:height .2s ease}.is-collapsible.message-body{padding:0!important}.is-collapsible.message-body .message-body-content{padding:1.25em 1.5em}

1
public/libs/bulma-collapsible/bulma-collapsible.min.js

File diff suppressed because one or more lines are too long

11
src/css/dashboard.scss

@ -20,7 +20,6 @@ body {
a {
color: $link;
border: 1px solid transparent;
margin-top: -1px;
&.is-active {
color: $white;
@ -53,6 +52,16 @@ body {
top: calc(50% - (1em / 2));
position: absolute !important
}
&.is-active[data-action="collapse"] {
color: $link !important;
background: none !important;
border-color: transparent !important;
&:hover {
border-color: $link !important
}
}
}
li ul {

58
src/js/dashboard.js

@ -1,4 +1,4 @@
/* global swal, axios, ClipboardJS, LazyLoad */
/* global swal, axios, ClipboardJS, LazyLoad, bulmaCollapsible */
const lsKeys = {
token: 'token',
@ -90,6 +90,8 @@ const page = {
clipboardJS: null,
lazyLoad: null,
albumsSidebarCollapse: null,
albumsSidebarCollapsible: null,
imageExts: ['.gif', '.jpeg', '.jpg', '.png', '.svg', '.tif', '.tiff', '.webp'],
videoExts: ['.3g2', '.3gp', '.asf', '.avchd', '.avi', '.divx', '.evo', '.flv', '.h264', '.h265', '.hevc', '.m2p', '.m2ts', '.m4v', '.mk3d', '.mkv', '.mov', '.mp4', '.mpeg', '.mpg', '.mxf', '.ogg', '.ogv', '.ps', '.qt', '.rmvb', '.ts', '.vob', '.webm', '.wmv'],
@ -1540,7 +1542,7 @@ page.addUploadsToAlbum = (ids, callback) => {
})
// Get albums list then update content of swal
axios.get('api/albums').then(list => {
axios.get('api/albums', { headers: { simple: '1' } }).then(list => {
if (list.data.success === false) {
if (list.data.description === 'No token provided') {
page.verifyToken(page.token)
@ -2040,7 +2042,7 @@ page.submitAlbum = element => {
}
page.getAlbumsSidebar = () => {
axios.get('api/albums', { headers: { sidebar: '1' } }).then(response => {
axios.get('api/albums', { headers: { simple: '1' } }).then(response => {
if (!response) return
if (response.data.success === false) {
@ -2053,18 +2055,27 @@ page.getAlbumsSidebar = () => {
const albums = response.data.albums
const count = response.data.count
const albumsContainer = document.querySelector('#albumsContainer')
const albumsSidebar = document.querySelector('#albumsSidebar')
// Clear albums sidebar if necessary
const oldAlbums = albumsContainer.querySelectorAll('li > a')
const oldAlbums = albumsSidebar.querySelectorAll('li > a')
const diffCount = oldAlbums.length !== count
if (oldAlbums.length) {
for (let i = 0; i < oldAlbums.length; i++) {
page.menus.splice(page.menus.indexOf(oldAlbums[i]), 1)
}
albumsContainer.innerHTML = ''
albumsSidebar.innerHTML = ''
}
if (albums === undefined) return
page.albumsSidebarCollapse.innerText = page.albumsSidebarCollapsible.collapsed()
? page.albumsSidebarCollapse.dataset.textExpand
: page.albumsSidebarCollapse.dataset.textCollapse
if (!albums || !albums.length) {
page.albumsSidebarCollapsible.collapse()
page.albumsSidebarCollapse.setAttribute('disabled', 'disabled')
return
}
for (let i = 0; i < albums.length; i++) {
const album = albums[i]
@ -2083,24 +2094,14 @@ page.getAlbumsSidebar = () => {
page.menus.push(a)
li.appendChild(a)
albumsContainer.appendChild(li)
albumsSidebar.appendChild(li)
}
if (count > albums.length) {
const li = document.createElement('li')
const a = document.createElement('a')
a.className = 'is-relative'
a.innerHTML = '...'
a.title = `You have ${count} albums, but the sidebar can only list your first ${albums.length} albums.`
a.addEventListener('click', event => {
page.getAlbums({
trigger: document.querySelector('#itemManageYourAlbums')
})
})
li.appendChild(a)
albumsContainer.appendChild(li)
page.albumsSidebarCollapse.removeAttribute('disabled')
if (!page.albumsSidebarCollapsible.collapsed() && diffCount) {
// Since it's not possible to refresh collapsible's height with bulmaCollapsible APIs,
// forcefully collapse albums sidebar if albums count is different with the previous iteration.
page.albumsSidebarCollapsible.collapse()
}
}).catch(page.onAxiosError)
}
@ -3010,4 +3011,15 @@ window.addEventListener('DOMContentLoaded', () => {
page.clipboardJS.on('error', page.onError)
page.lazyLoad = new LazyLoad()
page.albumsSidebarCollapse = document.querySelector('#albumsSidebarCollapse')
/* eslint-disable-next-line new-cap */
page.albumsSidebarCollapsible = new bulmaCollapsible(document.querySelector('#albumsSidebar'))
page.albumsSidebarCollapsible.on('before:expand', event => {
page.albumsSidebarCollapse.innerText = page.albumsSidebarCollapse.dataset.textCollapse
})
page.albumsSidebarCollapsible.on('before:collapse', event => {
page.albumsSidebarCollapse.innerText = page.albumsSidebarCollapse.dataset.textExpand
})
})

7
src/js/home.js

@ -314,7 +314,12 @@ page.setActiveTab = index => {
}
page.fetchAlbums = () => {
return axios.get('api/albums', { headers: { token: page.token } }).then(response => {
return axios.get('api/albums', {
headers: {
simple: '1',
token: page.token
}
}).then(response => {
if (response.data.success === false) {
return swal('An error occurred!', response.data.description, 'error')
}

2
src/js/player.js

@ -66,7 +66,7 @@ page.toggleReloadBtn = enabled => {
page.reloadBtn.removeAttribute('disabled')
} else {
page.reloadBtn.classList.add('is-loading')
page.reloadBtn.setAttribute('disabled', true)
page.reloadBtn.setAttribute('disabled', 'disabled')
}
}

7
views/dashboard.njk

@ -6,6 +6,7 @@
{% block stylesheets %}
<!-- Libs stylesheets -->
<link rel="stylesheet" href="libs/fontello/fontello.css{{ versions[1] }}">
<link rel="stylesheet" href="libs/bulma-collapsible/bulma-collapsible.min.css{{ versions[3] }}">
{{ super() }}
<link rel="stylesheet" href="css/sweetalert.css{{ versions[1] }}">
<link rel="stylesheet" href="css/thumbs.css{{ versions[1] }}">
@ -21,6 +22,7 @@
<script src="libs/lazyload/lazyload.min.js{{ versions[3] }}"></script>
{# Polyfill smooth scroll for older browsers #}
<script src="libs/smoothscroll/smoothscroll.min.js{{ versions[3] }}"></script>
<script src="libs/bulma-collapsible/bulma-collapsible.min.js{{ versions[3] }}"></script>
<!-- Scripts -->
{# We assign an ID for this so that the script can find out its own version #}
<script id="mainScript" src="js/dashboard.js{{ versions[1] }}"></script>
@ -64,7 +66,10 @@
<a id="itemManageYourAlbums" class="is-relative">Manage your albums</a>
</li>
<li>
<ul id="albumsContainer"></ul>
<a id="albumsSidebarCollapse" href="#albumsSidebar" data-action="collapse" data-text-collapse="Collapse albums sidebar" data-text-expand="Expand albums sidebar" disabled>Fetching albums sidebar…</a>
</li>
<li>
<ul id="albumsSidebar" class="is-collapsible"></ul>
</li>
</ul>
<p id="itemLabelAdmin" class="menu-label is-hidden">Administration</p>

Loading…
Cancel
Save