feat: refactor most of the album components to use store for presentation and actions
This commit is contained in:
parent
836a01327d
commit
92be4504cc
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 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 createLink(album) {
|
||||
album.isCreatingLink = true;
|
||||
// Since we actually want to change the state even if the call fails, use a try catch
|
||||
async deleteAlbum(id) {
|
||||
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.deleteAlbumAction(id);
|
||||
|
||||
this.alert({ text: response.message, error: false });
|
||||
} catch (e) {
|
||||
this.alert({ text: e.message, error: true });
|
||||
}
|
||||
},
|
||||
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(albumId) {
|
||||
this.isCreatingLink = true;
|
||||
try {
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
});
|
||||
|
|
|
@ -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()
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue