2020-01-30 00:53:18 +00:00
|
|
|
<template>
|
2020-12-31 10:21:03 +00:00
|
|
|
<v-dialog v-model="show" fullscreen hide-overlay scrollable
|
|
|
|
lazy persistent class="p-upload-dialog" @keydown.esc="cancel">
|
2020-06-27 08:31:20 +00:00
|
|
|
<v-card color="application">
|
2020-12-12 06:56:14 +00:00
|
|
|
<v-toolbar dark flat color="navigation" :dense="$vuetify.breakpoint.smAndDown">
|
2020-06-27 08:31:20 +00:00
|
|
|
<v-btn icon dark @click.stop="cancel">
|
|
|
|
<v-icon>close</v-icon>
|
|
|
|
</v-btn>
|
|
|
|
<v-toolbar-title>
|
|
|
|
<translate key="Upload">Upload</translate>
|
|
|
|
</v-toolbar-title>
|
|
|
|
</v-toolbar>
|
|
|
|
<v-container grid-list-xs text-xs-left fluid>
|
2020-12-31 10:21:03 +00:00
|
|
|
<v-form ref="form" class="p-photo-upload" lazy-validation dense @submit.prevent="submit">
|
|
|
|
<input ref="upload" type="file" multiple class="d-none" @change.stop="upload()">
|
2020-01-30 00:53:18 +00:00
|
|
|
|
2020-06-27 08:31:20 +00:00
|
|
|
<v-container fluid>
|
|
|
|
<p class="subheading">
|
2020-12-31 10:21:03 +00:00
|
|
|
<v-combobox v-if="total === 0" v-model="selectedAlbums" flat solo hide-details chips
|
|
|
|
deletable-chips multiple color="secondary-dark"
|
|
|
|
class="my-0"
|
2020-06-27 08:31:20 +00:00
|
|
|
:items="albums"
|
|
|
|
item-text="Title"
|
|
|
|
item-value="UID"
|
|
|
|
:allow-overflow="false"
|
2020-09-07 14:54:57 +00:00
|
|
|
:label="$gettext('Select albums or create a new one')"
|
2020-06-27 08:31:20 +00:00
|
|
|
return-object
|
|
|
|
>
|
2020-12-31 10:21:03 +00:00
|
|
|
<template #no-data>
|
2020-06-27 08:31:20 +00:00
|
|
|
<v-list-tile>
|
|
|
|
<v-list-tile-content>
|
|
|
|
<v-list-tile-title>
|
2020-12-17 12:23:23 +00:00
|
|
|
<translate
|
|
|
|
key="Press enter to create a new album.">Press enter to create a new album.</translate>
|
2020-06-27 08:31:20 +00:00
|
|
|
</v-list-tile-title>
|
|
|
|
</v-list-tile-content>
|
|
|
|
</v-list-tile>
|
|
|
|
</template>
|
2020-12-31 10:21:03 +00:00
|
|
|
<template #selection="data">
|
2020-06-27 08:31:20 +00:00
|
|
|
<v-chip
|
2020-12-17 12:23:23 +00:00
|
|
|
:key="JSON.stringify(data.item)"
|
|
|
|
:selected="data.selected"
|
|
|
|
:disabled="data.disabled"
|
|
|
|
class="v-chip--select-multi"
|
|
|
|
@input="data.parent.selectItem(data.item)"
|
2020-06-27 08:31:20 +00:00
|
|
|
>
|
2020-12-30 15:07:03 +00:00
|
|
|
<v-icon class="pr-1">bookmark</v-icon>
|
2020-06-27 08:31:20 +00:00
|
|
|
{{ data.item.Title ? data.item.Title : data.item | truncate(40) }}
|
|
|
|
</v-chip>
|
|
|
|
</template>
|
|
|
|
</v-combobox>
|
|
|
|
<span v-else-if="failed"><translate key="Upload failed">Upload failed</translate></span>
|
|
|
|
<span v-else-if="total > 0 && completed < 100">
|
2020-07-05 12:48:49 +00:00
|
|
|
<translate :translate-params="{n: current, t: total}">Uploading %{n} of %{t}…</translate>
|
|
|
|
</span>
|
|
|
|
<span v-else-if="indexing"><translate key="Upload complete">Upload complete. Indexing…</translate></span>
|
2020-06-27 08:31:20 +00:00
|
|
|
<span v-else-if="completed === 100"><translate key="Done">Done.</translate></span>
|
|
|
|
</p>
|
2020-01-30 00:53:18 +00:00
|
|
|
|
2020-12-31 10:21:03 +00:00
|
|
|
<v-progress-linear v-model="completed" color="secondary-dark"
|
2020-06-27 08:31:20 +00:00
|
|
|
:indeterminate="indexing"></v-progress-linear>
|
2020-01-30 00:53:18 +00:00
|
|
|
|
2020-12-31 10:21:03 +00:00
|
|
|
<p v-if="safe" class="body-1">
|
2020-07-05 12:48:49 +00:00
|
|
|
<translate>Please don't upload photos containing offensive content.</translate>
|
|
|
|
<translate>Uploads that may contain such images will be rejected automatically.</translate>
|
2020-06-27 08:31:20 +00:00
|
|
|
</p>
|
2020-01-30 00:53:18 +00:00
|
|
|
|
2020-12-31 10:21:03 +00:00
|
|
|
<p v-if="review" class="body-1">
|
2020-06-30 11:44:32 +00:00
|
|
|
<translate>Non-photographic and low-quality images require a review before they appear in search results.</translate>
|
2020-06-27 08:31:20 +00:00
|
|
|
</p>
|
2020-04-29 11:07:46 +00:00
|
|
|
|
2020-06-27 08:31:20 +00:00
|
|
|
<v-btn
|
2020-12-17 12:23:23 +00:00
|
|
|
:disabled="busy"
|
|
|
|
color="secondary-dark"
|
|
|
|
class="white--text ml-0 mt-2 action-upload"
|
|
|
|
depressed
|
|
|
|
@click.stop="uploadDialog()"
|
2020-06-27 08:31:20 +00:00
|
|
|
>
|
|
|
|
<translate key="Upload">Upload</translate>
|
|
|
|
<v-icon right dark>cloud_upload</v-icon>
|
|
|
|
</v-btn>
|
|
|
|
</v-container>
|
|
|
|
</v-form>
|
2020-01-30 00:53:18 +00:00
|
|
|
|
2020-06-27 08:31:20 +00:00
|
|
|
</v-container>
|
|
|
|
</v-card>
|
|
|
|
</v-dialog>
|
2020-01-30 00:53:18 +00:00
|
|
|
</template>
|
|
|
|
<script>
|
2020-12-17 12:23:23 +00:00
|
|
|
import Api from "common/api";
|
|
|
|
import Notify from "common/notify";
|
|
|
|
import Album from "model/album";
|
|
|
|
|
|
|
|
export default {
|
2020-12-31 10:21:03 +00:00
|
|
|
name: 'PTabUpload',
|
2020-12-17 12:23:23 +00:00
|
|
|
props: {
|
|
|
|
show: Boolean,
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
albums: [],
|
|
|
|
selectedAlbums: [],
|
|
|
|
selected: [],
|
|
|
|
loading: false,
|
|
|
|
uploads: [],
|
|
|
|
busy: false,
|
|
|
|
indexing: false,
|
|
|
|
failed: false,
|
|
|
|
current: 0,
|
|
|
|
total: 0,
|
|
|
|
completed: 0,
|
|
|
|
started: 0,
|
|
|
|
review: this.$config.feature("review"),
|
|
|
|
safe: !this.$config.get("uploadNSFW"),
|
2020-12-31 10:21:03 +00:00
|
|
|
};
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
show: function () {
|
|
|
|
this.reset();
|
|
|
|
this.review = this.$config.feature("review");
|
|
|
|
this.safe = !this.$config.get("uploadNSFW");
|
|
|
|
this.findAlbums("");
|
2020-12-17 12:23:23 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
findAlbums(q) {
|
|
|
|
if (this.loading) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loading = true;
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
q: q,
|
|
|
|
count: 1000,
|
|
|
|
offset: 0,
|
|
|
|
type: "album"
|
|
|
|
};
|
|
|
|
|
|
|
|
Album.search(params).then(response => {
|
|
|
|
this.loading = false;
|
|
|
|
this.albums = response.models;
|
|
|
|
}).catch(() => this.loading = false);
|
|
|
|
},
|
|
|
|
cancel() {
|
|
|
|
if (this.busy) {
|
|
|
|
Notify.info(this.$gettext("Uploading photos…"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.$emit('cancel');
|
|
|
|
},
|
|
|
|
confirm() {
|
|
|
|
if (this.busy) {
|
|
|
|
Notify.info(this.$gettext("Uploading photos…"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.$emit('confirm');
|
|
|
|
},
|
|
|
|
submit() {
|
|
|
|
// DO NOTHING
|
|
|
|
},
|
|
|
|
uploadDialog() {
|
|
|
|
this.$refs.upload.click();
|
|
|
|
},
|
|
|
|
reset() {
|
|
|
|
this.busy = false;
|
|
|
|
this.selected = [];
|
|
|
|
this.uploads = [];
|
|
|
|
this.indexing = false;
|
|
|
|
this.failed = false;
|
|
|
|
this.current = 0;
|
|
|
|
this.total = 0;
|
|
|
|
this.completed = 0;
|
|
|
|
this.started = 0;
|
|
|
|
},
|
|
|
|
upload() {
|
|
|
|
this.selected = this.$refs.upload.files;
|
|
|
|
this.total = this.selected.length;
|
|
|
|
|
|
|
|
if (this.total < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.started = Date.now();
|
|
|
|
this.selected = this.$refs.upload.files;
|
|
|
|
this.total = this.selected.length;
|
|
|
|
this.busy = true;
|
|
|
|
this.indexing = false;
|
|
|
|
this.failed = false;
|
|
|
|
this.current = 0;
|
|
|
|
this.completed = 0;
|
|
|
|
this.uploads = [];
|
|
|
|
|
|
|
|
Notify.info(this.$gettext("Uploading photos…"));
|
|
|
|
|
|
|
|
let addToAlbums = [];
|
|
|
|
|
|
|
|
if (this.selectedAlbums && this.selectedAlbums.length > 0) {
|
|
|
|
this.selectedAlbums.forEach((a) => {
|
|
|
|
if (typeof a === "string") {
|
2020-12-31 10:21:03 +00:00
|
|
|
addToAlbums.push(a);
|
2020-12-17 12:23:23 +00:00
|
|
|
} else if (a instanceof Album && a.UID) {
|
2020-12-31 10:21:03 +00:00
|
|
|
addToAlbums.push(a.UID);
|
2020-12-17 12:23:23 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function performUpload(ctx) {
|
|
|
|
for (let i = 0; i < ctx.selected.length; i++) {
|
|
|
|
let file = ctx.selected[i];
|
|
|
|
let formData = new FormData();
|
|
|
|
|
|
|
|
ctx.current = i + 1;
|
|
|
|
|
|
|
|
formData.append('files', file);
|
|
|
|
|
|
|
|
await Api.post('upload/' + ctx.started,
|
2020-12-31 10:21:03 +00:00
|
|
|
formData,
|
|
|
|
{
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'multipart/form-data'
|
2020-12-17 12:23:23 +00:00
|
|
|
}
|
2020-12-31 10:21:03 +00:00
|
|
|
}
|
2020-12-17 12:23:23 +00:00
|
|
|
).then(() => {
|
|
|
|
ctx.completed = Math.round((ctx.current / ctx.total) * 100);
|
|
|
|
}).catch(() => {
|
|
|
|
ctx.completed = Math.round((ctx.current / ctx.total) * 100);
|
2020-12-31 10:21:03 +00:00
|
|
|
});
|
2020-12-17 12:23:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
performUpload(this).then(() => {
|
|
|
|
this.indexing = true;
|
|
|
|
const ctx = this;
|
|
|
|
|
|
|
|
Api.post('import/upload/' + this.started, {
|
|
|
|
move: true,
|
|
|
|
albums: addToAlbums,
|
|
|
|
}).then(() => {
|
|
|
|
ctx.reset();
|
|
|
|
Notify.success(ctx.$gettext("Upload complete"));
|
|
|
|
ctx.$emit('confirm');
|
|
|
|
}).catch(() => {
|
|
|
|
ctx.reset();
|
|
|
|
Notify.error(ctx.$gettext("Failure while importing uploaded files"));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
2020-01-30 00:53:18 +00:00
|
|
|
</script>
|