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)
|
.where('userId', user.id)
|
||||||
.orderBy('id', 'desc');
|
.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
|
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 jetpack = require('fs-jetpack');
|
||||||
const Busboy = require('busboy');
|
const Busboy = require('busboy');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { dump } = require('dumper.js');
|
|
||||||
/*
|
/*
|
||||||
TODO: Strip exif data if the owner/user configured it as such
|
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 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 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: 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 {
|
class uploadPOST extends Route {
|
||||||
|
@ -23,7 +20,6 @@ class uploadPOST extends Route {
|
||||||
|
|
||||||
async run(req, res, db) {
|
async run(req, res, db) {
|
||||||
const user = await Util.isAuthorized(req);
|
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' });
|
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);
|
return this.uploadFile(req, res, db, user);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ class Util {
|
||||||
const filename = randomstring.generate({
|
const filename = randomstring.generate({
|
||||||
length: parseInt(process.env.GENERATED_FILENAME_LENGTH, 10),
|
length: parseInt(process.env.GENERATED_FILENAME_LENGTH, 10),
|
||||||
capitalization: 'lowercase'
|
capitalization: 'lowercase'
|
||||||
}) + path.extname(name);
|
}) + path.extname(name).toLowerCase();
|
||||||
const exists = jetpack.exists(path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER, filename));
|
const exists = jetpack.exists(path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER, filename));
|
||||||
if (!exists) return filename;
|
if (!exists) return filename;
|
||||||
if (i < 5) return retry(i + 1);
|
if (i < 5) return retry(i + 1);
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
</b-tooltip>
|
</b-tooltip>
|
||||||
<b-tooltip label="Albums"
|
<b-tooltip label="Albums"
|
||||||
position="is-top">
|
position="is-top">
|
||||||
<a @click="manageAlbums(item)">
|
<a @click="$parent.openAlbumModal(item)">
|
||||||
<i class="icon-interface-window" />
|
<i class="icon-interface-window" />
|
||||||
</a>
|
</a>
|
||||||
</b-tooltip>
|
</b-tooltip>
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
section.hero div.hero-body {
|
section.hero div.hero-body {
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.albumsModal .columns .column { padding: .25rem; }
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~/assets/styles/_colors.scss';
|
@import '~/assets/styles/_colors.scss';
|
||||||
|
@ -16,22 +18,40 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-narrow">
|
<div class="column is-narrow">
|
||||||
<Sidebar/>
|
<Sidebar />
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h2 class="subtitle">Your uploaded files</h2>
|
<h2 class="subtitle">Your uploaded files</h2>
|
||||||
<hr>
|
<hr>
|
||||||
<!--
|
|
||||||
<h1 class="title">Uploads</h1>
|
|
||||||
<h2 class="subtitle">Keep track of all your uploads in here</h2>
|
|
||||||
<hr>
|
|
||||||
-->
|
|
||||||
<Grid v-if="files.length"
|
<Grid v-if="files.length"
|
||||||
:files="files" />
|
:files="files" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -45,7 +65,12 @@ export default {
|
||||||
Grid
|
Grid
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return { files: [] };
|
return {
|
||||||
|
files: [],
|
||||||
|
albums: [],
|
||||||
|
isAlbumsModalActive: false,
|
||||||
|
showingModalForFile: null
|
||||||
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
config() {
|
config() {
|
||||||
|
@ -57,6 +82,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getFiles();
|
this.getFiles();
|
||||||
|
this.getAlbums();
|
||||||
this.$ga.page({
|
this.$ga.page({
|
||||||
page: '/dashboard',
|
page: '/dashboard',
|
||||||
title: 'Dashboard',
|
title: 'Dashboard',
|
||||||
|
@ -64,14 +90,44 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
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() {
|
async getFiles() {
|
||||||
try {
|
try {
|
||||||
const response = await this.axios.get(`${this.config.baseURL}/files`);
|
const response = await this.axios.get(`${this.config.baseURL}/files`);
|
||||||
this.files = response.data.files;
|
this.files = response.data.files;
|
||||||
console.log(this.files);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(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