Be able to add a file to multiple albums

This commit is contained in:
Pitu 2019-03-02 22:07:24 +09:00
parent 0639c4e1bb
commit ce76a8ec7b
7 changed files with 134 additions and 14 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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
*/

View 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);
}

View File

@ -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);

View File

@ -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>

View File

@ -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);
}
}
}
};