Frontend: Code clean-up

This commit is contained in:
Michael Mayer 2020-12-30 14:04:37 +01:00
parent 4614cbe4ea
commit 915363f339
8 changed files with 371 additions and 371 deletions

View file

@ -1,14 +1,14 @@
<template>
<div class="p-page p-page-album-photos" v-infinite-scroll="loadMore" :infinite-scroll-disabled="scrollDisabled"
<div v-infinite-scroll="loadMore" class="p-page p-page-album-photos" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
<p-album-toolbar :album="model" :settings="settings" :filter="filter" :filter-change="updateQuery"
:refresh="refresh"></p-album-toolbar>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-container fluid class="pa-0" v-else>
<v-container v-else fluid class="pa-0">
<p-scroll-top></p-scroll-top>
<p-photo-clipboard :refresh="refresh"
@ -52,29 +52,10 @@ import Event from "pubsub-js";
import Thumb from "model/thumb";
export default {
name: 'p-page-album-photos',
name: 'PPageAlbumPhotos',
props: {
staticFilter: Object
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.camera = query['camera'] ? parseInt(query['camera']) : 0;
this.filter.country = query['country'] ? query['country'] : '';
this.settings.view = this.viewType();
this.lastFilter = {};
this.routeName = this.$route.name;
if (this.uid !== this.$route.params.uid) {
this.uid = this.$route.params.uid;
this.findAlbum().then(() => this.search());
} else {
this.search();
}
}
},
data() {
const uid = this.$route.params.uid;
const query = this.$route.query;
@ -111,6 +92,39 @@ export default {
},
};
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.camera = query['camera'] ? parseInt(query['camera']) : 0;
this.filter.country = query['country'] ? query['country'] : '';
this.settings.view = this.viewType();
this.lastFilter = {};
this.routeName = this.$route.name;
if (this.uid !== this.$route.params.uid) {
this.uid = this.$route.params.uid;
this.findAlbum().then(() => this.search());
} else {
this.search();
}
}
},
created() {
this.findAlbum().then(() => this.search());
this.subscriptions.push(Event.subscribe("albums.updated", (ev, data) => this.onAlbumsUpdated(ev, data)));
this.subscriptions.push(Event.subscribe("photos", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
methods: {
viewType() {
let queryParam = this.$route.query['view'];
@ -145,7 +159,7 @@ export default {
},
editPhoto(index) {
let selection = this.results.map((p) => {
return p.getId()
return p.getId();
});
// Open Edit Dialog
@ -165,7 +179,7 @@ export default {
this.$viewer.show(Thumb.fromPhotos(this.results), index);
}
} else if (showMerged) {
this.$viewer.show(Thumb.fromFiles([selected]), 0)
this.$viewer.show(Thumb.fromFiles([selected]), 0);
} else {
this.viewerResults().then((results) => {
const thumbsIndex = results.findIndex(result => result.UID === selected.UID);
@ -388,14 +402,14 @@ export default {
this.filter.order = m.Order;
window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}`;
return Promise.resolve(this.model)
return Promise.resolve(this.model);
});
},
onAlbumsUpdated(ev, data) {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
for (let i = 0; i < data.entities.length; i++) {
@ -408,7 +422,7 @@ export default {
}
}
window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}`
window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}`;
this.dirty = true;
this.complete = false;
@ -447,7 +461,7 @@ export default {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
const type = ev.split('.')[1];
@ -485,19 +499,5 @@ export default {
}
},
},
created() {
this.findAlbum().then(() => this.search());
this.subscriptions.push(Event.subscribe("albums.updated", (ev, data) => this.onAlbumsUpdated(ev, data)));
this.subscriptions.push(Event.subscribe("photos", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
};
</script>

View file

@ -1,54 +1,54 @@
<template>
<div class="p-page p-page-albums" v-infinite-scroll="loadMore" :infinite-scroll-disabled="scrollDisabled"
<div v-infinite-scroll="loadMore" class="p-page p-page-albums" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
<v-form ref="form" class="p-albums-search" lazy-validation @submit.prevent="updateQuery" dense>
<v-form ref="form" class="p-albums-search" lazy-validation dense @submit.prevent="updateQuery">
<v-toolbar flat color="secondary" :dense="$vuetify.breakpoint.smAndDown">
<v-text-field @keyup.enter.native="updateQuery"
single-line
<v-text-field single-line
class="hidden-xs-only mr-3"
:label="$gettext('Search')"
browser-autocomplete="off"
prepend-inner-icon="search"
clearable
color="secondary-dark"
@click:clear="clearQuery"
v-model="filter.q"
clearable
id="search"
color="secondary-dark"
@keyup.enter.native="updateQuery"
@click:clear="clearQuery"
></v-text-field>
<v-select @change="updateQuery"
<v-select v-model="filter.category"
single-line
:label="$gettext('Category')"
color="secondary-dark"
v-model="filter.category"
:items="categories"
class="input-category"
@change="updateQuery"
>
</v-select>
<v-spacer></v-spacer>
<v-btn icon @click.stop="refresh" class="action-reload" :title="$gettext('Reload')">
<v-btn icon class="action-reload" :title="$gettext('Reload')" @click.stop="refresh">
<v-icon>refresh</v-icon>
</v-btn>
<v-btn icon @click.stop="showUpload()" v-if="!$config.values.readonly && $config.feature('upload')"
class="hidden-sm-and-down" :title="$gettext('Upload')">
<v-btn v-if="!$config.values.readonly && $config.feature('upload')" icon class="hidden-sm-and-down"
:title="$gettext('Upload')" @click.stop="showUpload()">
<v-icon>cloud_upload</v-icon>
</v-btn>
<v-btn icon @click.prevent="create" class="action-add" v-if="staticFilter.type === 'album'"
:title="$gettext('Add Album')">
<v-btn v-if="staticFilter.type === 'album'" icon class="action-add" :title="$gettext('Add Album')"
@click.prevent="create">
<v-icon>add</v-icon>
</v-btn>
</v-toolbar>
</v-form>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-container fluid class="pa-0" v-else>
<v-container v-else fluid class="pa-0">
<p-scroll-top></p-scroll-top>
<p-album-clipboard :refresh="refresh" :selection="selection" :share="share" :edit="edit"
@ -86,19 +86,19 @@
xs6 sm4 lg3 xl2 d-flex
>
<v-hover>
<v-card tile class="accent lighten-3"
slot-scope="{ hover }"
@contextmenu="onContextMenu($event, index)"
<v-card slot-scope="{ hover }" tile
class="accent lighten-3"
:dark="selection.includes(album.UID)"
:class="selection.includes(album.UID) ? 'elevation-10 ma-0 accent darken-1 white--text' : 'elevation-0 ma-1 accent lighten-3'"
:to="{name: view, params: {uid: album.UID, slug: album.Slug, year: album.Year, month: album.Month}}"
@contextmenu="onContextMenu($event, index)"
>
<v-img
:src="album.thumbnailUrl('tile_500')"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
aspect-ratio="1"
class="accent lighten-2"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
>
<v-layout
slot="placeholder"
@ -133,16 +133,16 @@
<v-card-actions primary-title class="pl-3 pr-2 pb-0 mb-0" style="user-select: none;">
<h3 v-if="album.Type !== 'month'"
@click.stop.prevent="edit(album)"
class="body-2 ma-0 action-title-edit"
:data-uid="album.UID">
:data-uid="album.UID"
@click.stop.prevent="edit(album)">
{{ album.Title }}
</h3>
<h3 v-else
@click.stop.prevent="edit(album)"
class="body-2 ma-0 action-title-edit"
:data-uid="album.UID">
:data-uid="album.UID"
@click.stop.prevent="edit(album)">
{{ album.getDateString() | capitalize }}
</h3>
@ -157,14 +157,14 @@
<v-card-text primary-title class="pb-2 pt-0 p-photo-desc" style="user-select: none;"
@click.stop.prevent="">
<div class="caption mb-2" v-if="album.Description">
<div v-if="album.Description" class="caption mb-2">
<button @click.exact="edit(album)">
{{ album.Description | truncate(100) }}
</button>
</div>
<div class="caption mb-2" v-else-if="album.Type === 'album'">
<button @click.exact="edit(album)" v-if="album.PhotoCount === 1">
<div v-else-if="album.Type === 'album'" class="caption mb-2">
<button v-if="album.PhotoCount === 1" @click.exact="edit(album)">
<translate>Contains one entry.</translate>
</button>
<button v-else-if="album.PhotoCount > 0">
@ -174,13 +174,13 @@
<translate>Add photos or videos from search results by selecting them.</translate>
</button>
</div>
<div class="caption mb-2" v-else-if="album.Type === 'folder'">
<div v-else-if="album.Type === 'folder'" class="caption mb-2">
<button @click.exact="edit(album)">
/{{ album.Path | truncate(100) }}
</button>
</div>
<div class="caption mb-2 d-block" v-if="album.Location">
<div v-if="album.Location" class="caption mb-2 d-block">
<button @click.exact="edit(album)">
<v-icon size="14">location_on</v-icon>
{{ album.Location }}
@ -210,35 +210,11 @@ import {MaxItems} from "common/clipboard";
import Notify from "common/notify";
export default {
name: 'p-page-albums',
name: 'PPageAlbums',
props: {
staticFilter: Object,
view: String,
},
computed: {
context: function () {
if (!this.staticFilter) {
return "album";
}
if (this.staticFilter.type) {
return this.staticFilter.type;
}
return "";
}
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query["q"] ? query["q"] : "";
this.filter.category = query["category"] ? query["category"] : "";
this.lastFilter = {};
this.routeName = this.$route.name;
this.search();
}
},
data() {
const query = this.$route.query;
const routeName = this.$route.name;
@ -286,6 +262,43 @@ export default {
album: new Album(),
};
},
computed: {
context: function () {
if (!this.staticFilter) {
return "album";
}
if (this.staticFilter.type) {
return this.staticFilter.type;
}
return "";
}
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query["q"] ? query["q"] : "";
this.filter.category = query["category"] ? query["category"] : "";
this.lastFilter = {};
this.routeName = this.$route.name;
this.search();
}
},
created() {
this.search();
this.subscriptions.push(Event.subscribe("albums", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
methods: {
share(album) {
this.album = album;
@ -511,7 +524,7 @@ export default {
if (this.results.findIndex(a => a.Title.startsWith(title)) !== -1) {
const existing = this.results.filter(a => a.Title.startsWith(title));
title = `${title} (${existing.length + 1})`
title = `${title} (${existing.length + 1})`;
}
const album = new Album({"Title": title, "Favorite": true});
@ -530,7 +543,7 @@ export default {
return;
}
this.selection.push(uid)
this.selection.push(uid);
this.lastId = uid;
}
},
@ -566,7 +579,7 @@ export default {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
const type = ev.split('.')[1];
@ -608,7 +621,7 @@ export default {
this.results.splice(index, 1);
}
this.removeSelection(uid)
this.removeSelection(uid);
}
break;
@ -629,18 +642,5 @@ export default {
}
}
},
created() {
this.search();
this.subscriptions.push(Event.subscribe("albums", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
};
</script>

View file

@ -1,10 +1,12 @@
<template>
<div class="p-page p-page-labels" v-infinite-scroll="loadMore" :infinite-scroll-disabled="scrollDisabled"
<div v-infinite-scroll="loadMore" class="p-page p-page-labels" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
<v-form ref="form" class="p-labels-search" lazy-validation @submit.prevent="updateQuery" dense>
<v-form ref="form" class="p-labels-search" lazy-validation dense @submit.prevent="updateQuery">
<v-toolbar flat color="secondary" :dense="$vuetify.breakpoint.smAndDown">
<v-text-field class="pt-3 pr-3 input-search"
<v-text-field id="search"
v-model="filter.q"
class="pt-3 pr-3 input-search"
single-line
:label="$gettext('Search')"
prepend-inner-icon="search"
@ -12,30 +14,28 @@
clearable
color="secondary-dark"
@click:clear="clearQuery"
v-model="filter.q"
@keyup.enter.native="updateQuery"
id="search"
></v-text-field>
<v-spacer></v-spacer>
<v-btn icon @click.stop="refresh" class="action-reload" :title="$gettext('Reload')">
<v-btn icon class="action-reload" :title="$gettext('Reload')" @click.stop="refresh">
<v-icon>refresh</v-icon>
</v-btn>
<v-btn v-if="!filter.all" icon @click.stop="showAll" class="action-show-all" :title="$gettext('Show more')">
<v-btn v-if="!filter.all" icon class="action-show-all" :title="$gettext('Show more')" @click.stop="showAll">
<v-icon>visibility</v-icon>
</v-btn>
<v-btn v-else icon @click.stop="showImportant" class="action-show-important" :title="$gettext('Show less')">
<v-btn v-else icon class="action-show-important" :title="$gettext('Show less')" @click.stop="showImportant">
<v-icon>visibility_off</v-icon>
</v-btn>
</v-toolbar>
</v-form>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-container fluid class="pa-0" v-else>
<v-container v-else fluid class="pa-0">
<p-label-clipboard :refresh="refresh" :selection="selection"
:clear-selection="clearSelection"></p-label-clipboard>
@ -63,18 +63,18 @@
xs6 sm4 md3 lg2 d-flex
>
<v-hover>
<v-card tile class="accent lighten-3"
slot-scope="{ hover }"
@contextmenu="onContextMenu($event, index)"
<v-card slot-scope="{ hover }" tile
class="accent lighten-3"
:dark="selection.includes(label.UID)"
:class="selection.includes(label.UID) ? 'elevation-10 ma-0 accent darken-1 white--text' : 'elevation-0 ma-1 accent lighten-3'"
:to="{name: 'browse', query: {q: 'label:' + (label.CustomSlug ? label.CustomSlug : label.Slug)}}">
:to="{name: 'browse', query: {q: 'label:' + (label.CustomSlug ? label.CustomSlug : label.Slug)}}"
@contextmenu="onContextMenu($event, index)">
<v-img
:src="label.thumbnailUrl('tile_500')"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
aspect-ratio="1"
class="accent lighten-2"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
>
<v-layout
slot="placeholder"
@ -111,8 +111,8 @@
<v-edit-dialog
:return-value.sync="label.Name"
lazy
@save="onSave(label)"
class="p-inline-edit"
@save="onSave(label)"
>
<span v-if="label.Name" class="body-2 ma-0">
{{ label.Name | capitalize }}
@ -120,7 +120,7 @@
<span v-else>
<v-icon>edit</v-icon>
</span>
<template v-slot:input>
<template #input>
<v-text-field
v-model="label.Name"
:rules="[titleRule]"
@ -155,21 +155,10 @@ import {MaxItems} from "../common/clipboard";
import Notify from "../common/notify";
export default {
name: 'p-page-labels',
name: 'PPageLabels',
props: {
staticFilter: Object
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.all = query['all'] ? query['all'] : '';
this.lastFilter = {};
this.routeName = this.$route.name;
this.search();
}
},
data() {
const query = this.$route.query;
const routeName = this.$route.name;
@ -202,6 +191,30 @@ export default {
lastId: "",
};
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.all = query['all'] ? query['all'] : '';
this.lastFilter = {};
this.routeName = this.$route.name;
this.search();
}
},
created() {
this.search();
this.subscriptions.push(Event.subscribe("labels", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
methods: {
selectRange(rangeEnd, models) {
if (!models || !models[rangeEnd] || !(models[rangeEnd] instanceof RestModel)) {
@ -287,7 +300,7 @@ export default {
return;
}
this.selection.push(uid)
this.selection.push(uid);
this.lastId = uid;
}
},
@ -456,7 +469,7 @@ export default {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
const type = ev.split('.')[1];
@ -485,7 +498,7 @@ export default {
this.results.splice(index, 1);
}
this.removeSelection(uid)
this.removeSelection(uid);
}
break;
@ -497,18 +510,5 @@ export default {
}
}
},
created() {
this.search();
this.subscriptions.push(Event.subscribe("labels", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
};
</script>

View file

@ -1,8 +1,9 @@
<template>
<div class="p-page p-page-errors" v-infinite-scroll="loadMore" :infinite-scroll-disabled="scrollDisabled"
<div v-infinite-scroll="loadMore" class="p-page p-page-errors" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
<v-toolbar flat color="secondary" :dense="$vuetify.breakpoint.smAndDown">
<v-text-field class="pt-3 pr-3 input-search"
<v-text-field v-model="filter.q"
class="pt-3 pr-3 input-search"
browser-autocomplete="off"
single-line
:label="$gettext('Search')"
@ -10,13 +11,12 @@
clearable
color="secondary-dark"
@click:clear="clearQuery"
v-model="filter.q"
@keyup.enter.native="updateQuery"
></v-text-field>
<v-spacer></v-spacer>
<v-btn icon @click.stop="reload" class="action-reload" :title="$gettext('Reload')">
<v-btn icon class="action-reload" :title="$gettext('Reload')" @click.stop="reload">
<v-icon>refresh</v-icon>
</v-btn>
@ -25,10 +25,10 @@
<v-icon>bug_report</v-icon>
</v-btn>
</v-toolbar>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-list dense two-line v-else-if="errors.length > 0">
<v-list v-else-if="errors.length > 0" dense two-line>
<v-list-tile
v-for="(err, index) in errors" :key="index"
avatar
@ -45,10 +45,10 @@
</v-list-tile>
</v-list>
<v-card v-else class="errors-empty secondary-light lighten-1 ma-0 pa-2" flat>
<v-card-title primary-title v-if="filter.q !== ''">
<v-card-title v-if="filter.q !== ''" primary-title>
<translate>No warnings or error containing this keyword. Note that search is case-sensitive.</translate>
</v-card-title>
<v-card-title primary-title v-else>
<v-card-title v-else primary-title>
<translate>Log messages appear here whenever PhotoPrism comes across broken files, or there are other potential issues.</translate>
</v-card-title>
</v-card>
@ -72,8 +72,8 @@
<v-card-actions class="pa-2">
<v-spacer></v-spacer>
<v-btn color="secondary-light" depressed @click="details.show = false"
class="action-close">
<v-btn color="secondary-light" depressed class="action-close"
@click="details.show = false">
<translate>Close</translate>
</v-btn>
</v-card-actions>
@ -87,14 +87,7 @@ import {DateTime} from "luxon";
import Api from "common/api";
export default {
name: 'p-page-errors',
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.reload();
}
},
name: 'PPageErrors',
data() {
const query = this.$route.query;
const q = query["q"] ? query["q"] : "";
@ -115,6 +108,16 @@ export default {
},
};
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.reload();
}
},
created() {
this.loadMore();
},
methods: {
updateQuery() {
this.filter.q = this.filter.q.trim();
@ -208,8 +211,5 @@ export default {
return DateTime.fromISO(s).toFormat("yyyy-LL-dd HH:mm:ss");
},
},
created() {
this.loadMore();
},
};
</script>

View file

@ -1,6 +1,6 @@
<template>
<div class="p-page p-page-files">
<v-form ref="form" class="p-files-search" lazy-validation @submit.prevent="updateQuery" dense>
<v-form ref="form" class="p-files-search" lazy-validation dense @submit.prevent="updateQuery">
<v-toolbar flat color="secondary" :dense="$vuetify.breakpoint.smAndDown">
<v-toolbar-title>
<router-link to="/library/files">
@ -15,16 +15,16 @@
<v-spacer></v-spacer>
<v-btn icon @click.stop="refresh" :title="$gettext('Reload')">
<v-btn icon :title="$gettext('Reload')" @click.stop="refresh">
<v-icon>refresh</v-icon>
</v-btn>
</v-toolbar>
</v-form>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-container fluid class="pa-0" v-else>
<v-container v-else fluid class="pa-0">
<p-file-clipboard :refresh="refresh" :selection="selection"
:clear-selection="clearSelection"></p-file-clipboard>
@ -53,17 +53,17 @@
xs6 sm4 md3 lg2 d-flex
>
<v-hover>
<v-card tile class="accent lighten-3 clickable"
slot-scope="{ hover }"
@contextmenu="onContextMenu($event, index)"
<v-card slot-scope="{ hover }" tile
class="accent lighten-3 clickable"
:dark="selection.includes(model.UID)"
:class="selection.includes(model.UID) ? 'elevation-10 ma-0 darken-1 white--text' : 'elevation-0 ma-1 lighten-3'">
:class="selection.includes(model.UID) ? 'elevation-10 ma-0 darken-1 white--text' : 'elevation-0 ma-1 lighten-3'"
@contextmenu="onContextMenu($event, index)">
<v-img
:src="model.thumbnailUrl('tile_500')"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
aspect-ratio="1"
class="accent lighten-2"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
>
<v-layout
slot="placeholder"
@ -86,8 +86,8 @@
</v-btn>
</v-img>
<v-card-title primary-title class="pa-3 p-photo-desc" style="user-select: none;"
v-if="model.isFile()">
<v-card-title v-if="model.isFile()" primary-title class="pa-3 p-photo-desc"
style="user-select: none;">
<div>
<h3 class="body-2 mb-2" :title="model.Name">
<button @click.exact="openFile(index)">
@ -99,7 +99,7 @@
</div>
</div>
</v-card-title>
<v-card-title primary-title class="pa-3 p-photo-desc" v-else>
<v-card-title v-else primary-title class="pa-3 p-photo-desc">
<div>
<h3 class="body-2 mb-2" :title="model.Title">
<button @click.exact="openFile(index)">
@ -128,22 +128,10 @@ import Notify from "common/notify";
import {MaxItems} from "common/clipboard";
export default {
name: 'p-page-files',
name: 'PPageFiles',
props: {
staticFilter: Object
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.all = query['all'] ? query['all'] : '';
this.lastFilter = {};
this.routeName = this.$route.name;
this.path = this.$route.params.pathMatch;
this.search();
}
},
data() {
const query = this.$route.query;
const routeName = this.$route.name;
@ -179,6 +167,32 @@ export default {
breadcrumbs: [],
};
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.all = query['all'] ? query['all'] : '';
this.lastFilter = {};
this.routeName = this.$route.name;
this.path = this.$route.params.pathMatch;
this.search();
}
},
created() {
this.path = this.$route.params.pathMatch;
this.search();
this.subscriptions.push(Event.subscribe("folders", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
methods: {
getBreadcrumbs() {
let result = [];
@ -188,10 +202,10 @@ export default {
crumbs.forEach(dir => {
if (dir) {
path += "/" + dir
result.push({path: path, name: dir})
path += "/" + dir;
result.push({path: path, name: dir});
}
})
});
return result;
},
@ -207,10 +221,10 @@ export default {
},
downloadFile(index) {
const model = this.results[index];
const link = document.createElement('a')
const link = document.createElement('a');
link.href = `/api/v1/dl/${model.Hash}?t=${this.$config.downloadToken()}`;
link.download = model.Name;
link.click()
link.click();
},
selectRange(rangeEnd, models) {
if (!models || !models[rangeEnd] || !(models[rangeEnd] instanceof RestModel)) {
@ -298,7 +312,7 @@ export default {
return;
}
this.selection.push(uid)
this.selection.push(uid);
this.lastId = uid;
}
},
@ -420,7 +434,7 @@ export default {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
const type = ev.split('.')[1];
@ -449,7 +463,7 @@ export default {
this.results.splice(index, 1);
}
this.removeSelection(ppid)
this.removeSelection(ppid);
}
break;
@ -461,19 +475,5 @@ export default {
}
}
},
created() {
this.path = this.$route.params.pathMatch;
this.search();
this.subscriptions.push(Event.subscribe("folders", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
};
</script>

View file

@ -4,6 +4,7 @@
<div class="p-map-control">
<div class="mapboxgl-ctrl mapboxgl-ctrl-group">
<v-text-field class="pa-0 ma-0 input-search"
v-model="filter.q"
single-line
solo
flat
@ -14,7 +15,6 @@
browser-autocomplete="off"
color="secondary-dark"
@click:clear="clearQuery"
v-model="filter.q"
@keyup.enter.native="formChange"
></v-text-field>
</div>
@ -30,14 +30,7 @@ import Api from "common/api";
import Thumb from "model/thumb";
export default {
name: 'p-page-places',
watch: {
'$route'() {
this.filter.q = this.query();
this.lastFilter = {};
this.search();
}
},
name: 'PPagePlaces',
data() {
const s = this.$config.values.settings.maps;
const filter = {
@ -178,8 +171,18 @@ export default {
lastFilter: {},
config: this.$config.values,
settings: s,
};
},
watch: {
'$route'() {
this.filter.q = this.query();
this.lastFilter = {};
this.search();
}
},
mounted() {
this.renderMap();
},
methods: {
query: function () {
return this.$route.params.q ? this.$route.params.q : "";
@ -196,7 +199,7 @@ export default {
if (selected.Type === TypeVideo || selected.Type === TypeLive) {
this.$modal.show('video', {video: selected, album: null});
} else {
this.$viewer.show(Thumb.fromPhotos(this.photos), index)
this.$viewer.show(Thumb.fromPhotos(this.photos), index);
}
} else {
this.$notify.warn(this.$gettext("No photos found"));
@ -376,15 +379,15 @@ export default {
});
const clusterId = features[0].properties.cluster_id;
this.map.getSource('photos').getClusterExpansionZoom(
clusterId,
(err, zoom) => {
if (err) return;
clusterId,
(err, zoom) => {
if (err) return;
this.map.easeTo({
center: features[0].geometry.coordinates,
zoom: zoom
});
}
this.map.easeTo({
center: features[0].geometry.coordinates,
zoom: zoom
});
}
);
});
@ -398,9 +401,6 @@ export default {
this.search();
},
},
mounted() {
this.renderMap();
},
};
</script>

View file

@ -1,15 +1,15 @@
<template>
<div class="p-page p-page-albums" v-infinite-scroll="loadMore" :infinite-scroll-disabled="scrollDisabled"
<div v-infinite-scroll="loadMore" class="p-page p-page-albums" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
<v-toolbar flat color="secondary" :dense="$vuetify.breakpoint.smAndDown">
<v-toolbar-title>
<translate>Albums</translate>
</v-toolbar-title>
</v-toolbar>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-container fluid class="pa-0" v-else>
<v-container v-else fluid class="pa-0">
<p-scroll-top></p-scroll-top>
<p-album-clipboard :refresh="refresh" :selection="selection"
@ -37,19 +37,19 @@
xs6 sm4 lg3 xl2 d-flex
>
<v-hover>
<v-card tile class="accent lighten-3"
slot-scope="{ hover }"
@contextmenu="onContextMenu($event, index)"
<v-card slot-scope="{ hover }" tile
class="accent lighten-3"
:dark="selection.includes(album.UID)"
:class="selection.includes(album.UID) ? 'elevation-10 ma-0 accent darken-1 white--text' : 'elevation-0 ma-1 accent lighten-3'"
:to="{name: view, params: {uid: album.UID, slug: album.Slug, year: album.Year, month: album.Month}}"
@contextmenu="onContextMenu($event, index)"
>
<v-img
:src="album.thumbnailUrl('tile_500')"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
aspect-ratio="1"
class="accent lighten-2"
@mousedown="onMouseDown($event, index)"
@click="onClick($event, index)"
>
<v-layout
slot="placeholder"
@ -81,10 +81,10 @@
</h3>
</v-card-title>
<v-card-text class="pl-3 pr-3 pt-0 pb-3 p-album-desc">
<div class="caption" title="Description" v-if="album.Description">
<div v-if="album.Description" class="caption" title="Description">
{{ album.Description | truncate(100) }}
</div>
<div class="caption" title="Description" v-else>
<div v-else class="caption" title="Description">
<translate>Shared with you.</translate>
</div>
</v-card-text>
@ -106,35 +106,11 @@ import {MaxItems} from "../common/clipboard";
import Notify from "../common/notify";
export default {
name: 'p-page-albums',
name: 'PPageAlbums',
props: {
staticFilter: Object,
view: String,
},
computed: {
context: function () {
if (!this.staticFilter) {
return "album";
}
if (this.staticFilter.type) {
return this.staticFilter.type;
}
return "";
}
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query["q"] ? query["q"] : "";
this.filter.category = query["category"] ? query["category"] : "";
this.lastFilter = {};
this.routeName = this.$route.name;
this.search();
}
},
data() {
const query = this.$route.query;
const routeName = this.$route.name;
@ -176,6 +152,51 @@ export default {
lastId: "",
};
},
computed: {
context: function () {
if (!this.staticFilter) {
return "album";
}
if (this.staticFilter.type) {
return this.staticFilter.type;
}
return "";
}
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query["q"] ? query["q"] : "";
this.filter.category = query["category"] ? query["category"] : "";
this.lastFilter = {};
this.routeName = this.$route.name;
this.search();
}
},
created() {
const token = this.$route.params.token;
if (this.$session.hasToken(token)) {
this.search();
} else {
this.$session.redeemToken(token).then(() => {
this.search();
});
}
this.subscriptions.push(Event.subscribe("albums", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
methods: {
showUpload() {
Event.publish("dialog.upload");
@ -379,7 +400,7 @@ export default {
if (this.results.findIndex(a => a.Title.startsWith(title)) !== -1) {
const existing = this.results.filter(a => a.Title.startsWith(title));
title = `${title} (${existing.length + 1})`
title = `${title} (${existing.length + 1})`;
}
const album = new Album({"Title": title, "Favorite": true});
@ -398,7 +419,7 @@ export default {
return;
}
this.selection.push(uid)
this.selection.push(uid);
this.lastId = uid;
}
},
@ -434,7 +455,7 @@ export default {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
const type = ev.split('.')[1];
@ -465,7 +486,7 @@ export default {
this.results.splice(index, 1);
}
this.removeSelection(uid)
this.removeSelection(uid);
}
break;
@ -486,26 +507,5 @@ export default {
}
}
},
created() {
const token = this.$route.params.token;
if (this.$session.hasToken(token)) {
this.search();
} else {
this.$session.redeemToken(token).then(() => {
this.search();
});
}
this.subscriptions.push(Event.subscribe("albums", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
};
</script>

View file

@ -1,9 +1,9 @@
<template>
<div class="p-page p-page-album-photos" v-infinite-scroll="loadMore" :infinite-scroll-disabled="scrollDisabled"
<div v-infinite-scroll="loadMore" class="p-page p-page-album-photos" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="10" :infinite-scroll-listen-for-event="'scrollRefresh'">
<v-form lazy-validation dense
ref="form" autocomplete="off" class="p-photo-toolbar p-album-toolbar" accept-charset="UTF-8">
<v-form ref="form" lazy-validation
dense autocomplete="off" class="p-photo-toolbar p-album-toolbar" accept-charset="UTF-8">
<v-toolbar flat color="secondary" :dense="$vuetify.breakpoint.smAndDown">
<v-toolbar-title>
{{ model.Title }}
@ -11,22 +11,22 @@
<v-spacer></v-spacer>
<v-btn icon @click.stop="refresh" class="hidden-xs-only action-reload">
<v-btn icon class="hidden-xs-only action-reload" @click.stop="refresh">
<v-icon>refresh</v-icon>
</v-btn>
<v-btn icon @click.stop="download" v-if="$config.feature('download')" class="hidden-xs-only action-download"
:title="$gettext('Download')">
<v-btn v-if="$config.feature('download')" icon class="hidden-xs-only action-download" :title="$gettext('Download')"
@click.stop="download">
<v-icon>get_app</v-icon>
</v-btn>
<v-btn icon v-if="settings.view === 'cards'" @click.stop="setView('list')">
<v-btn v-if="settings.view === 'cards'" icon @click.stop="setView('list')">
<v-icon>view_list</v-icon>
</v-btn>
<v-btn icon v-else-if="settings.view === 'list'" @click.stop="setView('mosaic')">
<v-btn v-else-if="settings.view === 'list'" icon @click.stop="setView('mosaic')">
<v-icon>view_comfy</v-icon>
</v-btn>
<v-btn icon v-else @click.stop="setView('cards')">
<v-btn v-else icon @click.stop="setView('cards')">
<v-icon>view_column</v-icon>
</v-btn>
</v-toolbar>
@ -48,10 +48,10 @@
</template>
</v-form>
<v-container fluid class="pa-4" v-if="loading">
<v-container v-if="loading" fluid class="pa-4">
<v-progress-linear color="secondary-dark" :indeterminate="true"></v-progress-linear>
</v-container>
<v-container fluid class="pa-0" v-else>
<v-container v-else fluid class="pa-0">
<p-scroll-top></p-scroll-top>
<p-photo-clipboard :refresh="refresh"
@ -93,29 +93,10 @@ import Thumb from "model/thumb";
import Notify from "common/notify";
export default {
name: 'p-page-album-photos',
name: 'PPageAlbumPhotos',
props: {
staticFilter: Object
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.camera = query['camera'] ? parseInt(query['camera']) : 0;
this.filter.country = query['country'] ? query['country'] : '';
this.settings.view = this.viewType();
this.lastFilter = {};
this.routeName = this.$route.name;
if (this.uid !== this.$route.params.uid) {
this.uid = this.$route.params.uid;
this.findAlbum().then(() => this.search());
} else {
this.search();
}
}
},
data() {
const uid = this.$route.params.uid;
const query = this.$route.query;
@ -153,6 +134,47 @@ export default {
},
};
},
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.camera = query['camera'] ? parseInt(query['camera']) : 0;
this.filter.country = query['country'] ? query['country'] : '';
this.settings.view = this.viewType();
this.lastFilter = {};
this.routeName = this.$route.name;
if (this.uid !== this.$route.params.uid) {
this.uid = this.$route.params.uid;
this.findAlbum().then(() => this.search());
} else {
this.search();
}
}
},
created() {
const token = this.$route.params.token;
if (this.$session.hasToken(token)) {
this.findAlbum().then(() => this.search());
} else {
this.$session.redeemToken(token).then(() => {
this.findAlbum().then(() => this.search());
});
}
this.subscriptions.push(Event.subscribe("albums.updated", (ev, data) => this.onAlbumsUpdated(ev, data)));
this.subscriptions.push(Event.subscribe("photos", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
methods: {
setView(name) {
this.settings.view = name;
@ -191,7 +213,7 @@ export default {
},
editPhoto(index) {
let selection = this.results.map((p) => {
return p.getId()
return p.getId();
});
// Open Edit Dialog
@ -211,7 +233,7 @@ export default {
this.$viewer.show(Thumb.fromPhotos(this.results), index);
}
} else if (showMerged) {
this.$viewer.show(Thumb.fromFiles([selected]), 0)
this.$viewer.show(Thumb.fromFiles([selected]), 0);
} else {
this.viewerResults().then((results) => {
const thumbsIndex = results.findIndex(result => result.UID === selected.UID);
@ -424,14 +446,14 @@ export default {
this.filter.order = m.Order;
window.document.title = this.model.Title;
return Promise.resolve(this.model)
return Promise.resolve(this.model);
});
},
onAlbumsUpdated(ev, data) {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
for (let i = 0; i < data.entities.length; i++) {
@ -444,7 +466,7 @@ export default {
}
}
window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}`
window.document.title = `${this.$config.get("siteTitle")}: ${this.model.Title}`;
this.dirty = true;
this.complete = false;
@ -483,7 +505,7 @@ export default {
if (!this.listen) return;
if (!data || !data.entities) {
return
return;
}
const type = ev.split('.')[1];
@ -525,33 +547,11 @@ export default {
},
onDownload(path) {
Notify.success(this.$gettext("Downloading…"));
const link = document.createElement('a')
const link = document.createElement('a');
link.href = path;
link.download = "album.zip";
link.click();
},
},
created() {
const token = this.$route.params.token;
if (this.$session.hasToken(token)) {
this.findAlbum().then(() => this.search());
} else {
this.$session.redeemToken(token).then(() => {
this.findAlbum().then(() => this.search());
});
}
this.subscriptions.push(Event.subscribe("albums.updated", (ev, data) => this.onAlbumsUpdated(ev, data)));
this.subscriptions.push(Event.subscribe("photos", (ev, data) => this.onUpdate(ev, data)));
this.subscriptions.push(Event.subscribe("touchmove.top", () => this.refresh()));
this.subscriptions.push(Event.subscribe("touchmove.bottom", () => this.loadMore()));
},
destroyed() {
for (let i = 0; i < this.subscriptions.length; i++) {
Event.unsubscribe(this.subscriptions[i]);
}
},
};
</script>