From fe10a00ba9a3c30d8718ca004ccd19518466f5bd Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Sun, 16 Sep 2018 01:09:02 -0300 Subject: Site --- src/site/store/index.js | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/site/store/index.js (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js new file mode 100644 index 0000000..3977093 --- /dev/null +++ b/src/site/store/index.js @@ -0,0 +1,51 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; + +Vue.use(Vuex); + +const state = { + loggedIn: false, + user: {}, + token: null, + config: null +}; + +/* eslint-disable no-shadow */ +const mutations = { + loggedIn(state, payload) { + state.loggedIn = payload; + }, + user(state, payload) { + if (!payload) { + state.user = {}; + localStorage.removeItem('ls-user'); + return; + } + localStorage.setItem('ls-user', JSON.stringify(payload)); + state.user = payload; + }, + token(state, payload) { + if (!payload) { + localStorage.removeItem('ls-token'); + state.token = null; + return; + } + localStorage.setItem('ls-token', payload); + setAuthorizationHeader(payload); + state.token = payload; + }, + config(state, payload) { + state.config = payload; + } +}; + +const setAuthorizationHeader = payload => { + Vue.axios.defaults.headers.common.Authorization = payload ? `Bearer ${payload}` : ''; +}; + +const store = new Vuex.Store({ + state, + mutations +}); + +export default store; -- cgit v1.2.3 From 430af8306b1ab17e59a6dabf8f65ab816d28695d Mon Sep 17 00:00:00 2001 From: Pitu Date: Wed, 19 Sep 2018 04:45:50 -0300 Subject: Switch to Nuxt.js --- src/site/store/index.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 3977093..a681fbe 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,8 +1,6 @@ import Vue from 'vue'; import Vuex from 'vuex'; -Vue.use(Vuex); - const state = { loggedIn: false, user: {}, @@ -18,19 +16,19 @@ const mutations = { user(state, payload) { if (!payload) { state.user = {}; - localStorage.removeItem('ls-user'); + localStorage.removeItem('lolisafe-user'); return; } - localStorage.setItem('ls-user', JSON.stringify(payload)); + localStorage.setItem('lolisafe-user', JSON.stringify(payload)); state.user = payload; }, token(state, payload) { if (!payload) { - localStorage.removeItem('ls-token'); + localStorage.removeItem('lolisafe-token'); state.token = null; return; } - localStorage.setItem('ls-token', payload); + localStorage.setItem('lolisafe-token', payload); setAuthorizationHeader(payload); state.token = payload; }, @@ -39,13 +37,22 @@ const mutations = { } }; +const actions = { + nuxtServerInit({ commit }, { req }) { + const config = require('~/config.js'); + commit('config', config); + } +}; + const setAuthorizationHeader = payload => { + console.log('hihi'); Vue.axios.defaults.headers.common.Authorization = payload ? `Bearer ${payload}` : ''; }; -const store = new Vuex.Store({ +const store = () => new Vuex.Store({ state, - mutations + mutations, + actions }); export default store; -- cgit v1.2.3 From 55e6c1f9cddf43bc2a5a9aa5f689f94ea2aab60e Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 19 Feb 2019 23:54:11 +0900 Subject: WIP --- src/site/store/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index a681fbe..74ecadf 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -39,6 +39,7 @@ const mutations = { const actions = { nuxtServerInit({ commit }, { req }) { + /* TODO: Get env variables from context/process */ const config = require('~/config.js'); commit('config', config); } -- cgit v1.2.3 From 48d18597234bed153e3cf10531fb283095b9738a Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 21 Feb 2019 23:49:44 +0900 Subject: Load enviroment variables into config --- src/site/store/index.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 74ecadf..7cd9e42 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -39,9 +39,15 @@ const mutations = { const actions = { nuxtServerInit({ commit }, { req }) { - /* TODO: Get env variables from context/process */ - const config = require('~/config.js'); - commit('config', config); + commit('config', { + version: process.env.npm_package_version, + URL: process.env.DOMAIN, + baseURL: `${process.env.DOMAIN}${process.env.ROUTE_PREFIX}`, + serviceName: process.env.SERVICE_NAME, + maxFileSize: process.env.MAX_SIZE, + chunkSize: process.env.CHUNK_SIZE, + maxLinksPerAlbum: process.env.MAX_LINKS_PER_ALBUM + }); } }; -- cgit v1.2.3 From 73d85e8c7938e1db30da3cc4354b143d4a078473 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 2 Mar 2019 02:08:11 +0900 Subject: Enviroment variables parsing fix --- src/site/store/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 7cd9e42..e96f10a 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -44,9 +44,11 @@ const actions = { URL: process.env.DOMAIN, baseURL: `${process.env.DOMAIN}${process.env.ROUTE_PREFIX}`, serviceName: process.env.SERVICE_NAME, - maxFileSize: process.env.MAX_SIZE, - chunkSize: process.env.CHUNK_SIZE, - maxLinksPerAlbum: process.env.MAX_LINKS_PER_ALBUM + maxFileSize: parseInt(process.env.MAX_SIZE, 10), + chunkSize: parseInt(process.env.CHUNK_SIZE, 10), + maxLinksPerAlbum: parseInt(process.env.MAX_LINKS_PER_ALBUM, 10), + publicMode: process.env.PUBLIC_MODE == 'true' ? true : false, + enableAccounts: process.env.USER_ACCOUNTS == 'true' ? true : false }); } }; -- cgit v1.2.3 From 3ce7657871bfe392d73ab67a6c1a8a10543e3d98 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 2 Mar 2019 22:36:28 +0900 Subject: wip --- src/site/store/index.js | 1 - 1 file changed, 1 deletion(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index e96f10a..194bff9 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -54,7 +54,6 @@ const actions = { }; const setAuthorizationHeader = payload => { - console.log('hihi'); Vue.axios.defaults.headers.common.Authorization = payload ? `Bearer ${payload}` : ''; }; -- cgit v1.2.3 From 2f063735d7877b5d5f703f2936b8756d8c9a7059 Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 12 Mar 2019 05:38:25 +0000 Subject: Changed store from deprecated mode --- src/site/store/index.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 194bff9..404eb1c 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,15 +1,15 @@ import Vue from 'vue'; import Vuex from 'vuex'; -const state = { +export const state = () => ({ loggedIn: false, user: {}, token: null, config: null -}; +}); /* eslint-disable no-shadow */ -const mutations = { +export const mutations = { loggedIn(state, payload) { state.loggedIn = payload; }, @@ -37,7 +37,7 @@ const mutations = { } }; -const actions = { +export const actions = { nuxtServerInit({ commit }, { req }) { commit('config', { version: process.env.npm_package_version, @@ -56,11 +56,3 @@ const actions = { const setAuthorizationHeader = payload => { Vue.axios.defaults.headers.common.Authorization = payload ? `Bearer ${payload}` : ''; }; - -const store = () => new Vuex.Store({ - state, - mutations, - actions -}); - -export default store; -- cgit v1.2.3 From 088ffe175ebe0f0733127c0003ebbdaa850feaf9 Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 15 Mar 2019 07:17:27 +0000 Subject: =?UTF-8?q?This=20should=20fix=20credential=20leaking=20?= =?UTF-8?q?=F0=9F=98=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/site/store/index.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 404eb1c..57a036e 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,9 +1,11 @@ import Vue from 'vue'; -import Vuex from 'vuex'; +import axios from 'axios'; + +const cookieparser = process.server ? require('cookieparser') : null; export const state = () => ({ loggedIn: false, - user: {}, + user: null, token: null, config: null }); @@ -38,7 +40,7 @@ export const mutations = { }; export const actions = { - nuxtServerInit({ commit }, { req }) { + async nuxtServerInit({ commit }, { req }) { commit('config', { version: process.env.npm_package_version, URL: process.env.DOMAIN, @@ -50,6 +52,27 @@ export const actions = { publicMode: process.env.PUBLIC_MODE == 'true' ? true : false, enableAccounts: process.env.USER_ACCOUNTS == 'true' ? true : false }); + + let token = null; + if (req.headers.cookie) { + try { + token = cookieparser.parse(req.headers.cookie).token; + commit('loggedIn', true); + commit('token', token); + + const res = await axios.get(`${this.config.baseURL}/verify`); + if (!res || !res.data.user); + commit('user', res.data.user); + } catch (error) { + // TODO: Deactivate this on production + console.error(error); + } + } + commit('token', token); + if (!token) { + commit('user', null); + commit('loggedIn', false); + } } }; -- cgit v1.2.3 From dfaeb1051faf54687e8c4a2bdacabbc65558084f Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 15 Mar 2019 07:25:05 +0000 Subject: yeah --- src/site/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 57a036e..63f3feb 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import axios from 'axios'; -const cookieparser = process.server ? require('cookieparser') : null; +const cookieparser = process.server ? require('cookie-parser') : null; export const state = () => ({ loggedIn: false, -- cgit v1.2.3 From a142078f64027eba52c6e422eab34533f2bd09bb Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 15 Mar 2019 07:30:58 +0000 Subject: No need for this --- src/site/store/index.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 63f3feb..19ab0ae 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -17,20 +17,16 @@ export const mutations = { }, user(state, payload) { if (!payload) { - state.user = {}; - localStorage.removeItem('lolisafe-user'); + state.user = null; return; } - localStorage.setItem('lolisafe-user', JSON.stringify(payload)); state.user = payload; }, token(state, payload) { if (!payload) { - localStorage.removeItem('lolisafe-token'); state.token = null; return; } - localStorage.setItem('lolisafe-token', payload); setAuthorizationHeader(payload); state.token = payload; }, -- cgit v1.2.3 From d7745aff40104c8b7104f6a56ff8d7a9186dc10d Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 15 Mar 2019 07:34:19 +0000 Subject: Turns out we were using the wrong cookieparser --- src/site/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 19ab0ae..6a05622 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import axios from 'axios'; -const cookieparser = process.server ? require('cookie-parser') : null; +const cookieparser = process.server ? require('cookieparser') : null; export const state = () => ({ loggedIn: false, -- cgit v1.2.3 From 19e79365adf33d5031a68f85933051fc4fea046d Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 15 Mar 2019 07:52:33 +0000 Subject: proper baseurl --- src/site/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 6a05622..3c43f53 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -56,7 +56,7 @@ export const actions = { commit('loggedIn', true); commit('token', token); - const res = await axios.get(`${this.config.baseURL}/verify`); + const res = await axios.get(`${process.env.DOMAIN}${process.env.ROUTE_PREFIX}/verify`); if (!res || !res.data.user); commit('user', res.data.user); } catch (error) { -- cgit v1.2.3 From 107d1f4750e8f82a628b528c4ec200e918be271d Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 19 Mar 2019 07:58:36 +0000 Subject: API key WIP --- src/site/store/index.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 3c43f53..2f83f63 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -53,12 +53,13 @@ export const actions = { if (req.headers.cookie) { try { token = cookieparser.parse(req.headers.cookie).token; + console.log(token); commit('loggedIn', true); commit('token', token); - - const res = await axios.get(`${process.env.DOMAIN}${process.env.ROUTE_PREFIX}/verify`); - if (!res || !res.data.user); - commit('user', res.data.user); + const res = await axios.get(`${process.env.DOMAIN}${process.env.ROUTE_PREFIX}/verify`, { + headers: { authorization: `Bearer ${token}` } + }); + if (res && res.data.user) commit('user', res.data.user); } catch (error) { // TODO: Deactivate this on production console.error(error); -- cgit v1.2.3 From 8905f2e7a7096e8567e1d1871af62f0842303dfc Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 29 Mar 2019 00:35:22 +0900 Subject: Added axios package --- src/site/store/index.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 6a05622..13e49c3 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,5 +1,7 @@ +/* import Vue from 'vue'; import axios from 'axios'; +*/ const cookieparser = process.server ? require('cookieparser') : null; @@ -27,7 +29,6 @@ export const mutations = { state.token = null; return; } - setAuthorizationHeader(payload); state.token = payload; }, config(state, payload) { @@ -36,7 +37,7 @@ export const mutations = { }; export const actions = { - async nuxtServerInit({ commit }, { req }) { + async nuxtServerInit({ commit }, { app, req }) { commit('config', { version: process.env.npm_package_version, URL: process.env.DOMAIN, @@ -56,9 +57,11 @@ export const actions = { commit('loggedIn', true); commit('token', token); - const res = await axios.get(`${this.config.baseURL}/verify`); - if (!res || !res.data.user); - commit('user', res.data.user); + app.$axios.setToken(token, 'Bearer'); + + const data = await this.$axios.$get(`verify`); + if (!data || !data.user); + commit('user', data.user); } catch (error) { // TODO: Deactivate this on production console.error(error); @@ -69,9 +72,10 @@ export const actions = { commit('user', null); commit('loggedIn', false); } + }, + login({ commit }, { app, token, user }) { + commit('token', token); + commit('user', user); + commit('loggedIn', true); } }; - -const setAuthorizationHeader = payload => { - Vue.axios.defaults.headers.common.Authorization = payload ? `Bearer ${payload}` : ''; -}; -- cgit v1.2.3 From c4d803c4f6fec98bed6bec3680e5a28963c27488 Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 29 Mar 2019 03:27:52 +0000 Subject: Make sure to remove the token to prevent credential leak --- src/site/store/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index a4a0d51..a9380b7 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -70,6 +70,7 @@ export const actions = { } commit('token', token); if (!token) { + app.$axios.setToken(''); commit('user', null); commit('loggedIn', false); } -- cgit v1.2.3 From ab0839f1f50fcb477476871ca267a004c8fd35e4 Mon Sep 17 00:00:00 2001 From: Pitu Date: Wed, 24 Apr 2019 08:36:47 +0000 Subject: Globally catch exceptions --- src/site/store/index.js | 72 ++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 40 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index a9380b7..80c6a9a 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,15 +1,9 @@ -/* -import Vue from 'vue'; -import axios from 'axios'; -*/ - -const cookieparser = process.server ? require('cookieparser') : null; - export const state = () => ({ loggedIn: false, user: null, token: null, - config: null + config: null, + alert: null }); /* eslint-disable no-shadow */ @@ -18,26 +12,21 @@ export const mutations = { state.loggedIn = payload; }, user(state, payload) { - if (!payload) { - state.user = null; - return; - } state.user = payload; }, token(state, payload) { - if (!payload) { - state.token = null; - return; - } state.token = payload; }, config(state, payload) { state.config = payload; + }, + alert(state, payload) { + state.alert = payload; } }; export const actions = { - async nuxtServerInit({ commit }, { app, req }) { + async nuxtServerInit({ commit, dispatch }, { app, req }) { commit('config', { version: process.env.npm_package_version, URL: process.env.DOMAIN, @@ -50,34 +39,37 @@ export const actions = { enableAccounts: process.env.USER_ACCOUNTS == 'true' ? true : false }); - let token = null; - if (req.headers.cookie) { - try { - token = cookieparser.parse(req.headers.cookie).token; - console.log(token); - commit('loggedIn', true); - commit('token', token); - - app.$axios.setToken(token, 'Bearer'); + const cookies = this.$cookies.getAll(); + if (!cookies.token) return dispatch('logout'); - const data = await this.$axios.$get(`verify`); - if (!data || !data.user); - commit('user', data.user); - } catch (error) { - // TODO: Deactivate this on production - console.error(error); - } - } - commit('token', token); - if (!token) { - app.$axios.setToken(''); - commit('user', null); - commit('loggedIn', false); + commit('token', cookies.token); + try { + const response = await this.$axios.$get('verify'); + dispatch('login', { + token: cookies.token, + user: response.user + }); + } catch (error) { + dispatch('logout'); } }, - login({ commit }, { app, token, user }) { + login({ commit }, { token, user }) { + this.$cookies.set('token', token); commit('token', token); commit('user', user); commit('loggedIn', true); + }, + logout({ commit }) { + this.$cookies.remove('token'); + commit('token', null); + commit('user', null); + commit('loggedIn', false); + }, + alert({ commit }, payload) { + if (!payload) return commit('alert', null); + commit('alert', { + text: payload.text, + error: payload.error + }); } }; -- cgit v1.2.3 From 4e4b4ea4680d915c65487e7169bc93f17db3bf96 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 12 Oct 2019 22:59:56 +0900 Subject: don't log out on API error --- src/site/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index 80c6a9a..cf3650f 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -50,7 +50,7 @@ export const actions = { user: response.user }); } catch (error) { - dispatch('logout'); + // dispatch('logout'); } }, login({ commit }, { token, user }) { -- cgit v1.2.3 From c114e59be329fa9ceb8f1f8e79356a0e3afbd1ae Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 9 May 2020 19:21:20 +0900 Subject: Feature: * Frontend is now served by the API process * Only 1 process spawns for lolisafe to work * Switched frontend from server-side render to static site, now saved in `/dist` --- src/site/store/index.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/index.js b/src/site/store/index.js index cf3650f..1fc2272 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,3 +1,4 @@ +import config from '../../../dist/config.json'; export const state = () => ({ loggedIn: false, user: null, @@ -26,18 +27,8 @@ export const mutations = { }; export const actions = { - async nuxtServerInit({ commit, dispatch }, { app, req }) { - commit('config', { - version: process.env.npm_package_version, - URL: process.env.DOMAIN, - baseURL: `${process.env.DOMAIN}${process.env.ROUTE_PREFIX}`, - serviceName: process.env.SERVICE_NAME, - maxFileSize: parseInt(process.env.MAX_SIZE, 10), - chunkSize: parseInt(process.env.CHUNK_SIZE, 10), - maxLinksPerAlbum: parseInt(process.env.MAX_LINKS_PER_ALBUM, 10), - publicMode: process.env.PUBLIC_MODE == 'true' ? true : false, - enableAccounts: process.env.USER_ACCOUNTS == 'true' ? true : false - }); + async nuxtClientInit({ commit, dispatch }, { app, req }) { + commit('config', config); const cookies = this.$cookies.getAll(); if (!cookies.token) return dispatch('logout'); -- cgit v1.2.3 From 720ffaf0083564c85a07d66a6d303f34706add41 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 2 Jul 2020 02:50:55 +0300 Subject: feat: start refactoring the code to actually use vuex This includes creating multiple stores as needed for components and removing all complex states from components (since all those states should be stored in vuex) --- src/site/store/alert.js | 26 ++++++++++++++++++++ src/site/store/auth.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++ src/site/store/config.js | 19 +++++++++++++++ src/site/store/images.js | 56 +++++++++++++++++++++++++++++++++++++++++++ src/site/store/index.js | 62 +++++++----------------------------------------- 5 files changed, 170 insertions(+), 54 deletions(-) create mode 100644 src/site/store/alert.js create mode 100644 src/site/store/auth.js create mode 100644 src/site/store/config.js create mode 100644 src/site/store/images.js (limited to 'src/site/store') diff --git a/src/site/store/alert.js b/src/site/store/alert.js new file mode 100644 index 0000000..78c0eaf --- /dev/null +++ b/src/site/store/alert.js @@ -0,0 +1,26 @@ +/* eslint-disable no-shadow */ +const getDefaultState = () => ({ + text: null, + error: false +}); + +export const state = getDefaultState; + +export const actions = { + set({ commit }, data) { + commit('set', data); + }, + clear({ commit }) { + commit('clear'); + } +}; + +export const mutations = { + set(state, { text, error }) { + state.text = text; + state.error = error; + }, + clear(state) { + Object.assign(state, getDefaultState()); + } +}; diff --git a/src/site/store/auth.js b/src/site/store/auth.js new file mode 100644 index 0000000..a62a6ec --- /dev/null +++ b/src/site/store/auth.js @@ -0,0 +1,61 @@ +/* eslint-disable no-shadow */ +// only used so I could keep the convention of naming the first param as "state" in mutations +const getDefaultState = () => ({ + loggedIn: false, + isLoading: false, + user: null, + token: null +}); + +export const state = getDefaultState; + +export const getters = { + isLoggedIn: state => state.loggedIn +}; + +export const actions = { + async verify({ commit, dispatch }) { + try { + const response = await this.$axios.$get('verify'); + commit('loginSuccess', response); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async login({ commit, dispatch }, { username, password }) { + commit('loginRequest'); + + try { + const data = await this.$axios.$post(`auth/login`, { username, password }); + this.$axios.setToken(data.token, 'Bearer'); + + commit('setToken', data.token); + commit('loginSuccess', { token: data.token, user: data.user }); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + logout({ commit }) { + commit('logout'); + } +}; + +export const mutations = { + setToken(state, token) { + state.token = token; + }, + loginRequest(state) { + state.isLoading = true; + }, + loginSuccess(state, { user }) { + this.$cookies.set('token', state.token); + state.user = user; + state.loggedIn = true; + state.isLoading = false; + }, + logout(state) { + this.$cookies.remove('token'); + // reset state to default + Object.assign(state, getDefaultState()); + } +}; diff --git a/src/site/store/config.js b/src/site/store/config.js new file mode 100644 index 0000000..6202f84 --- /dev/null +++ b/src/site/store/config.js @@ -0,0 +1,19 @@ +/* eslint-disable no-shadow */ +export const state = () => ({ + development: true, + version: '4.0.0', + URL: 'http://localhost:8080', + baseURL: 'http://localhost:8080/api', + serviceName: '', + maxFileSize: 100, + chunkSize: 90, + maxLinksPerAlbum: 5, + publicMode: false, + userAccounts: false +}); + +export const mutations = { + set(state, config) { + Object.assign(state, config); + } +}; diff --git a/src/site/store/images.js b/src/site/store/images.js new file mode 100644 index 0000000..e87dac1 --- /dev/null +++ b/src/site/store/images.js @@ -0,0 +1,56 @@ +/* eslint-disable no-shadow */ +export const state = () => ({ + files: [], + isLoading: false, + pagination: { + page: 1, + limit: 30, + totalFiles: 0 + } +}); + +export const getters = { + getTotalFiles: state => state.pagination.totalFiles, + getFetchedCount: state => state.files.length, + shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, + getLimit: ({ pagination }) => pagination.limit +}; + +export const actions = { + async fetch({ commit, dispatch, state }, page) { + commit('setIsLoading'); + + page = page || 1; + + try { + const response = await this.$axios.$get(`files`, { params: { limit: state.pagination.limit, page } }); + + commit('updateFiles', { files: response.files }); + commit('updatePaginationMeta', { totalFiles: response.count, page }); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async fetchById({ commit, dispatch }) { + try { + const response = await this.$axios.$get('verify'); + commit('loginSuccess', response); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + } +}; + +export const mutations = { + setIsLoading(state) { + state.isLoading = true; + }, + updateFiles(state, { files }) { + state.files = files || []; + state.isLoading = false; + }, + updatePaginationMeta(state, { page, totalFiles }) { + state.pagination.page = page || 1; + state.pagination.totalFiles = totalFiles || 0; + } +}; diff --git a/src/site/store/index.js b/src/site/store/index.js index 1fc2272..8f910ae 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,66 +1,20 @@ import config from '../../../dist/config.json'; -export const state = () => ({ - loggedIn: false, - user: null, - token: null, - config: null, - alert: null -}); - -/* eslint-disable no-shadow */ -export const mutations = { - loggedIn(state, payload) { - state.loggedIn = payload; - }, - user(state, payload) { - state.user = payload; - }, - token(state, payload) { - state.token = payload; - }, - config(state, payload) { - state.config = payload; - }, - alert(state, payload) { - state.alert = payload; - } -}; export const actions = { - async nuxtClientInit({ commit, dispatch }, { app, req }) { - commit('config', config); + async nuxtClientInit({ commit, dispatch }) { + commit('config/set', config); const cookies = this.$cookies.getAll(); - if (!cookies.token) return dispatch('logout'); + if (!cookies.token) return dispatch('auth/logout'); - commit('token', cookies.token); - try { - const response = await this.$axios.$get('verify'); - dispatch('login', { - token: cookies.token, - user: response.user - }); - } catch (error) { - // dispatch('logout'); - } - }, - login({ commit }, { token, user }) { - this.$cookies.set('token', token); - commit('token', token); - commit('user', user); - commit('loggedIn', true); - }, - logout({ commit }) { - this.$cookies.remove('token'); - commit('token', null); - commit('user', null); - commit('loggedIn', false); - }, - alert({ commit }, payload) { + commit('auth/setToken', cookies.token); + await dispatch('auth/verify'); + } + /* alert({ commit }, payload) { if (!payload) return commit('alert', null); commit('alert', { text: payload.text, error: payload.error }); - } + } */ }; -- cgit v1.2.3 From c2dbbe6396540ee9d76991a00f5028b49d221d0c Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 2 Jul 2020 23:42:02 +0300 Subject: feat: refactor account to use vuex, fix small presentational components --- src/site/store/auth.js | 39 ++++++++++++++++++++++++++++++++++++++- src/site/store/images.js | 4 ++-- 2 files changed, 40 insertions(+), 3 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/auth.js b/src/site/store/auth.js index a62a6ec..73976d6 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -10,7 +10,8 @@ const getDefaultState = () => ({ export const state = getDefaultState; export const getters = { - isLoggedIn: state => state.loggedIn + isLoggedIn: state => state.loggedIn, + getApiKey: state => state.user?.apiKey }; export const actions = { @@ -35,6 +36,36 @@ export const actions = { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } }, + async fetchCurrentUser({ commit, dispatch }) { + try { + const data = await this.$axios.$get(`users/me`); + commit('setUser', data.user); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async changePassword({ dispatch }, { password, newPassword }) { + try { + const response = await this.$axios.$post(`user/password/change`, { + password, + newPassword + }); + + return response; + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async requestAPIKey({ commit, dispatch }) { + try { + const response = await this.$axios.$post(`user/apikey/change`); + commit('setApiKey', response.apiKey); + + return response; + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, logout({ commit }) { commit('logout'); } @@ -44,6 +75,12 @@ export const mutations = { setToken(state, token) { state.token = token; }, + setApiKey(state, apiKey) { + state.user.apiKey = apiKey; + }, + setUser(state, user) { + state.user = user; + }, loginRequest(state) { state.isLoading = true; }, diff --git a/src/site/store/images.js b/src/site/store/images.js index e87dac1..f6dae1b 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -10,8 +10,8 @@ export const state = () => ({ }); export const getters = { - getTotalFiles: state => state.pagination.totalFiles, - getFetchedCount: state => state.files.length, + getTotalFiles: ({ pagination }) => pagination.totalFiles, + getFetchedCount: ({ files }) => files.length, shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, getLimit: ({ pagination }) => pagination.limit }; -- cgit v1.2.3 From 7581d13d1cdbd190009dea11549669cfa5cc00ad Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Fri, 3 Jul 2020 00:35:09 +0300 Subject: feat: separate album view into multiple components and use vuex --- src/site/store/albums.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/site/store/albums.js (limited to 'src/site/store') diff --git a/src/site/store/albums.js b/src/site/store/albums.js new file mode 100644 index 0000000..a33181c --- /dev/null +++ b/src/site/store/albums.js @@ -0,0 +1,56 @@ +/* eslint-disable no-shadow */ +export const state = () => ({ + list: [], + isListLoading: false, + albumDetails: {}, + expandedAlbums: [] +}); + +export const getters = { + isExpanded: state => id => state.expandedAlbums.indexOf(id) > -1, + getDetails: state => id => state.albumDetails[id] || {} +}; + +export const actions = { + async fetch({ commit, dispatch }) { + try { + commit('albumsRequest'); + const response = await this.$axios.$get(`albums/mini`); + + commit('setAlbums', response.albums); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async fetchDetails({ commit }, albumId) { + const response = await this.$axios.$get(`album/${albumId}/links`); + + commit('setDetails', { + id: albumId, + details: { + links: response.links + } + }); + } +}; + +export const mutations = { + albumsRequest(state) { + state.isLoading = true; + }, + setAlbums(state, albums) { + state.list = albums; + state.isLoading = false; + }, + setDetails(state, { id, details }) { + state.albumDetails[id] = details; + }, + toggleExpandedState(state, id) { + const foundIndex = state.expandedAlbums.indexOf(id); + if (foundIndex > -1) { + state.expandedAlbums.splice(foundIndex, 1); + } else { + state.expandedAlbums.push(id); + } + } +}; -- cgit v1.2.3 From 92be4504ccb8f6d918013e5c33870858cd22376a Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sat, 4 Jul 2020 03:26:35 +0300 Subject: feat: refactor most of the album components to use store for presentation and actions --- src/site/store/album.js | 0 src/site/store/albums.js | 75 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/site/store/album.js (limited to 'src/site/store') diff --git a/src/site/store/album.js b/src/site/store/album.js new file mode 100644 index 0000000..e69de29 diff --git a/src/site/store/albums.js b/src/site/store/albums.js index a33181c..d5d45ce 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -1,4 +1,6 @@ /* eslint-disable no-shadow */ +import Vue from 'vue'; + export const state = () => ({ list: [], isListLoading: false, @@ -18,10 +20,13 @@ export const actions = { const response = await this.$axios.$get(`albums/mini`); commit('setAlbums', response.albums); + + return response; } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } }, + async fetchDetails({ commit }, albumId) { const response = await this.$axios.$get(`album/${albumId}/links`); @@ -31,6 +36,52 @@ export const actions = { links: response.links } }); + + return response; + }, + + async createAlbum({ commit }, name) { + const response = await this.$axios.$post(`album/new`, { name }); + + commit('addAlbum', response.data); + + return response; + }, + + async deleteAlbum({ commit }, albumId) { + const response = await this.$axios.$delete(`album/${albumId}`); + + commit('removeAlbum', albumId); + + return response; + }, + + async createLink({ commit }, albumId) { + const response = await this.$axios.$post(`album/link/new`, { albumId }); + + commit('addAlbumLink', { albumId, data: response.data }); + + return response; + }, + + async updateLinkOptions({ commit }, { albumId, linkOpts }) { + const response = await this.$axios.$post(`album/link/edit`, { + identifier: linkOpts.identifier, + enableDownload: linkOpts.enableDownload, + enabled: linkOpts.enabled + }); + + commit('updateAlbumLinkOpts', { albumId, linkOpts: response.data }); + + return response; + }, + + async deleteLink({ commit }, { albumId, identifier }) { + const response = await this.$axios.$delete(`album/link/delete/${identifier}`); + + commit('removeAlbumLink', { albumId, identifier }); + + return response; } }; @@ -42,8 +93,30 @@ export const mutations = { state.list = albums; state.isLoading = false; }, + addAlbum(state, album) { + state.list.unshift(album); + }, + removeAlbum(state, albumId) { + // state.list = state.list.filter(({ id }) => id !== albumId); + const foundIndex = state.list.findIndex(({ id }) => id === albumId); + state.list.splice(foundIndex, 1); + }, setDetails(state, { id, details }) { - state.albumDetails[id] = details; + Vue.set(state.albumDetails, id, details); + }, + addAlbumLink(state, { albumId, data }) { + state.albumDetails[albumId].links.push(data); + }, + updateAlbumLinkOpts(state, { albumId, linkOpts }) { + const foundIndex = state.albumDetails[albumId].links.findIndex( + ({ identifier }) => identifier === linkOpts.identifier + ); + const link = state.albumDetails[albumId].links[foundIndex]; + state.albumDetails[albumId].links[foundIndex] = { ...link, ...linkOpts }; + }, + removeAlbumLink(state, { albumId, identifier }) { + const foundIndex = state.albumDetails[albumId].links.findIndex(({ identifier: id }) => id === identifier); + state.albumDetails[albumId].links.splice(foundIndex, 1); }, toggleExpandedState(state, id) { const foundIndex = state.expandedAlbums.indexOf(id); -- cgit v1.2.3 From 04fdd63cee5327f49e5e11d5837a9031027c34ef Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sun, 5 Jul 2020 04:17:09 +0300 Subject: feat: refactor single album page to use vuex --- src/site/store/album.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ src/site/store/albums.js | 38 +++++++++++++++------------------- 2 files changed, 71 insertions(+), 21 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/album.js b/src/site/store/album.js index e69de29..f7c88c9 100644 --- a/src/site/store/album.js +++ b/src/site/store/album.js @@ -0,0 +1,54 @@ +/* eslint-disable no-shadow */ +export const state = () => ({ + files: [], + name: null, + isLoading: false, + pagination: { + page: 1, + limit: 30, + totalFiles: 0, + }, + downloadEnabled: false, +}); + +export const getters = { + getTotalFiles: ({ pagination }) => pagination.totalFiles, + getFetchedCount: ({ files }) => files.length, + shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, + getLimit: ({ pagination }) => pagination.limit, + getName: ({ name }) => name, +}; + +export const actions = { + async fetchById({ commit, dispatch, state }, { id, page }) { + commit('setIsLoading'); + + page = page || 1; + + try { + const response = await this.$axios.$get(`album/${id}/full`, { + params: { limit: state.pagination.limit, page }, + }); + + commit('setFiles', response); + commit('updatePaginationMeta', { totalFiles: response.count, page }); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, +}; + +export const mutations = { + setIsLoading(state) { + state.isLoading = true; + }, + setFiles(state, { files, name }) { + state.files = files || []; + state.name = name; + state.isLoading = false; + }, + updatePaginationMeta(state, { page, totalFiles }) { + state.pagination.page = page || 1; + state.pagination.totalFiles = totalFiles || 0; + }, +}; diff --git a/src/site/store/albums.js b/src/site/store/albums.js index d5d45ce..f3d7bcf 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -5,26 +5,22 @@ export const state = () => ({ list: [], isListLoading: false, albumDetails: {}, - expandedAlbums: [] + expandedAlbums: [], }); export const getters = { - isExpanded: state => id => state.expandedAlbums.indexOf(id) > -1, - getDetails: state => id => state.albumDetails[id] || {} + isExpanded: (state) => (id) => state.expandedAlbums.indexOf(id) > -1, + getDetails: (state) => (id) => state.albumDetails[id] || {}, }; export const actions = { - async fetch({ commit, dispatch }) { - try { - commit('albumsRequest'); - const response = await this.$axios.$get(`albums/mini`); + async fetch({ commit }) { + commit('albumsRequest'); + const response = await this.$axios.$get('albums/mini'); - commit('setAlbums', response.albums); + commit('setAlbums', response.albums); - return response; - } catch (e) { - dispatch('alert/set', { text: e.message, error: true }, { root: true }); - } + return response; }, async fetchDetails({ commit }, albumId) { @@ -33,15 +29,15 @@ export const actions = { commit('setDetails', { id: albumId, details: { - links: response.links - } + links: response.links, + }, }); return response; }, async createAlbum({ commit }, name) { - const response = await this.$axios.$post(`album/new`, { name }); + const response = await this.$axios.$post('album/new', { name }); commit('addAlbum', response.data); @@ -57,7 +53,7 @@ export const actions = { }, async createLink({ commit }, albumId) { - const response = await this.$axios.$post(`album/link/new`, { albumId }); + const response = await this.$axios.$post('album/link/new', { albumId }); commit('addAlbumLink', { albumId, data: response.data }); @@ -65,10 +61,10 @@ export const actions = { }, async updateLinkOptions({ commit }, { albumId, linkOpts }) { - const response = await this.$axios.$post(`album/link/edit`, { + const response = await this.$axios.$post('album/link/edit', { identifier: linkOpts.identifier, enableDownload: linkOpts.enableDownload, - enabled: linkOpts.enabled + enabled: linkOpts.enabled, }); commit('updateAlbumLinkOpts', { albumId, linkOpts: response.data }); @@ -82,7 +78,7 @@ export const actions = { commit('removeAlbumLink', { albumId, identifier }); return response; - } + }, }; export const mutations = { @@ -109,7 +105,7 @@ export const mutations = { }, updateAlbumLinkOpts(state, { albumId, linkOpts }) { const foundIndex = state.albumDetails[albumId].links.findIndex( - ({ identifier }) => identifier === linkOpts.identifier + ({ identifier }) => identifier === linkOpts.identifier, ); const link = state.albumDetails[albumId].links[foundIndex]; state.albumDetails[albumId].links[foundIndex] = { ...link, ...linkOpts }; @@ -125,5 +121,5 @@ export const mutations = { } else { state.expandedAlbums.push(id); } - } + }, }; -- cgit v1.2.3 From 766e74cc51138b32482f65f0f2647eb9d943103e Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sun, 5 Jul 2020 04:18:08 +0300 Subject: feat: add video preview on hover to dashboard and apply new linter rules to some of the files --- src/site/store/auth.js | 20 ++++++++++---------- src/site/store/images.js | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 73976d6..55009ce 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -4,14 +4,14 @@ const getDefaultState = () => ({ loggedIn: false, isLoading: false, user: null, - token: null + token: null, }); export const state = getDefaultState; export const getters = { - isLoggedIn: state => state.loggedIn, - getApiKey: state => state.user?.apiKey + isLoggedIn: (state) => state.loggedIn, + getApiKey: (state) => state.user?.apiKey, }; export const actions = { @@ -27,7 +27,7 @@ export const actions = { commit('loginRequest'); try { - const data = await this.$axios.$post(`auth/login`, { username, password }); + const data = await this.$axios.$post('auth/login', { username, password }); this.$axios.setToken(data.token, 'Bearer'); commit('setToken', data.token); @@ -38,7 +38,7 @@ export const actions = { }, async fetchCurrentUser({ commit, dispatch }) { try { - const data = await this.$axios.$get(`users/me`); + const data = await this.$axios.$get('users/me'); commit('setUser', data.user); } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); @@ -46,9 +46,9 @@ export const actions = { }, async changePassword({ dispatch }, { password, newPassword }) { try { - const response = await this.$axios.$post(`user/password/change`, { + const response = await this.$axios.$post('user/password/change', { password, - newPassword + newPassword, }); return response; @@ -58,7 +58,7 @@ export const actions = { }, async requestAPIKey({ commit, dispatch }) { try { - const response = await this.$axios.$post(`user/apikey/change`); + const response = await this.$axios.$post('user/apikey/change'); commit('setApiKey', response.apiKey); return response; @@ -68,7 +68,7 @@ export const actions = { }, logout({ commit }) { commit('logout'); - } + }, }; export const mutations = { @@ -94,5 +94,5 @@ export const mutations = { this.$cookies.remove('token'); // reset state to default Object.assign(state, getDefaultState()); - } + }, }; diff --git a/src/site/store/images.js b/src/site/store/images.js index f6dae1b..14f475a 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -25,7 +25,7 @@ export const actions = { try { const response = await this.$axios.$get(`files`, { params: { limit: state.pagination.limit, page } }); - commit('updateFiles', { files: response.files }); + commit('setFiles', { files: response.files }); commit('updatePaginationMeta', { totalFiles: response.count, page }); } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); @@ -45,7 +45,7 @@ export const mutations = { setIsLoading(state) { state.isLoading = true; }, - updateFiles(state, { files }) { + setFiles(state, { files }) { state.files = files || []; state.isLoading = false; }, -- cgit v1.2.3 From 15f296a7805b7623f56eab67b74ab0bf93a038e1 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Tue, 7 Jul 2020 02:02:37 +0300 Subject: chore: eslint stores feat: merge album and images --- src/site/store/.eslintrc.json | 5 +++++ src/site/store/admin.js | 0 src/site/store/album.js | 5 ++++- src/site/store/albums.js | 1 - src/site/store/alert.js | 7 +++---- src/site/store/auth.js | 17 +++++----------- src/site/store/config.js | 5 ++--- src/site/store/images.js | 45 ++++++++++++++++++++++++------------------- src/site/store/index.js | 5 +++-- 9 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 src/site/store/.eslintrc.json create mode 100644 src/site/store/admin.js (limited to 'src/site/store') diff --git a/src/site/store/.eslintrc.json b/src/site/store/.eslintrc.json new file mode 100644 index 0000000..052e3ef --- /dev/null +++ b/src/site/store/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-shadow": ["error", { "allow": ["state"] }] + } +} diff --git a/src/site/store/admin.js b/src/site/store/admin.js new file mode 100644 index 0000000..e69de29 diff --git a/src/site/store/album.js b/src/site/store/album.js index f7c88c9..d8ffacc 100644 --- a/src/site/store/album.js +++ b/src/site/store/album.js @@ -1,4 +1,3 @@ -/* eslint-disable no-shadow */ export const state = () => ({ files: [], name: null, @@ -36,6 +35,10 @@ export const actions = { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } }, + // TODO: Fix duplicate code between this store and files store + deleteFile({ commit }, fileId) { + + }, }; export const mutations = { diff --git a/src/site/store/albums.js b/src/site/store/albums.js index f3d7bcf..2b4ac60 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -1,4 +1,3 @@ -/* eslint-disable no-shadow */ import Vue from 'vue'; export const state = () => ({ diff --git a/src/site/store/alert.js b/src/site/store/alert.js index 78c0eaf..ff38e09 100644 --- a/src/site/store/alert.js +++ b/src/site/store/alert.js @@ -1,7 +1,6 @@ -/* eslint-disable no-shadow */ const getDefaultState = () => ({ text: null, - error: false + error: false, }); export const state = getDefaultState; @@ -12,7 +11,7 @@ export const actions = { }, clear({ commit }) { commit('clear'); - } + }, }; export const mutations = { @@ -22,5 +21,5 @@ export const mutations = { }, clear(state) { Object.assign(state, getDefaultState()); - } + }, }; diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 55009ce..69de9ec 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -1,8 +1,5 @@ -/* eslint-disable no-shadow */ -// only used so I could keep the convention of naming the first param as "state" in mutations const getDefaultState = () => ({ loggedIn: false, - isLoading: false, user: null, token: null, }); @@ -23,18 +20,14 @@ export const actions = { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } }, - async login({ commit, dispatch }, { username, password }) { + async login({ commit }, { username, password }) { commit('loginRequest'); - try { - const data = await this.$axios.$post('auth/login', { username, password }); - this.$axios.setToken(data.token, 'Bearer'); + const data = await this.$axios.$post('auth/login', { username, password }); + this.$axios.setToken(data.token, 'Bearer'); - commit('setToken', data.token); - commit('loginSuccess', { token: data.token, user: data.user }); - } catch (e) { - dispatch('alert/set', { text: e.message, error: true }, { root: true }); - } + commit('setToken', data.token); + commit('loginSuccess', { token: data.token, user: data.user }); }, async fetchCurrentUser({ commit, dispatch }) { try { diff --git a/src/site/store/config.js b/src/site/store/config.js index 6202f84..f52fc0f 100644 --- a/src/site/store/config.js +++ b/src/site/store/config.js @@ -1,4 +1,3 @@ -/* eslint-disable no-shadow */ export const state = () => ({ development: true, version: '4.0.0', @@ -9,11 +8,11 @@ export const state = () => ({ chunkSize: 90, maxLinksPerAlbum: 5, publicMode: false, - userAccounts: false + userAccounts: false, }); export const mutations = { set(state, config) { Object.assign(state, config); - } + }, }; diff --git a/src/site/store/images.js b/src/site/store/images.js index 14f475a..d02219f 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -1,19 +1,21 @@ -/* eslint-disable no-shadow */ export const state = () => ({ files: [], isLoading: false, pagination: { page: 1, limit: 30, - totalFiles: 0 - } + totalFiles: 0, + }, + name: null, + downloadEnabled: false, }); export const getters = { getTotalFiles: ({ pagination }) => pagination.totalFiles, getFetchedCount: ({ files }) => files.length, shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, - getLimit: ({ pagination }) => pagination.limit + getLimit: ({ pagination }) => pagination.limit, + getName: ({ name }) => name, }; export const actions = { @@ -23,34 +25,37 @@ export const actions = { page = page || 1; try { - const response = await this.$axios.$get(`files`, { params: { limit: state.pagination.limit, page } }); + const response = await this.$axios.$get('files', { params: { limit: state.pagination.limit, page } }); - commit('setFiles', { files: response.files }); - commit('updatePaginationMeta', { totalFiles: response.count, page }); + commit('setFilesAndMeta', { ...response, page }); } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } }, - async fetchById({ commit, dispatch }) { - try { - const response = await this.$axios.$get('verify'); - commit('loginSuccess', response); - } catch (e) { - dispatch('alert/set', { text: e.message, error: true }, { root: true }); - } - } + async fetchByAlbumId({ commit, dispatch, state }, { id, page }) { + commit('setIsLoading'); + + page = page || 1; + + const response = await this.$axios.$get(`album/${id}/full`, { + params: { limit: state.pagination.limit, page }, + }); + + commit('setFilesAndMeta', { ...response, page }); + }, }; export const mutations = { setIsLoading(state) { state.isLoading = true; }, - setFiles(state, { files }) { + setFilesAndMeta(state, { + files, name, page, count, + }) { state.files = files || []; + state.name = name ?? null; state.isLoading = false; - }, - updatePaginationMeta(state, { page, totalFiles }) { state.pagination.page = page || 1; - state.pagination.totalFiles = totalFiles || 0; - } + state.pagination.totalFiles = count || 0; + }, }; diff --git a/src/site/store/index.js b/src/site/store/index.js index 8f910ae..c0faffb 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,5 +1,6 @@ import config from '../../../dist/config.json'; +// eslint-disable-next-line import/prefer-default-export export const actions = { async nuxtClientInit({ commit, dispatch }) { commit('config/set', config); @@ -8,8 +9,8 @@ export const actions = { if (!cookies.token) return dispatch('auth/logout'); commit('auth/setToken', cookies.token); - await dispatch('auth/verify'); - } + return dispatch('auth/verify'); + }, /* alert({ commit }, payload) { if (!payload) return commit('alert', null); commit('alert', { -- cgit v1.2.3 From 1a8b6602e094289a4f477c33e432e0f5e1587b45 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 03:13:51 +0300 Subject: refactor: change uploader component to use vuex --- src/site/store/albums.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/albums.js b/src/site/store/albums.js index 2b4ac60..8441182 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -5,6 +5,7 @@ export const state = () => ({ isListLoading: false, albumDetails: {}, expandedAlbums: [], + tinyDetails: [], }); export const getters = { @@ -21,7 +22,6 @@ export const actions = { return response; }, - async fetchDetails({ commit }, albumId) { const response = await this.$axios.$get(`album/${albumId}/links`); @@ -34,7 +34,6 @@ export const actions = { return response; }, - async createAlbum({ commit }, name) { const response = await this.$axios.$post('album/new', { name }); @@ -42,7 +41,6 @@ export const actions = { return response; }, - async deleteAlbum({ commit }, albumId) { const response = await this.$axios.$delete(`album/${albumId}`); @@ -50,7 +48,6 @@ export const actions = { return response; }, - async createLink({ commit }, albumId) { const response = await this.$axios.$post('album/link/new', { albumId }); @@ -58,7 +55,6 @@ export const actions = { return response; }, - async updateLinkOptions({ commit }, { albumId, linkOpts }) { const response = await this.$axios.$post('album/link/edit', { identifier: linkOpts.identifier, @@ -70,12 +66,18 @@ export const actions = { return response; }, - async deleteLink({ commit }, { albumId, identifier }) { const response = await this.$axios.$delete(`album/link/delete/${identifier}`); commit('removeAlbumLink', { albumId, identifier }); + return response; + }, + async getTinyDetails({ commit }) { + const response = await this.$axios.$get('albums/dropdown'); + + commit('setTinyDetails', response); + return response; }, }; @@ -111,7 +113,7 @@ export const mutations = { }, removeAlbumLink(state, { albumId, identifier }) { const foundIndex = state.albumDetails[albumId].links.findIndex(({ identifier: id }) => id === identifier); - state.albumDetails[albumId].links.splice(foundIndex, 1); + if (foundIndex > -1) state.albumDetails[albumId].links.splice(foundIndex, 1); }, toggleExpandedState(state, id) { const foundIndex = state.expandedAlbums.indexOf(id); @@ -121,4 +123,7 @@ export const mutations = { state.expandedAlbums.push(id); } }, + setTinyDetails(state, { albums }) { + state.tinyDetails = albums; + }, }; -- cgit v1.2.3 From 15266378810d81704f8c9ece6ecf919526efacae Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 03:15:07 +0300 Subject: feat: add new sidebar with mdi icons and active reactivity --- src/site/store/auth.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/site/store') diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 69de9ec..286d321 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -9,6 +9,7 @@ export const state = getDefaultState; export const getters = { isLoggedIn: (state) => state.loggedIn, getApiKey: (state) => state.user?.apiKey, + getToken: (state) => state.token, }; export const actions = { -- cgit v1.2.3 From b519b6ccb469e874c783b995ddf0ab6fabdb5a0e Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 03:37:50 +0300 Subject: refactor: refactor grid to use vuex for every action --- src/site/store/album.js | 57 --------------------------------------- src/site/store/images.js | 69 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 59 deletions(-) delete mode 100644 src/site/store/album.js (limited to 'src/site/store') diff --git a/src/site/store/album.js b/src/site/store/album.js deleted file mode 100644 index d8ffacc..0000000 --- a/src/site/store/album.js +++ /dev/null @@ -1,57 +0,0 @@ -export const state = () => ({ - files: [], - name: null, - isLoading: false, - pagination: { - page: 1, - limit: 30, - totalFiles: 0, - }, - downloadEnabled: false, -}); - -export const getters = { - getTotalFiles: ({ pagination }) => pagination.totalFiles, - getFetchedCount: ({ files }) => files.length, - shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, - getLimit: ({ pagination }) => pagination.limit, - getName: ({ name }) => name, -}; - -export const actions = { - async fetchById({ commit, dispatch, state }, { id, page }) { - commit('setIsLoading'); - - page = page || 1; - - try { - const response = await this.$axios.$get(`album/${id}/full`, { - params: { limit: state.pagination.limit, page }, - }); - - commit('setFiles', response); - commit('updatePaginationMeta', { totalFiles: response.count, page }); - } catch (e) { - dispatch('alert/set', { text: e.message, error: true }, { root: true }); - } - }, - // TODO: Fix duplicate code between this store and files store - deleteFile({ commit }, fileId) { - - }, -}; - -export const mutations = { - setIsLoading(state) { - state.isLoading = true; - }, - setFiles(state, { files, name }) { - state.files = files || []; - state.name = name; - state.isLoading = false; - }, - updatePaginationMeta(state, { page, totalFiles }) { - state.pagination.page = page || 1; - state.pagination.totalFiles = totalFiles || 0; - }, -}; diff --git a/src/site/store/images.js b/src/site/store/images.js index d02219f..3019d85 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -1,4 +1,6 @@ -export const state = () => ({ +import Vue from 'vue'; + +export const getDefaultState = () => ({ files: [], isLoading: false, pagination: { @@ -8,8 +10,11 @@ export const state = () => ({ }, name: null, downloadEnabled: false, + filesAlbums: {}, }); +export const state = getDefaultState; + export const getters = { getTotalFiles: ({ pagination }) => pagination.totalFiles, getFetchedCount: ({ files }) => files.length, @@ -28,11 +33,15 @@ export const actions = { const response = await this.$axios.$get('files', { params: { limit: state.pagination.limit, page } }); commit('setFilesAndMeta', { ...response, page }); + + return response; } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } + + return null; }, - async fetchByAlbumId({ commit, dispatch, state }, { id, page }) { + async fetchByAlbumId({ commit, state }, { id, page }) { commit('setIsLoading'); page = page || 1; @@ -42,6 +51,36 @@ export const actions = { }); commit('setFilesAndMeta', { ...response, page }); + + return response; + }, + async getFileAlbums({ commit }, fileId) { + const response = await this.$axios.$get(`file/${fileId}/albums`); + + commit('setFileAlbums', { ...response, fileId }); + + return response; + }, + async addToAlbum({ commit }, { fileId, albumId }) { + const response = await this.$axios.$post('file/album/add', { fileId, albumId }); + + commit('addAlbumToFile', { fileId, albumId, ...response.data }); + + return response; + }, + async removeFromAlbum({ commit }, { fileId, albumId }) { + const response = await this.$axios.$post('file/album/del', { fileId, albumId }); + + commit('removeAlbumFromFile', { fileId, albumId }); + + return response; + }, + async deleteFile({ commit }, fileId) { + const response = await this.$axios.$delete(`file/${fileId}`); + + commit('removeFile', fileId); + + return response; }, }; @@ -58,4 +97,30 @@ export const mutations = { state.pagination.page = page || 1; state.pagination.totalFiles = count || 0; }, + removeFile(state, fileId) { + const foundIndex = state.files.findIndex(({ id }) => id === fileId); + if (foundIndex > -1) { + state.files.splice(foundIndex, 1); + state.pagination.totalFiles -= 1; + } + }, + setFileAlbums(state, { fileId, albums }) { + Vue.set(state.filesAlbums, fileId, albums); + }, + addAlbumToFile(state, { fileId, album }) { + if (!state.filesAlbums[fileId]) return; + + state.filesAlbums[fileId].push(album); + }, + removeAlbumFromFile(state, { fileId, albumId }) { + if (!state.filesAlbums[fileId]) return; + + const foundIndex = state.filesAlbums[fileId].findIndex(({ id }) => id === albumId); + if (foundIndex > -1) { + state.filesAlbums[fileId].splice(foundIndex, 1); + } + }, + resetState(state) { + Object.assign(state, getDefaultState()); + }, }; -- cgit v1.2.3 From ad852de51a0d2dd5d29c08838d5a430c58849e74 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 04:00:12 +0300 Subject: chore: linter the entire project using the new rules --- src/site/store/auth.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/site/store') diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 286d321..fcc051b 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -49,6 +49,8 @@ export const actions = { } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } + + return null; }, async requestAPIKey({ commit, dispatch }) { try { @@ -59,6 +61,8 @@ export const actions = { } catch (e) { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } + + return null; }, logout({ commit }) { commit('logout'); -- cgit v1.2.3 From fd3f6de51a082dcd72c2ef557747e031ef7b9c4a Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 9 Jul 2020 02:24:40 +0300 Subject: refactor: refactor most of the admin pages to use the store instead of internal states --- src/site/store/admin.js | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ src/site/store/alert.js | 18 +++++++--- src/site/store/auth.js | 10 ++++-- src/site/store/images.js | 2 +- 4 files changed, 115 insertions(+), 8 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/admin.js b/src/site/store/admin.js index e69de29..2586a18 100644 --- a/src/site/store/admin.js +++ b/src/site/store/admin.js @@ -0,0 +1,93 @@ +export const state = () => ({ + users: [], + user: { + id: null, + username: null, + enabled: false, + createdAt: null, + editedAt: null, + apiKeyEditedAt: null, + isAdmin: null, + files: [], + }, + file: {}, + settings: {}, +}); + +export const actions = { + async fetchUsers({ commit }) { + const response = await this.$axios.$get('admin/users'); + commit('setUsers', response); + + return response; + }, + async fetchUser({ commit }, id) { + const response = await this.$axios.$get(`/admin/users/${id}`); + commit('setUserInfo', response); + + return response; + }, + async enableUser({ commit }, id) { + const response = await this.$axios.$post('admin/users/enable', { id }); + + commit('changeUserState', { userId: id, enabled: true }); + + return response; + }, + async disableUser({ commit }, id) { + const response = await this.$axios.$post('admin/users/disable', { id }); + + commit('changeUserState', { userId: id, enabled: false }); + + return response; + }, + async promoteUser({ commit }, id) { + const response = await this.$axios.$post('admin/users/promote', { id }); + + commit('changeUserState', { userId: id, isAdmin: true }); + + return response; + }, + async demoteUser({ commit }, id) { + const response = await this.$axios.$post('admin/users/demote', { id }); + + commit('changeUserState', { userId: id, isAdmin: false }); + + return response; + }, + async purgeUserFiles(_, id) { + const response = await this.$axios.$post('admin/users/purge', { id }); + + return response; + }, +}; + +export const mutations = { + setUsers(state, { users }) { + state.users = users; + }, + setUserInfo(state, { user, files }) { + state.user = { ...state.user, ...user }; + state.user.files = files || []; + }, + changeUserState(state, { userId, enabled, isAdmin }) { + const foundIndex = state.users.findIndex(({ id }) => id === userId); + if (foundIndex > -1) { + if (enabled !== undefined) { + state.users[foundIndex].enabled = enabled; + } + if (isAdmin !== undefined) { + state.users[foundIndex].isAdmin = isAdmin; + } + } + + if (state.user.id === userId) { + if (enabled !== undefined) { + state.user.enabled = enabled; + } + if (isAdmin !== undefined) { + state.user.isAdmin = isAdmin; + } + } + }, +}; diff --git a/src/site/store/alert.js b/src/site/store/alert.js index ff38e09..580dcc8 100644 --- a/src/site/store/alert.js +++ b/src/site/store/alert.js @@ -1,12 +1,19 @@ +import AlertTypes from '~/constants/alertTypes'; + const getDefaultState = () => ({ - text: null, - error: false, + message: null, + type: null, + snackbar: false, }); export const state = getDefaultState; export const actions = { set({ commit }, data) { + // Only exists for backwards compatibility, remove one day + if (data.error === true) data.type = AlertTypes.ERROR; + if (data.text !== undefined) data.message = data.text; + commit('set', data); }, clear({ commit }) { @@ -15,9 +22,10 @@ export const actions = { }; export const mutations = { - set(state, { text, error }) { - state.text = text; - state.error = error; + set(state, { message, type, snackbar }) { + state.message = message; + state.type = type; + state.snackbar = snackbar || false; }, clear(state) { Object.assign(state, getDefaultState()); diff --git a/src/site/store/auth.js b/src/site/store/auth.js index fcc051b..465de7d 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -30,6 +30,12 @@ export const actions = { commit('setToken', data.token); commit('loginSuccess', { token: data.token, user: data.user }); }, + async register(_, { username, password }) { + return this.$axios.$post('auth/register', { + username, + password, + }); + }, async fetchCurrentUser({ commit, dispatch }) { try { const data = await this.$axios.$get('users/me'); @@ -83,13 +89,13 @@ export const mutations = { state.isLoading = true; }, loginSuccess(state, { user }) { - this.$cookies.set('token', state.token); + this.$cookies.set('token', state.token, { path: '/' }); state.user = user; state.loggedIn = true; state.isLoading = false; }, logout(state) { - this.$cookies.remove('token'); + this.$cookies.remove('token', { path: '/' }); // reset state to default Object.assign(state, getDefaultState()); }, diff --git a/src/site/store/images.js b/src/site/store/images.js index 3019d85..a7581e0 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -10,7 +10,7 @@ export const getDefaultState = () => ({ }, name: null, downloadEnabled: false, - filesAlbums: {}, + filesAlbums: {}, // map of file ids with a list of album objects the file is in }); export const state = getDefaultState; -- cgit v1.2.3 From 0f66d807035d3e32a66c7dc9bf55fb3be99aedac Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Fri, 10 Jul 2020 01:13:51 +0300 Subject: refactor: finish refactoring all the components to use vuex --- src/site/store/admin.js | 31 ++++++++++++++++++++++++++++++- src/site/store/auth.js | 6 +++++- src/site/store/images.js | 15 ++++++++------- 3 files changed, 43 insertions(+), 9 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/admin.js b/src/site/store/admin.js index 2586a18..b31c446 100644 --- a/src/site/store/admin.js +++ b/src/site/store/admin.js @@ -15,6 +15,12 @@ export const state = () => ({ }); export const actions = { + async fetchSettings({ commit }) { + const response = await this.$axios.$get('service/config'); + commit('setSettings', response); + + return response; + }, async fetchUsers({ commit }) { const response = await this.$axios.$get('admin/users'); commit('setUsers', response); @@ -22,11 +28,23 @@ export const actions = { return response; }, async fetchUser({ commit }, id) { - const response = await this.$axios.$get(`/admin/users/${id}`); + const response = await this.$axios.$get(`admin/users/${id}`); + commit('setUserInfo', response); + + return response; + }, + async fetchFile({ commit }, id) { + const response = await this.$axios.$get(`file/${id}`); + commit('setFile', response); commit('setUserInfo', response); return response; }, + async banIP(_, ip) { + const response = await this.$axios.$post('admin/ban/ip', { ip }); + + return response; + }, async enableUser({ commit }, id) { const response = await this.$axios.$post('admin/users/enable', { id }); @@ -58,11 +76,19 @@ export const actions = { async purgeUserFiles(_, id) { const response = await this.$axios.$post('admin/users/purge', { id }); + return response; + }, + async restartService() { + const response = await this.$axios.$post('service/restart'); + return response; }, }; export const mutations = { + setSettings(state, { config }) { + state.settings = config; + }, setUsers(state, { users }) { state.users = users; }, @@ -70,6 +96,9 @@ export const mutations = { state.user = { ...state.user, ...user }; state.user.files = files || []; }, + setFile(state, { file }) { + state.file = file || {}; + }, changeUserState(state, { userId, enabled, isAdmin }) { const foundIndex = state.users.findIndex(({ id }) => id === userId); if (foundIndex > -1) { diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 465de7d..96631e2 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -1,6 +1,10 @@ const getDefaultState = () => ({ loggedIn: false, - user: null, + user: { + id: null, + isAdmin: false, + username: null, + }, token: null, }); diff --git a/src/site/store/images.js b/src/site/store/images.js index a7581e0..acac286 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -10,7 +10,8 @@ export const getDefaultState = () => ({ }, name: null, downloadEnabled: false, - filesAlbums: {}, // map of file ids with a list of album objects the file is in + fileAlbumsMap: {}, // map of file ids with a list of album objects the file is in + filesTags: {}, // map of file ids with a list of tag objects for the file }); export const state = getDefaultState; @@ -105,19 +106,19 @@ export const mutations = { } }, setFileAlbums(state, { fileId, albums }) { - Vue.set(state.filesAlbums, fileId, albums); + Vue.set(state.fileAlbumsMap, fileId, albums); }, addAlbumToFile(state, { fileId, album }) { - if (!state.filesAlbums[fileId]) return; + if (!state.fileAlbumsMap[fileId]) return; - state.filesAlbums[fileId].push(album); + state.fileAlbumsMap[fileId].push(album); }, removeAlbumFromFile(state, { fileId, albumId }) { - if (!state.filesAlbums[fileId]) return; + if (!state.fileAlbumsMap[fileId]) return; - const foundIndex = state.filesAlbums[fileId].findIndex(({ id }) => id === albumId); + const foundIndex = state.fileAlbumsMap[fileId].findIndex(({ id }) => id === albumId); if (foundIndex > -1) { - state.filesAlbums[fileId].splice(foundIndex, 1); + state.fileAlbumsMap[fileId].splice(foundIndex, 1); } }, resetState(state) { -- cgit v1.2.3 From c93ddb09008c45942544b13bbb03319c367f9cd8 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sun, 19 Jul 2020 22:27:11 +0300 Subject: feat: Start working on a new album/tags/image info modal --- src/site/store/admin.js | 2 +- src/site/store/images.js | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/admin.js b/src/site/store/admin.js index b31c446..04ad980 100644 --- a/src/site/store/admin.js +++ b/src/site/store/admin.js @@ -34,7 +34,7 @@ export const actions = { return response; }, async fetchFile({ commit }, id) { - const response = await this.$axios.$get(`file/${id}`); + const response = await this.$axios.$get(`admin/file/${id}`); commit('setFile', response); commit('setUserInfo', response); diff --git a/src/site/store/images.js b/src/site/store/images.js index acac286..0d5e82a 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -8,10 +8,11 @@ export const getDefaultState = () => ({ limit: 30, totalFiles: 0, }, - name: null, - downloadEnabled: false, + albumName: null, + albumDownloadEnabled: false, + fileExtraInfoMap: {}, // information about the selected file fileAlbumsMap: {}, // map of file ids with a list of album objects the file is in - filesTags: {}, // map of file ids with a list of tag objects for the file + fileTagsMap: {}, // map of file ids with a list of tag objects for the file }); export const state = getDefaultState; @@ -55,6 +56,15 @@ export const actions = { return response; }, + async fetchFileMeta({ commit }, fileId) { + const response = await this.$axios.$get(`file/${fileId}`); + + commit('setFileAlbums', { ...response, fileId }); + commit('setFileTags', { ...response, fileId }); + commit('setFileExtraInfo', { ...response, fileId }); + + return response; + }, async getFileAlbums({ commit }, fileId) { const response = await this.$axios.$get(`file/${fileId}/albums`); @@ -90,10 +100,11 @@ export const mutations = { state.isLoading = true; }, setFilesAndMeta(state, { - files, name, page, count, + files, name, page, count, downloadEnabled, }) { state.files = files || []; - state.name = name ?? null; + state.albumName = name ?? null; + state.downloadEnabled = downloadEnabled ?? false; state.isLoading = false; state.pagination.page = page || 1; state.pagination.totalFiles = count || 0; @@ -108,6 +119,12 @@ export const mutations = { setFileAlbums(state, { fileId, albums }) { Vue.set(state.fileAlbumsMap, fileId, albums); }, + setFileTags(state, { fileId, tags }) { + Vue.set(state.fileTagsMap, fileId, tags); + }, + setFileExtraInfo(state, { fileId, file }) { + Vue.set(state.fileExtraInfoMap, fileId, file); + }, addAlbumToFile(state, { fileId, album }) { if (!state.fileAlbumsMap[fileId]) return; -- cgit v1.2.3 From 18bb451f793677a5bbfdc2c14128bae33c66dfde Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Mon, 20 Jul 2020 23:01:45 +0300 Subject: feat: implement all-in-one file detail viewer, tag editor and album selection modal --- src/site/store/images.js | 27 +++++++++++++++++++++++++++ src/site/store/tags.js | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/site/store/tags.js (limited to 'src/site/store') diff --git a/src/site/store/images.js b/src/site/store/images.js index 0d5e82a..be04c8a 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -91,6 +91,20 @@ export const actions = { commit('removeFile', fileId); + return response; + }, + async addTag({ commit }, { fileId, tagName }) { + const response = await this.$axios.$post('file/tag/add', { fileId, tagName }); + + commit('addTagToFile', response.data); + + return response; + }, + async removeTag({ commit }, { fileId, tagName }) { + const response = await this.$axios.$post('file/tag/del', { fileId, tagName }); + + commit('removeTagFromFile', response.data); + return response; }, }; @@ -138,6 +152,19 @@ export const mutations = { state.fileAlbumsMap[fileId].splice(foundIndex, 1); } }, + addTagToFile(state, { fileId, tag }) { + if (!state.fileTagsMap[fileId]) return; + + state.fileTagsMap[fileId].push(tag); + }, + removeTagFromFile(state, { fileId, tag }) { + if (!state.fileTagsMap[fileId]) return; + + const foundIndex = state.fileTagsMap[fileId].findIndex(({ id }) => id === tag.id); + if (foundIndex > -1) { + state.fileTagsMap[fileId].splice(foundIndex, 1); + } + }, resetState(state) { Object.assign(state, getDefaultState()); }, diff --git a/src/site/store/tags.js b/src/site/store/tags.js new file mode 100644 index 0000000..c06b741 --- /dev/null +++ b/src/site/store/tags.js @@ -0,0 +1,40 @@ +export const state = () => ({ + tagsList: [], +}); + +export const actions = { + async fetch({ commit }) { + const response = await this.$axios.$get('tags'); + + commit('setTags', response.tags); + + return response; + }, + async createTag({ commit }, name) { + const response = await this.$axios.$post('tag/new', { name }); + + commit('addTag', response.data); + + return response; + }, + async deleteTag({ commit }, tagId) { + const response = await this.$axios.$delete(`tag/${tagId}`); + + commit('deleteTag', response.data); + + return response; + }, +}; + +export const mutations = { + setTags(state, tags) { + state.tagsList = tags; + }, + addTag(state, tag) { + state.tagsList.unshift(tag); + }, + deleteTag(state, { id: tagId }) { + const foundIndex = state.tagsList.findIndex(({ id }) => id === tagId); + state.tagsList.splice(foundIndex, 1); + }, +}; -- cgit v1.2.3 From 279234a081e5ea772978732ae5d2e45d8adcd741 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 22 Jul 2020 02:14:06 +0300 Subject: feat: add new search input For now, it clones the autocomplete from buefy, untill a PR or resolution to the opened issue about not being able to manipulate how the suggestions are applied is found --- src/site/store/images.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/site/store') diff --git a/src/site/store/images.js b/src/site/store/images.js index be04c8a..4737c26 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -8,6 +8,7 @@ export const getDefaultState = () => ({ limit: 30, totalFiles: 0, }, + search: '', albumName: null, albumDownloadEnabled: false, fileExtraInfoMap: {}, // information about the selected file -- cgit v1.2.3 From 39e9941ded8de4e41048781daa80de0838c01c19 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 23 Jul 2020 04:08:31 +0300 Subject: feat: Add hiding to recommendations as a prop fix: change some of the regexes to remove , and ; as separator support because the query parser doesn't understad them and I don't feel like dealing with all the edge cases introduces by it --- src/site/store/images.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/site/store') diff --git a/src/site/store/images.js b/src/site/store/images.js index 4737c26..0488573 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -106,6 +106,12 @@ export const actions = { commit('removeTagFromFile', response.data); + return response; + }, + async search({ commit }, { q, albumId }) { + const optionalAlbum = albumId ? `&albumId=${albumId}` : ''; + const response = await this.$axios.$get(`search/?q=${encodeURI(q)}${optionalAlbum}`); + return response; }, }; -- cgit v1.2.3 From 151c360740aac5733759888220d91a1d3713b6e1 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Fri, 2 Oct 2020 22:16:34 +0300 Subject: feat: allow administrators to create custom links for albums --- src/site/store/albums.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/site/store') diff --git a/src/site/store/albums.js b/src/site/store/albums.js index 8441182..c1ff696 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -55,6 +55,13 @@ export const actions = { return response; }, + async createCustomLink({ commit }, { albumId, value }) { + const response = await this.$axios.$post('album/link/new', { albumId, identifier: value }); + + commit('addAlbumLink', { albumId, data: response.data }); + + return response; + }, async updateLinkOptions({ commit }, { albumId, linkOpts }) { const response = await this.$axios.$post('album/link/edit', { identifier: linkOpts.identifier, -- cgit v1.2.3 From 90001c2df56d58e69fd199a518ae7f3e4ed327fc Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 24 Dec 2020 10:40:50 +0200 Subject: chore: remove trailing commas --- src/site/store/admin.js | 8 ++++---- src/site/store/albums.js | 16 ++++++++-------- src/site/store/alert.js | 6 +++--- src/site/store/auth.js | 14 +++++++------- src/site/store/config.js | 4 ++-- src/site/store/images.js | 14 +++++++------- src/site/store/index.js | 2 +- src/site/store/tags.js | 6 +++--- 8 files changed, 35 insertions(+), 35 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/admin.js b/src/site/store/admin.js index 04ad980..58b63b5 100644 --- a/src/site/store/admin.js +++ b/src/site/store/admin.js @@ -8,10 +8,10 @@ export const state = () => ({ editedAt: null, apiKeyEditedAt: null, isAdmin: null, - files: [], + files: [] }, file: {}, - settings: {}, + settings: {} }); export const actions = { @@ -82,7 +82,7 @@ export const actions = { const response = await this.$axios.$post('service/restart'); return response; - }, + } }; export const mutations = { @@ -118,5 +118,5 @@ export const mutations = { state.user.isAdmin = isAdmin; } } - }, + } }; diff --git a/src/site/store/albums.js b/src/site/store/albums.js index c1ff696..4f796a1 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -5,12 +5,12 @@ export const state = () => ({ isListLoading: false, albumDetails: {}, expandedAlbums: [], - tinyDetails: [], + tinyDetails: [] }); export const getters = { isExpanded: (state) => (id) => state.expandedAlbums.indexOf(id) > -1, - getDetails: (state) => (id) => state.albumDetails[id] || {}, + getDetails: (state) => (id) => state.albumDetails[id] || {} }; export const actions = { @@ -28,8 +28,8 @@ export const actions = { commit('setDetails', { id: albumId, details: { - links: response.links, - }, + links: response.links + } }); return response; @@ -66,7 +66,7 @@ export const actions = { const response = await this.$axios.$post('album/link/edit', { identifier: linkOpts.identifier, enableDownload: linkOpts.enableDownload, - enabled: linkOpts.enabled, + enabled: linkOpts.enabled }); commit('updateAlbumLinkOpts', { albumId, linkOpts: response.data }); @@ -86,7 +86,7 @@ export const actions = { commit('setTinyDetails', response); return response; - }, + } }; export const mutations = { @@ -113,7 +113,7 @@ export const mutations = { }, updateAlbumLinkOpts(state, { albumId, linkOpts }) { const foundIndex = state.albumDetails[albumId].links.findIndex( - ({ identifier }) => identifier === linkOpts.identifier, + ({ identifier }) => identifier === linkOpts.identifier ); const link = state.albumDetails[albumId].links[foundIndex]; state.albumDetails[albumId].links[foundIndex] = { ...link, ...linkOpts }; @@ -132,5 +132,5 @@ export const mutations = { }, setTinyDetails(state, { albums }) { state.tinyDetails = albums; - }, + } }; diff --git a/src/site/store/alert.js b/src/site/store/alert.js index 580dcc8..cbd6359 100644 --- a/src/site/store/alert.js +++ b/src/site/store/alert.js @@ -3,7 +3,7 @@ import AlertTypes from '~/constants/alertTypes'; const getDefaultState = () => ({ message: null, type: null, - snackbar: false, + snackbar: false }); export const state = getDefaultState; @@ -18,7 +18,7 @@ export const actions = { }, clear({ commit }) { commit('clear'); - }, + } }; export const mutations = { @@ -29,5 +29,5 @@ export const mutations = { }, clear(state) { Object.assign(state, getDefaultState()); - }, + } }; diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 96631e2..85e3a39 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -3,9 +3,9 @@ const getDefaultState = () => ({ user: { id: null, isAdmin: false, - username: null, + username: null }, - token: null, + token: null }); export const state = getDefaultState; @@ -13,7 +13,7 @@ export const state = getDefaultState; export const getters = { isLoggedIn: (state) => state.loggedIn, getApiKey: (state) => state.user?.apiKey, - getToken: (state) => state.token, + getToken: (state) => state.token }; export const actions = { @@ -37,7 +37,7 @@ export const actions = { async register(_, { username, password }) { return this.$axios.$post('auth/register', { username, - password, + password }); }, async fetchCurrentUser({ commit, dispatch }) { @@ -52,7 +52,7 @@ export const actions = { try { const response = await this.$axios.$post('user/password/change', { password, - newPassword, + newPassword }); return response; @@ -76,7 +76,7 @@ export const actions = { }, logout({ commit }) { commit('logout'); - }, + } }; export const mutations = { @@ -102,5 +102,5 @@ export const mutations = { this.$cookies.remove('token', { path: '/' }); // reset state to default Object.assign(state, getDefaultState()); - }, + } }; diff --git a/src/site/store/config.js b/src/site/store/config.js index f52fc0f..c17632d 100644 --- a/src/site/store/config.js +++ b/src/site/store/config.js @@ -8,11 +8,11 @@ export const state = () => ({ chunkSize: 90, maxLinksPerAlbum: 5, publicMode: false, - userAccounts: false, + userAccounts: false }); export const mutations = { set(state, config) { Object.assign(state, config); - }, + } }; diff --git a/src/site/store/images.js b/src/site/store/images.js index 0488573..7cf25ce 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -6,14 +6,14 @@ export const getDefaultState = () => ({ pagination: { page: 1, limit: 30, - totalFiles: 0, + totalFiles: 0 }, search: '', albumName: null, albumDownloadEnabled: false, fileExtraInfoMap: {}, // information about the selected file fileAlbumsMap: {}, // map of file ids with a list of album objects the file is in - fileTagsMap: {}, // map of file ids with a list of tag objects for the file + fileTagsMap: {} // map of file ids with a list of tag objects for the file }); export const state = getDefaultState; @@ -23,7 +23,7 @@ export const getters = { getFetchedCount: ({ files }) => files.length, shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, getLimit: ({ pagination }) => pagination.limit, - getName: ({ name }) => name, + getName: ({ name }) => name }; export const actions = { @@ -50,7 +50,7 @@ export const actions = { page = page || 1; const response = await this.$axios.$get(`album/${id}/full`, { - params: { limit: state.pagination.limit, page }, + params: { limit: state.pagination.limit, page } }); commit('setFilesAndMeta', { ...response, page }); @@ -113,7 +113,7 @@ export const actions = { const response = await this.$axios.$get(`search/?q=${encodeURI(q)}${optionalAlbum}`); return response; - }, + } }; export const mutations = { @@ -121,7 +121,7 @@ export const mutations = { state.isLoading = true; }, setFilesAndMeta(state, { - files, name, page, count, downloadEnabled, + files, name, page, count, downloadEnabled }) { state.files = files || []; state.albumName = name ?? null; @@ -174,5 +174,5 @@ export const mutations = { }, resetState(state) { Object.assign(state, getDefaultState()); - }, + } }; diff --git a/src/site/store/index.js b/src/site/store/index.js index c0faffb..c5d9a23 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -10,7 +10,7 @@ export const actions = { commit('auth/setToken', cookies.token); return dispatch('auth/verify'); - }, + } /* alert({ commit }, payload) { if (!payload) return commit('alert', null); commit('alert', { diff --git a/src/site/store/tags.js b/src/site/store/tags.js index c06b741..a28c2ad 100644 --- a/src/site/store/tags.js +++ b/src/site/store/tags.js @@ -1,5 +1,5 @@ export const state = () => ({ - tagsList: [], + tagsList: [] }); export const actions = { @@ -23,7 +23,7 @@ export const actions = { commit('deleteTag', response.data); return response; - }, + } }; export const mutations = { @@ -36,5 +36,5 @@ export const mutations = { deleteTag(state, { id: tagId }) { const foundIndex = state.tagsList.findIndex(({ id }) => id === tagId); state.tagsList.splice(foundIndex, 1); - }, + } }; -- cgit v1.2.3 From 587f7d69e80cfa1d94cc4730dc26834c389f574d Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 24 Dec 2020 13:57:09 +0200 Subject: bug: fix showlist resetting itself every time the page is changed bug: fix store not commiting search results --- src/site/store/images.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/images.js b/src/site/store/images.js index 7cf25ce..69b4f5e 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -9,6 +9,7 @@ export const getDefaultState = () => ({ totalFiles: 0 }, search: '', + showList: false, albumName: null, albumDownloadEnabled: false, fileExtraInfoMap: {}, // information about the selected file @@ -108,11 +109,22 @@ export const actions = { return response; }, - async search({ commit }, { q, albumId }) { + async search({ commit, dispatch }, { q, albumId, page }) { const optionalAlbum = albumId ? `&albumId=${albumId}` : ''; - const response = await this.$axios.$get(`search/?q=${encodeURI(q)}${optionalAlbum}`); - return response; + page = page || 1; + + try { + const response = await this.$axios.$get(`search/?q=${encodeURI(q)}${optionalAlbum}`); + + commit('setFilesAndMeta', { ...response, page }); + + return response; + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + + return null; } }; @@ -172,6 +184,9 @@ export const mutations = { state.fileTagsMap[fileId].splice(foundIndex, 1); } }, + setShowList(state, showList) { + state.showList = showList; + }, resetState(state) { Object.assign(state, getDefaultState()); } -- cgit v1.2.3 From fb2c27086f570fec60f4d52dcc9ca80e53186293 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 24 Dec 2020 23:45:16 +0900 Subject: Fix ESLint rules once and for all --- src/site/store/albums.js | 4 ++-- src/site/store/auth.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/albums.js b/src/site/store/albums.js index 4f796a1..8be0230 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -9,8 +9,8 @@ export const state = () => ({ }); export const getters = { - isExpanded: (state) => (id) => state.expandedAlbums.indexOf(id) > -1, - getDetails: (state) => (id) => state.albumDetails[id] || {} + isExpanded: state => id => state.expandedAlbums.indexOf(id) > -1, + getDetails: state => id => state.albumDetails[id] || {} }; export const actions = { diff --git a/src/site/store/auth.js b/src/site/store/auth.js index 85e3a39..51a79d6 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -11,9 +11,9 @@ const getDefaultState = () => ({ export const state = getDefaultState; export const getters = { - isLoggedIn: (state) => state.loggedIn, - getApiKey: (state) => state.user?.apiKey, - getToken: (state) => state.token + isLoggedIn: state => state.loggedIn, + getApiKey: state => state.user?.apiKey, + getToken: state => state.token }; export const actions = { -- cgit v1.2.3 From 7190e035b441aef96c8249bb02d12f7cd55a17d9 Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 20:17:47 +0900 Subject: chore: style changes --- src/site/store/images.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/site/store') diff --git a/src/site/store/images.js b/src/site/store/images.js index 69b4f5e..535e7cd 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -5,7 +5,7 @@ export const getDefaultState = () => ({ isLoading: false, pagination: { page: 1, - limit: 30, + limit: 50, totalFiles: 0 }, search: '', -- cgit v1.2.3 From edb3bed98864e34695a5ae0093c414a2b578073a Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 28 Dec 2020 00:10:59 +0900 Subject: feat: Add warning to nsfw albums --- src/site/store/albums.js | 12 ++++++++++++ src/site/store/index.js | 8 -------- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/albums.js b/src/site/store/albums.js index 8be0230..b109af6 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -73,6 +73,15 @@ export const actions = { return response; }, + async toggleNsfw({ commit }, { albumId, nsfw }) { + const response = await this.$axios.$post('album/edit', { + id: albumId, + nsfw + }); + commit('updateNsfw', { albumId, nsfw }); + + return response; + }, async deleteLink({ commit }, { albumId, identifier }) { const response = await this.$axios.$delete(`album/link/delete/${identifier}`); @@ -118,6 +127,9 @@ export const mutations = { const link = state.albumDetails[albumId].links[foundIndex]; state.albumDetails[albumId].links[foundIndex] = { ...link, ...linkOpts }; }, + updateNsfw(state, { albumId, value }) { + state.list.find(el => el.id === albumId).nsfw = value; + }, removeAlbumLink(state, { albumId, identifier }) { const foundIndex = state.albumDetails[albumId].links.findIndex(({ identifier: id }) => id === identifier); if (foundIndex > -1) state.albumDetails[albumId].links.splice(foundIndex, 1); diff --git a/src/site/store/index.js b/src/site/store/index.js index c5d9a23..94d673f 100644 --- a/src/site/store/index.js +++ b/src/site/store/index.js @@ -1,6 +1,5 @@ import config from '../../../dist/config.json'; -// eslint-disable-next-line import/prefer-default-export export const actions = { async nuxtClientInit({ commit, dispatch }) { commit('config/set', config); @@ -11,11 +10,4 @@ export const actions = { commit('auth/setToken', cookies.token); return dispatch('auth/verify'); } - /* alert({ commit }, payload) { - if (!payload) return commit('alert', null); - commit('alert', { - text: payload.text, - error: payload.error - }); - } */ }; -- cgit v1.2.3 From 13058d99d658c0920ce75b79d6b24df18a873ea9 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Sun, 27 Dec 2020 18:18:06 +0200 Subject: fix: nsfw album toggle doesn't propagate the changes properly fix: add nsfw flag to the booleanFields in knex postProcessResponse --- src/site/store/albums.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/site/store') diff --git a/src/site/store/albums.js b/src/site/store/albums.js index b109af6..bbd2db6 100644 --- a/src/site/store/albums.js +++ b/src/site/store/albums.js @@ -127,8 +127,8 @@ export const mutations = { const link = state.albumDetails[albumId].links[foundIndex]; state.albumDetails[albumId].links[foundIndex] = { ...link, ...linkOpts }; }, - updateNsfw(state, { albumId, value }) { - state.list.find(el => el.id === albumId).nsfw = value; + updateNsfw(state, { albumId, nsfw }) { + state.list.find(el => el.id === albumId).nsfw = nsfw; }, removeAlbumLink(state, { albumId, identifier }) { const foundIndex = state.albumDetails[albumId].links.findIndex(({ identifier: id }) => id === identifier); -- cgit v1.2.3