aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/site/assets/styles/_colors.scss10
-rw-r--r--src/site/assets/styles/style.scss139
-rw-r--r--src/site/components/album/AlbumDetails.vue85
-rw-r--r--src/site/components/album/AlbumEntry.vue11
-rw-r--r--src/site/components/grid/Grid.vue12
-rw-r--r--src/site/pages/dashboard/admin/file/_id.vue2
-rw-r--r--src/site/pages/dashboard/admin/user/_id.vue1
-rw-r--r--src/site/pages/dashboard/albums/_id.vue60
-rw-r--r--src/site/pages/dashboard/albums/index.vue28
-rw-r--r--src/site/pages/dashboard/tags/index.vue2
-rw-r--r--src/site/store/album.js0
-rw-r--r--src/site/store/albums.js75
12 files changed, 289 insertions, 136 deletions
diff --git a/src/site/assets/styles/_colors.scss b/src/site/assets/styles/_colors.scss
index b8861d2..6693d8a 100644
--- a/src/site/assets/styles/_colors.scss
+++ b/src/site/assets/styles/_colors.scss
@@ -10,6 +10,10 @@ $backgroundAccent: #20222b;
$backgroundAccentLighter: #53555e;
$backgroundLight1: #f5f6f8;
+$scheme-main: $background;
+$scheme-main-bis: $backgroundAccent;
+$scheme-main-ter: $backgroundAccentLighter;
+
// customize navbar
$navbar-background-color: $backgroundAccent;
$navbar-item-color: #f5f6f8;
@@ -47,6 +51,10 @@ $pagination-current-background-color: $base-3;
$pagination-current-border-color: $base-2;
// loading
-
$loading-background: rgba(0, 0, 0, 0.8);
$loading-background: rgba(40, 40, 40, 0.66);
+
+// dialogs
+$modal-card-body-background-color: $background;
+$modal-card-head-background-color: $backgroundAccent;
+$modal-card-foot-border-top: 1px solid rgba(255, 255, 255, 0.1098);
diff --git a/src/site/assets/styles/style.scss b/src/site/assets/styles/style.scss
index 69d15d3..6c939b5 100644
--- a/src/site/assets/styles/style.scss
+++ b/src/site/assets/styles/style.scss
@@ -1,15 +1,16 @@
// Let's first take care of having the customized colors ready.
-@import "./_colors.scss";
+@import './_colors.scss';
// Bulma/Buefy customization
-@import "../../../node_modules/bulma/sass/utilities/_all.sass";
+@import '../../../node_modules/bulma/sass/utilities/_all.sass';
$body-size: 14px !default;
-$family-primary: 'Nunito', BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
+$family-primary: 'Nunito', BlinkMacSystemFont, -apple-system, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
+ 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
$size-normal: 1rem;
-@import "../../../node_modules/bulma/bulma.sass";
-@import "../../../node_modules/buefy/src/scss/buefy.scss";
+@import '../../../node_modules/bulma/bulma.sass';
+@import '../../../node_modules/buefy/src/scss/buefy.scss';
html {
// font-size: 100%;
@@ -18,9 +19,9 @@ html {
}
a {
- color: #5E81AC;
+ color: #5e81ac;
&:hover {
- color: #81A1C1;
+ color: #81a1c1;
text-decoration: underline;
}
}
@@ -43,10 +44,18 @@ h4 {
}
@for $i from 1 through 10 {
- .mt#{$i} { margin-top: $i + em !important; }
- .mb#{$i} { margin-bottom: $i + em !important; }
- .ml#{$i} { margin-left: $i + em !important; }
- .mr#{$i} { margin-right: $i + em !important; }
+ .mt#{$i} {
+ margin-top: $i + em !important;
+ }
+ .mb#{$i} {
+ margin-bottom: $i + em !important;
+ }
+ .ml#{$i} {
+ margin-left: $i + em !important;
+ }
+ .mr#{$i} {
+ margin-right: $i + em !important;
+ }
}
.text-center {
@@ -58,8 +67,12 @@ hr {
height: 1px;
}
// Bulma color changes.
-.tooltip.is-top.is-primary:before { border-top: 5px solid #20222b; }
-.tooltip.is-primary:after { background: #20222b; }
+.tooltip.is-top.is-primary:before {
+ border-top: 5px solid #20222b;
+}
+.tooltip.is-primary:after {
+ background: #20222b;
+}
div#drag-overlay {
position: fixed;
@@ -93,7 +106,6 @@ div#drag-overlay {
}
}
-
section.hero {
&.dashboard {
// background-color: $backgroundLight1 !important;
@@ -103,10 +115,12 @@ section.hero {
}
}
-section input, section a.button {
+section input,
+section a.button {
font-size: 14px !important;
}
-section input, section p.control a.button {
+section input,
+section p.control a.button {
border-left: 0px !important;
border-top: 0px !important;
border-right: 0px !important;
@@ -114,13 +128,15 @@ section input, section p.control a.button {
box-shadow: 0 0 0 !important;
}
-section p.control a.button { margin-left: 10px !important; }
+section p.control a.button {
+ margin-left: 10px !important;
+}
section p.control button {
height: 100%;
font-size: 12px;
}
-.switch input[type=checkbox] + .check:before {
+.switch input[type='checkbox'] + .check:before {
background: #fbfbfb;
}
@@ -128,7 +144,8 @@ section p.control button {
Register and Login forms
*/
-section.hero.is-login, section.hero.is-register {
+section.hero.is-login,
+section.hero.is-register {
a {
font-size: 1.25em;
line-height: 2.5em;
@@ -174,18 +191,22 @@ section#register a.is-text {
font-size: 1.25em;
line-height: 2.5em;
}
-*/
+
.modal-card-head, .modal-card-foot {
background: $backgroundLight1;
}
+*/
.switch {
margin-top: 5px;
}
-.input, .taginput .taginput-container.is-focusable, .textarea, .select select {
+.input,
+.taginput .taginput-container.is-focusable,
+.textarea,
+.select select {
border: 2px solid #21252d;
- border-radius: .3em !important;
+ border-radius: 0.3em !important;
background: rgba(0, 0, 0, 0.15);
padding: 1rem;
color: $textColor;
@@ -203,9 +224,9 @@ button.button.is-primary {
border: 2px solid #21252d;
color: $textColor;
font-size: 1rem;
- border-top: 0;
- border-left: 0;
- border-right: 0;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
&:hover {
background-color: $base-2;
}
@@ -224,13 +245,16 @@ svg.waves {
user-select: none;
overflow: hidden;
}
-div.field-body > div.field { text-align: left; }
+div.field-body > div.field {
+ text-align: left;
+}
table.table {
background: $base-2;
color: $textColor;
border: 0;
thead {
- th, td {
+ th,
+ td {
color: $textColor;
}
}
@@ -244,60 +268,55 @@ table.table {
}
}
}
- th, td {
+ th,
+ td {
border-color: #ffffff1c;
}
}
// vue-bar
.vb > .vb-dragger {
- z-index: 5;
- width: 12px;
- right: 0;
+ z-index: 5;
+ width: 12px;
+ right: 0;
}
.vb > .vb-dragger > .vb-dragger-styler {
- -webkit-backface-visibility: hidden;
- backface-visibility: hidden;
- -webkit-transform: rotate3d(0,0,0,0);
- transform: rotate3d(0,0,0,0);
- -webkit-transition:
- background-color 100ms ease-out,
- margin 100ms ease-out,
- height 100ms ease-out;
- transition:
- background-color 100ms ease-out,
- margin 100ms ease-out,
- height 100ms ease-out;
- background-color: $backgroundAccent;
- margin: 5px 5px 5px 0;
- border-radius: 20px;
- height: calc(100% - 10px);
- display: block;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: rotate3d(0, 0, 0, 0);
+ transform: rotate3d(0, 0, 0, 0);
+ -webkit-transition: background-color 100ms ease-out, margin 100ms ease-out, height 100ms ease-out;
+ transition: background-color 100ms ease-out, margin 100ms ease-out, height 100ms ease-out;
+ background-color: $backgroundAccent;
+ margin: 5px 5px 5px 0;
+ border-radius: 20px;
+ height: calc(100% - 10px);
+ display: block;
}
.vb.vb-scrolling-phantom > .vb-dragger > .vb-dragger-styler {
- background-color: $backgroundAccentLighter;
+ background-color: $backgroundAccentLighter;
}
.vb > .vb-dragger:hover > .vb-dragger-styler {
- background-color: $backgroundAccentLighter;
- margin: 0px;
- height: 100%;
+ background-color: $backgroundAccentLighter;
+ margin: 0px;
+ height: 100%;
}
.vb.vb-dragging > .vb-dragger > .vb-dragger-styler {
- background-color: $backgroundAccentLighter;
- margin: 0px;
- height: 100%;
+ background-color: $backgroundAccentLighter;
+ margin: 0px;
+ height: 100%;
}
.vb.vb-dragging-phantom > .vb-dragger > .vb-dragger-styler {
- background-color: $backgroundAccentLighter;
+ background-color: $backgroundAccentLighter;
}
-.vb-content{
- overflow: auto !important
+.vb-content {
+ overflow: auto !important;
}
// helpers
@@ -313,7 +332,7 @@ table.table {
height: max-content;
}
-.pagination a, .pagination a:hover {
+.pagination a,
+.pagination a:hover {
text-decoration: none;
}
-
diff --git a/src/site/components/album/AlbumDetails.vue b/src/site/components/album/AlbumDetails.vue
index a02fe55..b646cb0 100644
--- a/src/site/components/album/AlbumDetails.vue
+++ b/src/site/components/album/AlbumDetails.vue
@@ -25,13 +25,13 @@
label="Allow download"
centered>
<b-switch v-model="props.row.enableDownload"
- @input="linkOptionsChanged(props.row)" />
+ @input="updateLinkOptions(albumId, props.row)" />
</b-table-column>
<b-table-column field="enabled"
numeric>
<button class="button is-danger"
- @click="promptDeleteAlbumLink(props.row.identifier)">Delete link</button>
+ @click="promptDeleteAlbumLink(albumId, props.row.identifier)">Delete link</button>
</b-table-column>
</template>
<template slot="empty">
@@ -42,6 +42,7 @@
Nothing here
</div>
</template>
+
<template slot="footer">
<div class="level is-paddingless">
<div class="level-left">
@@ -70,7 +71,7 @@
</template>
<script>
-import { mapState } from 'vuex';
+import { mapState, mapActions } from 'vuex';
export default {
props: {
@@ -90,55 +91,65 @@ export default {
},
computed: mapState(['config']),
methods: {
+ ...mapActions({
+ deleteAlbumAction: 'albums/deleteAlbum',
+ deleteAlbumLinkAction: 'albums/deleteLink',
+ updateLinkOptionsAction: 'albums/updateLinkOptions',
+ createLinkAction: 'albums/createLink',
+ alert: 'alert/set'
+ }),
promptDeleteAlbum(id) {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Are you sure you want to delete this album?',
onConfirm: () => this.deleteAlbum(id)
});
},
- async deleteAlbum(id) {
- const response = await this.$axios.$delete(`album/${id}`);
- this.getAlbums();
- return this.$buefy.toast.open(response.message);
- },
- promptDeleteAlbumLink(identifier) {
+ promptDeleteAlbumLink(albumId, identifier) {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Are you sure you want to delete this album link?',
- onConfirm: () => this.deleteAlbumLink(identifier)
+ onConfirm: () => this.deleteAlbumLink({ albumId, identifier })
});
},
- async deleteAlbumLink(identifier) {
- const response = await this.$axios.$delete(`album/link/delete/${identifier}`);
- return this.$buefy.toast.open(response.message);
+ async deleteAlbum(id) {
+ try {
+ const response = await this.deleteAlbumAction(id);
+
+ this.alert({ text: response.message, error: false });
+ } catch (e) {
+ this.alert({ text: e.message, error: true });
+ }
},
- async linkOptionsChanged(link) {
- const response = await this.$axios.$post(`album/link/edit`,
- {
- identifier: link.identifier,
- enableDownload: link.enableDownload,
- enabled: link.enabled
- });
- this.$buefy.toast.open(response.message);
+ async deleteAlbumLink(id) {
+ try {
+ const response = await this.deleteAlbumLinkAction(id);
+
+ this.alert({ text: response.message, error: false });
+ } catch (e) {
+ this.alert({ text: e.message, error: true });
+ }
},
- async createLink(album) {
- album.isCreatingLink = true;
- // Since we actually want to change the state even if the call fails, use a try catch
+ async createLink(albumId) {
+ this.isCreatingLink = true;
try {
- const response = await this.$axios.$post(`album/link/new`,
- { albumId: album.id });
- this.$buefy.toast.open(response.message);
- album.links.push({
- identifier: response.identifier,
- views: 0,
- enabled: true,
- enableDownload: true,
- expiresAt: null
- });
- } catch (error) {
- //
+ const response = await this.createLinkAction(albumId);
+
+ this.alert({ text: response.message, error: false });
+ } catch (e) {
+ this.alert({ text: e.message, error: true });
} finally {
- album.isCreatingLink = false;
+ this.isCreatingLink = false;
}
+ },
+ async updateLinkOptions(albumId, linkOpts) {
+ try {
+ const response = await this.updateLinkOptionsAction({ albumId, linkOpts });
+
+ this.alert({ text: response.message, error: false });
+ } catch (e) {
+ this.alert({ text: e.message, error: true });
+ }
}
}
};
diff --git a/src/site/components/album/AlbumEntry.vue b/src/site/components/album/AlbumEntry.vue
index 4d23d6c..28e434a 100644
--- a/src/site/components/album/AlbumEntry.vue
+++ b/src/site/components/album/AlbumEntry.vue
@@ -14,7 +14,9 @@
<h4>
<router-link :to="`/dashboard/albums/${album.id}`">{{ album.name }}</router-link>
</h4>
- <span>Updated <timeago :since="album.editedAt" /></span>
+ <span>
+ Created <span class="is-inline has-text-weight-semibold"><timeago :since="album.createdAt" /></span>
+ </span>
<span>{{ album.fileCount || 0 }} files</span>
</div>
<div class="latest is-hidden-mobile">
@@ -40,7 +42,7 @@
</div>
<AlbumDetails v-if="isExpanded"
- :details="getDetails"
+ :details="getDetails(album.id)"
:albumId="album.id" />
</div>
</template>
@@ -62,13 +64,10 @@ export default {
computed: {
...mapGetters({
isExpandedGetter: 'albums/isExpanded',
- getDetailsGetter: 'albums/getDetails'
+ getDetails: 'albums/getDetails'
}),
isExpanded() {
return this.isExpandedGetter(this.album.id);
- },
- getDetails() {
- return this.getDetailsGetter(this.album.id);
}
},
methods: {
diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index a06eabf..956dd28 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -29,12 +29,6 @@
<Waterfall v-if="showWaterfall"
:gutterWidth="10"
:gutterHeight="4">
- <input v-if="enableSearch"
- v-model="searchTerm"
- type="text"
- placeholder="Search..."
- @input="search()"
- @keyup.enter="search()">
<WaterfallItem v-for="(item, index) in gridFiles"
:key="item.id"
:width="width"
@@ -167,7 +161,7 @@
</template>
<template slot="footer">
<div class="has-text-right has-text-default">
- {{ files.length }} files
+ Showing {{ files.length }} files ({{ total }} total)
</div>
</template>
</b-table>
@@ -213,6 +207,10 @@ export default {
type: Array,
default: () => []
},
+ total: {
+ type: Number,
+ default: 0
+ },
fixed: {
type: Boolean,
default: false
diff --git a/src/site/pages/dashboard/admin/file/_id.vue b/src/site/pages/dashboard/admin/file/_id.vue
index 5821292..5853770 100644
--- a/src/site/pages/dashboard/admin/file/_id.vue
+++ b/src/site/pages/dashboard/admin/file/_id.vue
@@ -130,6 +130,7 @@ export default {
methods: {
promptDisableUser() {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Are you sure you want to disable the account of the user that uploaded this file?',
onConfirm: () => this.disableUser()
});
@@ -142,6 +143,7 @@ export default {
},
promptBanIP() {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Are you sure you want to ban the IP this file was uploaded from?',
onConfirm: () => this.banIP()
});
diff --git a/src/site/pages/dashboard/admin/user/_id.vue b/src/site/pages/dashboard/admin/user/_id.vue
index 2a56c34..8c73037 100644
--- a/src/site/pages/dashboard/admin/user/_id.vue
+++ b/src/site/pages/dashboard/admin/user/_id.vue
@@ -85,6 +85,7 @@ export default {
methods: {
promptDisableUser() {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Are you sure you want to disable the account of the user that uploaded this file?',
onConfirm: () => this.disableUser()
});
diff --git a/src/site/pages/dashboard/albums/_id.vue b/src/site/pages/dashboard/albums/_id.vue
index 47e7057..c082b63 100644
--- a/src/site/pages/dashboard/albums/_id.vue
+++ b/src/site/pages/dashboard/albums/_id.vue
@@ -10,25 +10,53 @@
<Sidebar />
</div>
<div class="column">
- <h2 class="subtitle">Files</h2>
+ <nav class="level">
+ <div class="level-left">
+ <div class="level-item">
+ <h2 class="subtitle">Files</h2>
+ </div>
+ </div>
+ <div class="level-right">
+ <div class="level-item">
+ <b-field>
+ <b-input
+ placeholder="Search"
+ type="search"/>
+ <p class="control">
+ <button
+ outlined
+ class="button is-primary">
+ Search
+ </button>
+ </p>
+ </b-field>
+ </div>
+ </div>
+ </nav>
+
<hr>
<Grid v-if="files.length"
- :files="files" />
-
- <b-pagination
- v-if="count > perPage"
- :total="count"
- :per-page="perPage"
- :current.sync="current"
- class="pagination"
- icon-prev="icon-interface-arrow-left"
- icon-next="icon-interface-arrow-right"
- icon-pack="icon"
- aria-next-label="Next page"
- aria-previous-label="Previous page"
- aria-page-label="Page"
- aria-current-label="Current page" />
+ :files="files"
+ :total="count">
+ <template v-slot:pagination>
+ <b-pagination
+ v-if="count > perPage"
+ :total="count"
+ :per-page="perPage"
+ :current.sync="current"
+ range-before="2"
+ range-after="2"
+ class="pagination-slot"
+ icon-prev="icon-interface-arrow-left"
+ icon-next="icon-interface-arrow-right"
+ icon-pack="icon"
+ aria-next-label="Next page"
+ aria-previous-label="Previous page"
+ aria-page-label="Page"
+ aria-current-label="Current page" />
+ </template>
+ </Grid>
</div>
</div>
</div>
diff --git a/src/site/pages/dashboard/albums/index.vue b/src/site/pages/dashboard/albums/index.vue
index 2a54ab8..a010254 100644
--- a/src/site/pages/dashboard/albums/index.vue
+++ b/src/site/pages/dashboard/albums/index.vue
@@ -18,7 +18,8 @@
@keyup.enter.native="createAlbum" />
<p class="control">
<button outlined
- class="button is-primary"
+ class="button is-black"
+ :disabled="isCreatingAlbum"
@click="createAlbum">Create album</button>
</p>
</b-field>
@@ -37,7 +38,7 @@
</template>
<script>
-import { mapState } from 'vuex';
+import { mapState, mapActions } from 'vuex';
import Sidebar from '~/components/sidebar/Sidebar.vue';
import AlbumEntry from '~/components/album/AlbumEntry.vue';
@@ -51,7 +52,8 @@ export default {
}],
data() {
return {
- newAlbumName: null
+ newAlbumName: null,
+ isCreatingAlbum: false
};
},
computed: mapState(['config', 'albums']),
@@ -59,13 +61,23 @@ export default {
return { title: 'Uploads' };
},
methods: {
+ ...mapActions({
+ 'alert': 'alert/set'
+ }),
async createAlbum() {
if (!this.newAlbumName || this.newAlbumName === '') return;
- const response = await this.$axios.$post(`album/new`,
- { name: this.newAlbumName });
- this.newAlbumName = null;
- this.$buefy.toast.open(response.message);
- this.getAlbums();
+
+ this.isCreatingAlbum = true;
+ try {
+ const response = await this.$store.dispatch('albums/createAlbum', this.newAlbumName);
+
+ this.alert({ text: response.message, error: false });
+ } catch (e) {
+ this.alert({ text: e.message, error: true });
+ } finally {
+ this.isCreatingAlbum = false;
+ this.newAlbumName = null;
+ }
}
}
};
diff --git a/src/site/pages/dashboard/tags/index.vue b/src/site/pages/dashboard/tags/index.vue
index 7c295b7..a9476da 100644
--- a/src/site/pages/dashboard/tags/index.vue
+++ b/src/site/pages/dashboard/tags/index.vue
@@ -228,12 +228,14 @@ export default {
methods: {
promptDeleteTag(id) {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Are you sure you want to delete this tag?',
onConfirm: () => this.promptPurgeTag(id)
});
},
promptPurgeTag(id) {
this.$buefy.dialog.confirm({
+ type: 'is-danger',
message: 'Would you like to delete every file associated with this tag?',
cancelText: 'No',
confirmText: 'Yes',
diff --git a/src/site/store/album.js b/src/site/store/album.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/site/store/album.js
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);