clean up wallpapers, move everything to store

This commit is contained in:
Gamebrary 2020-08-25 16:37:33 -07:00
parent 91f0d78b26
commit 18d0403172
8 changed files with 277 additions and 172 deletions

View file

@ -15,13 +15,14 @@
</template>
<tags-settings />
<account-settings />
<file-settings />
<wallpaper-settings />
<b-dropdown-divider />
<releases />
<about />
<b-dropdown-divider />
<!-- language -->
<!-- theme -->
<account-settings />
<sign-out />
</b-dropdown>
</b-navbar-nav>
@ -30,7 +31,7 @@
<script>
import TagsSettings from '@/components/Settings/TagsSettings';
import AccountSettings from '@/components/Settings/AccountSettings';
import FileSettings from '@/components/Settings/FileSettings';
import WallpaperSettings from '@/components/Settings/WallpaperSettings';
import Releases from '@/components/Settings/Releases';
import SignOut from '@/components/Settings/SignOut';
import About from '@/components/Settings/About';
@ -40,7 +41,7 @@ export default {
components: {
TagsSettings,
AccountSettings,
FileSettings,
WallpaperSettings,
Releases,
SignOut,
About,

View file

@ -11,6 +11,7 @@
title="Board settings"
scrollable
@show="init"
@hide="hide"
>
<form ref="boardSettingsForm" @submit.stop.prevent="submit">
<b-form-group
@ -25,7 +26,7 @@
</b-form-group>
<b-form-group
label="Board descriptiopn"
label="Board description"
label-for="description"
>
<b-form-textarea
@ -152,6 +153,10 @@ export default {
},
methods: {
hide() {
this.$bus.$off('WALLPAPER_UPLOADED', this.loadWallpapers);
},
async loadWallpapers() {
this.wallpapers = [];
@ -159,7 +164,7 @@ export default {
// TODO: use promise all instead
files.forEach(async (path) => {
const url = await this.$store.dispatch('LOAD_FIRESTORE_FILE', path);
const url = await this.$store.dispatch('LOAD_WALLPAPER', path);
const name = path.split(`${this.user.uid}/wallpapers/`)[1];
@ -175,7 +180,7 @@ export default {
async setWallpaper(file) {
this.wallpaper = file.path;
this.wallpaperUrl = await this.$store.dispatch('LOAD_FIRESTORE_FILE', file.path);
this.wallpaperUrl = await this.$store.dispatch('LOAD_WALLPAPER', file.path);
},
submit(e) {
@ -187,6 +192,8 @@ export default {
},
async init() {
this.$bus.$on('WALLPAPER_UPLOADED', this.loadWallpapers);
const { board } = this;
this.description = board.description;
@ -195,7 +202,7 @@ export default {
this.theme = board.theme || 'default';
this.wallpaper = board.wallpaper;
this.wallpaperUrl = board.wallpaper
? await this.$store.dispatch('LOAD_FIRESTORE_FILE', board.wallpaper)
? await this.$store.dispatch('LOAD_WALLPAPER', board.wallpaper)
: null;
this.loadWallpapers();

View file

@ -1,157 +0,0 @@
<template lang="html">
<b-dropdown-item v-b-modal:file-settings>
<b-icon-tags class="mr-1" />
Manage files
<b-modal
id="file-settings"
title="Manage Files"
hide-footer
scrollable
size="xl"
@show="loadWallpapers"
>
<b-row>
<b-col cols="12" lg="6">
<h5>Wallpapers</h5>
<b-form-file
v-model="file"
accept="image/*"
class="mb-3"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
/>
<b-button @click="uploadFile" :disabled="!Boolean(file)">
Upload
</b-button>
</b-col>
</b-row>
<hr>
Files
<b-form-row>
<b-col
v-for="(file, index) in wallpapers"
:key="file.name"
cols="6"
sm="4"
lg="3"
>
<b-card
:header="file.name"
class="mb-2"
header-class="py-0 px-2"
body-class="d-flex p-0 text-center justify-content-center align-items-center"
header-tag="small"
>
<b-img
:src="file.url"
:alt="file.name"
fluid
/>
<b-button
class="position-absolute delete-file"
variant="danger"
size="sm"
@click="confirmDeleteFile({ file, index })"
>
<b-icon-trash />
</b-button>
</b-card>
</b-col>
</b-form-row>
</b-modal>
</b-dropdown-item>
</template>
<script>
import firebase from 'firebase/app';
import 'firebase/firestore';
import { mapState } from 'vuex';
export default {
data() {
return {
file: null,
saving: false,
loading: false,
wallpapers: [],
};
},
computed: {
...mapState(['user', 'board']),
},
methods: {
async loadWallpapers() {
this.wallpapers = [];
this.loading = true;
const files = await this.$store.dispatch('LOAD_WALLPAPERS');
// TODO: use promise all instead
files.forEach(async (path) => {
const url = await this.$store.dispatch('LOAD_FIRESTORE_FILE', path);
const name = path.split(`${this.user.uid}/wallpapers/`)[1];
this.wallpapers.push({ name, url, path });
});
},
uploadFile() {
const { file, user } = this;
this.saving = true;
firebase.storage().ref(`${user.uid}/wallpapers/${file.name}`).put(file)
.then(({ state }) => {
if (state === 'success') {
this.$bvToast.toast(file.name, { title: 'File uploaded', variant: 'success' });
}
});
},
confirmDeleteFile({ file, index }) {
this.$bvModal.msgBoxConfirm(`${file.name} will be permanently removed`, {
title: 'Are you sure you want to delete this file?',
okVariant: 'danger',
okTitle: 'Yes',
})
.then((value) => {
if (value) {
this.deleteFile({ file, index });
}
});
},
async deleteFile({ file, index }) {
await this.$store.dispatch('DELETE_FIRESTORE_FILE', file.path);
this.$bvToast.toast(file.name, { title: 'File deleted', variant: 'success' });
this.wallpapers.splice(index, 1);
if (this.board && this.board.wallpaper && this.board.wallpaper === file.path) {
this.$bus.$emit('RELOAD_WALLPAPER');
}
},
},
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
img {
max-height: 140px;
}
.delete-file {
bottom: .5rem;
right: .5rem;
}
</style>

View file

@ -0,0 +1,179 @@
<template lang="html">
<b-dropdown-item v-b-modal:file-settings>
<b-icon-file-richtext class="mr-1" />
Wallpapers
<b-modal
id="file-settings"
title="Wallpapers"
hide-footer
scrollable
size="lg"
@show="loadWallpapers"
>
<b-row>
<b-col cols="12" lg="6">
<b-form-group
label="Upload wallpaper"
label-for="input-1"
description="Image files only"
>
<b-form-file
v-model="file"
accept="image/*"
placeholder="Choose a file or drop it here..."
/>
</b-form-group>
<b-alert v-if="isDuplicate && !saving" show variant="warning">
You already have a file named <strong>{{ file.name }}</strong>
</b-alert>
<b-button
@click="uploadWallpaper"
variant="primary"
:disabled="!Boolean(file) || saving || isDuplicate"
>
<b-spinner small v-if="saving" />
<span v-else>Upload</span>
</b-button>
</b-col>
</b-row>
<hr>
<b-form-row v-if="wallpapers.length">
<b-col cols="12">
<h5>My Wallpapers</h5>
</b-col>
<b-col
v-for="wallpaper in wallpapers"
:key="wallpaper.name"
cols="6"
sm="4"
lg="3"
>
<b-card
class="mb-2"
header-class="py-0 px-2"
body-class="d-flex p-0 text-center justify-content-center align-items-center"
header-tag="small"
>
<b-img
:src="wallpaper.url"
:alt="wallpaper.name"
fluid
/>
<b-button
class="position-absolute delete-file"
variant="danger"
size="sm"
@click="confirmDeleteWallpaper(wallpaper)"
>
<b-icon-trash />
</b-button>
</b-card>
</b-col>
</b-form-row>
<b-alert show v-else>You don't have any wallpapers.</b-alert>
</b-modal>
</b-dropdown-item>
</template>
<script>
import { mapState } from 'vuex';
export default {
data() {
return {
file: null,
saving: false,
loading: false,
wallpaperUrls: [],
};
},
computed: {
...mapState(['user', 'board', 'wallpapers']),
existingFiles() {
return this.wallpapers.map(({ name }) => name);
},
isDuplicate() {
const { file, existingFiles } = this;
return file && file.name && existingFiles.includes(file.name);
},
},
methods: {
async loadWallpapers() {
this.loading = true;
await this.$store.dispatch('LOAD_WALLPAPERS')
.catch(() => {
this.$bvToast.toast('There was an error loading wallpapers', { title: 'Error', variant: 'danger' });
});
},
async uploadWallpaper() {
const { file } = this;
this.saving = true;
await this.$store.dispatch('UPLOAD_WALLPAPER', file)
.catch(() => {
this.saving = false;
this.$bvToast.toast('There was an error uploading wallpaper', { title: 'Error', variant: 'danger' });
});
this.file = null;
this.saving = false;
this.$bvToast.toast(file.name, { title: 'File uploaded', variant: 'success' });
this.$bus.$emit('WALLPAPER_UPLOADED');
},
confirmDeleteWallpaper(file) {
this.$bvModal.msgBoxConfirm('Wallpaper will be permanently removed', {
title: 'Are you sure you want to delete this file?',
okVariant: 'danger',
okTitle: 'Yes',
})
.then((value) => {
if (value) {
this.deleteFile(file);
}
});
},
async deleteFile(file) {
await this.$store.dispatch('DELETE_WALLPAPER', file)
.catch(() => {
this.$bvToast.toast('There was an error deleting wallpaper', { title: 'Error', variant: 'danger' });
});
this.$bvToast.toast(file.name, { title: 'File deleted', variant: 'success' });
// const { board } = this;
// TODO: handle wallpapers in use
// if (board.wallpaper && this.board.wallpaper === file.path) {
// this.$bus.$emit('RELOAD_WALLPAPER');
// }
},
},
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
img {
max-height: 140px;
}
.delete-file {
bottom: .5rem;
right: .5rem;
}
</style>

View file

@ -94,14 +94,14 @@ export default {
async loadBoardWallpaper() {
this.wallpaperUrl = this.board.wallpaper
? await this.$store.dispatch('LOAD_FIRESTORE_FILE', this.board.wallpaper)
? await this.$store.dispatch('LOAD_WALLPAPER', this.board.wallpaper)
: null;
},
loadBoardGames() {
const { lists } = this.board;
if (lists.length === 0) {
if (lists && lists.length === 0) {
this.$bvModal.show('add-list');
}

View file

@ -95,17 +95,18 @@ export default {
},
DELETE_FIRESTORE_FILE(context, path) {
DELETE_WALLPAPER({ commit }, { fullPath }) {
return new Promise((resolve, reject) => {
firebase.storage().ref(path).delete()
firebase.storage().ref(fullPath).delete()
.then(() => {
commit('REMOVE_WALLPAPER', fullPath);
resolve();
})
.catch(reject);
});
},
LOAD_FIRESTORE_FILE(context, path) {
LOAD_WALLPAPER(context, path) {
const storage = firebase.storage().ref();
return new Promise((resolve, reject) => {
@ -117,13 +118,72 @@ export default {
});
},
async LOAD_WALLPAPERS({ state }) {
// TODO: commit wallpapers to store
LOAD_WALLPAPERS({ state, commit }) {
const storage = firebase.storage().ref(`${state.user.uid}/wallpapers`);
return new Promise((resolve, reject) => {
storage
.listAll()
.then(({ items }) => resolve(items.map(({ fullPath }) => fullPath)))
.then(({ items }) => {
const wallpapers = items.map(({ fullPath, name }) => {
const wallpaper = {
fullPath,
name,
};
return wallpaper;
});
// TODO: refactor? there's gotta be a better way to do this
const fetchedUrls = [];
wallpapers.forEach(({ fullPath }, index) => {
firebase.storage()
.ref()
.child(fullPath).getDownloadURL()
.then((url) => {
fetchedUrls.push(url);
wallpapers[index].url = url;
if (fetchedUrls.length === wallpapers.length) {
commit('SET_WALLPAPERS', wallpapers);
resolve();
}
})
.catch(reject);
});
})
.catch(reject);
});
},
UPLOAD_WALLPAPER({ state, commit }, file) {
return new Promise((resolve, reject) => {
firebase.storage()
.ref(`${state.user.uid}/wallpapers/${file.name}`)
.put(file)
.then((response) => {
if (response.state === 'success') {
const { metadata: { fullPath, name } } = response;
firebase.storage()
.ref()
.child(fullPath).getDownloadURL()
.then((url) => {
const wallpaper = {
fullPath,
name,
url,
};
commit('ADD_WALLPAPER', wallpaper);
resolve();
})
.catch(reject);
}
})
.catch(reject);
});
},

View file

@ -42,6 +42,20 @@ export default {
state.boardGames = boardGames;
},
SET_WALLPAPERS(state, wallpapers) {
state.wallpapers = wallpapers;
},
REMOVE_WALLPAPER(state, fullPath) {
const wallpaperIndex = state.wallpapers.findIndex(wallpaper => wallpaper.fullPath === fullPath);
state.wallpapers.splice(wallpaperIndex, 1);
},
ADD_WALLPAPER(state, wallpaper) {
state.wallpapers.push(wallpaper);
},
ADD_BOARD(state, board) {
state.boards.push(board);
},

View file

@ -19,4 +19,5 @@ export default {
publicGameData: {},
game: null,
wallpaperUrl: null,
wallpapers: [],
};