Be able to add a file to multiple albums
This commit is contained in:
parent
0639c4e1bb
commit
ce76a8ec7b
|
@ -0,0 +1,26 @@
|
|||
const Route = require('../../structures/Route');
|
||||
|
||||
class albumAddPOST extends Route {
|
||||
constructor() {
|
||||
super('/file/album/add', 'post');
|
||||
}
|
||||
|
||||
async run(req, res, db) {
|
||||
if (!req.body) return res.status(400).json({ message: 'No body provided' });
|
||||
const { fileId, albumId } = req.body;
|
||||
if (!fileId || !albumId) return res.status(400).json({ message: 'No id provided' });
|
||||
|
||||
try {
|
||||
await db.table('albumsFiles')
|
||||
.insert({ fileId, albumId });
|
||||
} catch (error) {
|
||||
return super.error(res, error);
|
||||
}
|
||||
|
||||
return res.json({
|
||||
message: 'Successfully added file to album'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = albumAddPOST;
|
|
@ -0,0 +1,27 @@
|
|||
const Route = require('../../structures/Route');
|
||||
|
||||
class albumDelPOST extends Route {
|
||||
constructor() {
|
||||
super('/file/album/del', 'post');
|
||||
}
|
||||
|
||||
async run(req, res, db) {
|
||||
if (!req.body) return res.status(400).json({ message: 'No body provided' });
|
||||
const { fileId, albumId } = req.body;
|
||||
if (!fileId || !albumId) return res.status(400).json({ message: 'No id provided' });
|
||||
|
||||
try {
|
||||
await db.table('albumsFiles')
|
||||
.where({ fileId, albumId })
|
||||
.delete();
|
||||
} catch (error) {
|
||||
return super.error(res, error);
|
||||
}
|
||||
|
||||
return res.json({
|
||||
message: 'Successfully removed file from album'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = albumDelPOST;
|
|
@ -14,6 +14,21 @@ class filesGET extends Route {
|
|||
.where('userId', user.id)
|
||||
.orderBy('id', 'desc');
|
||||
|
||||
for (const file of files) {
|
||||
file.albums = [];
|
||||
const albumFiles = await db.table('albumsFiles')
|
||||
.where('fileId', file.id);
|
||||
if (!albumFiles.length) continue;
|
||||
|
||||
for (const albumFile of albumFiles) {
|
||||
const album = await db.table('albums')
|
||||
.where('id', albumFile.albumId)
|
||||
.select('id', 'name')
|
||||
.first();
|
||||
if (!album) continue;
|
||||
file.albums.push(album);
|
||||
}
|
||||
}
|
||||
/*
|
||||
For each file, create the public link to be able to display the file
|
||||
*/
|
||||
|
|
|
@ -6,14 +6,11 @@ const log = require('../../utils/Log');
|
|||
const jetpack = require('fs-jetpack');
|
||||
const Busboy = require('busboy');
|
||||
const fs = require('fs');
|
||||
const { dump } = require('dumper.js');
|
||||
/*
|
||||
TODO: Strip exif data if the owner/user configured it as such
|
||||
TODO: If source has transparency generate a png thumbnail, otherwise a jpg.
|
||||
TODO: If source is a gif, generate a thumb of the first frame and play the gif on hover.
|
||||
TODO: If source is a video, generate a thumb of the first frame and save the video length.
|
||||
TODO: Check that the async isAuthorized works and is not nulling out
|
||||
TODO: Lowercase the file extensions
|
||||
*/
|
||||
|
||||
class uploadPOST extends Route {
|
||||
|
@ -23,7 +20,6 @@ class uploadPOST extends Route {
|
|||
|
||||
async run(req, res, db) {
|
||||
const user = await Util.isAuthorized(req);
|
||||
// TODO: .env variables are all casted to strings. pepehands
|
||||
if (!user && process.env.PUBLIC_MODE == 'false') return res.status(401).json({ message: 'Not authorized to use this resource' });
|
||||
return this.uploadFile(req, res, db, user);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class Util {
|
|||
const filename = randomstring.generate({
|
||||
length: parseInt(process.env.GENERATED_FILENAME_LENGTH, 10),
|
||||
capitalization: 'lowercase'
|
||||
}) + path.extname(name);
|
||||
}) + path.extname(name).toLowerCase();
|
||||
const exists = jetpack.exists(path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER, filename));
|
||||
if (!exists) return filename;
|
||||
if (i < 5) return retry(i + 1);
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
</b-tooltip>
|
||||
<b-tooltip label="Albums"
|
||||
position="is-top">
|
||||
<a @click="manageAlbums(item)">
|
||||
<a @click="$parent.openAlbumModal(item)">
|
||||
<i class="icon-interface-window" />
|
||||
</a>
|
||||
</b-tooltip>
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
section.hero div.hero-body {
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.albumsModal .columns .column { padding: .25rem; }
|
||||
</style>
|
||||
<style lang="scss">
|
||||
@import '~/assets/styles/_colors.scss';
|
||||
|
@ -16,22 +18,40 @@
|
|||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-narrow">
|
||||
<Sidebar/>
|
||||
<Sidebar />
|
||||
</div>
|
||||
<div class="column">
|
||||
<h2 class="subtitle">Your uploaded files</h2>
|
||||
<hr>
|
||||
<!--
|
||||
<h1 class="title">Uploads</h1>
|
||||
<h2 class="subtitle">Keep track of all your uploads in here</h2>
|
||||
<hr>
|
||||
-->
|
||||
<Grid v-if="files.length"
|
||||
:files="files" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<b-modal :active.sync="isAlbumsModalActive"
|
||||
:width="640"
|
||||
scroll="keep">
|
||||
<div class="card albumsModal">
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<h3 class="subtitle">Select the albums this file should be a part of</h3>
|
||||
<hr>
|
||||
<div class="columns is-multiline">
|
||||
<div v-for="(album, index) in albums"
|
||||
:key="index"
|
||||
class="column is-3">
|
||||
<div class="field">
|
||||
<b-checkbox :value="isAlbumSelected(album.id)"
|
||||
@input="albumCheckboxClicked($event, album.id)">{{ album.name }}</b-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
@ -45,7 +65,12 @@ export default {
|
|||
Grid
|
||||
},
|
||||
data() {
|
||||
return { files: [] };
|
||||
return {
|
||||
files: [],
|
||||
albums: [],
|
||||
isAlbumsModalActive: false,
|
||||
showingModalForFile: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
config() {
|
||||
|
@ -57,6 +82,7 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.getFiles();
|
||||
this.getAlbums();
|
||||
this.$ga.page({
|
||||
page: '/dashboard',
|
||||
title: 'Dashboard',
|
||||
|
@ -64,14 +90,44 @@ export default {
|
|||
});
|
||||
},
|
||||
methods: {
|
||||
isAlbumSelected(id) {
|
||||
if (!this.showingModalForFile) return;
|
||||
const found = this.showingModalForFile.albums.find(el => el.id === id);
|
||||
return found ? found.id ? true : false : false;
|
||||
},
|
||||
openAlbumModal(file) {
|
||||
this.showingModalForFile = file;
|
||||
this.isAlbumsModalActive = true;
|
||||
},
|
||||
async albumCheckboxClicked(value, id) {
|
||||
try {
|
||||
const response = await this.axios.post(`${this.config.baseURL}/file/album/${value ? 'add' : 'del'}`, {
|
||||
albumId: id,
|
||||
fileId: this.showingModalForFile.id
|
||||
});
|
||||
this.$toast.open(response.data.message);
|
||||
|
||||
// Not the prettiest solution to refetch on each click but it'll do for now
|
||||
this.getFiles();
|
||||
} catch (error) {
|
||||
this.$onPromiseError(error);
|
||||
}
|
||||
},
|
||||
async getFiles() {
|
||||
try {
|
||||
const response = await this.axios.get(`${this.config.baseURL}/files`);
|
||||
this.files = response.data.files;
|
||||
console.log(this.files);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
async getAlbums() {
|
||||
try {
|
||||
const response = await this.axios.get(`${this.config.baseURL}/albums/dropdown`);
|
||||
this.albums = response.data.albums;
|
||||
} catch (error) {
|
||||
this.$onPromiseError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue