Frontend: Improve album UX

Moves albums to the top next to photos, and replaces album icons.
This commit is contained in:
Michael Mayer 2020-12-30 16:07:03 +01:00
parent d09c23addc
commit 884839331a
11 changed files with 232 additions and 215 deletions

View File

@ -1,17 +1,17 @@
<template>
<div>
<v-container fluid class="pa-0" v-if="selection.length > 0">
<v-container v-if="selection.length > 0" fluid class="pa-0">
<v-speed-dial
fixed bottom right
id="t-clipboard" v-model="expanded" fixed
bottom
right
direction="top"
v-model="expanded"
transition="slide-y-reverse-transition"
class="p-clipboard p-album-clipboard"
id="t-clipboard"
>
<v-btn
fab dark
slot="activator"
slot="activator" fab
dark
color="accent darken-2"
class="action-menu"
>
@ -20,13 +20,13 @@
</v-btn>
<v-btn
fab dark small
v-if="$config.feature('share')" fab dark
small
:title="$gettext('Share')"
color="share"
@click.stop="shareDialog()"
:disabled="selection.length !== 1"
v-if="$config.feature('share')"
class="action-share"
@click.stop="shareDialog()"
>
<v-icon>share</v-icon>
</v-btn>
@ -35,19 +35,19 @@
:title="$gettext('Edit')"
color="edit"
:disabled="selection.length !== 1"
@click.stop="editDialog()"
class="action-edit"
@click.stop="editDialog()"
>
<v-icon>edit</v-icon>
</v-btn>
<v-btn
fab dark small
v-if="$config.feature('download')" fab dark
small
:title="$gettext('Download')"
color="download"
@click.stop="download()"
class="action-download"
v-if="$config.feature('download')"
:disabled="selection.length !== 1"
@click.stop="download()"
>
<v-icon>get_app</v-icon>
</v-btn>
@ -56,27 +56,27 @@
:title="$gettext('Add to album')"
color="album"
:disabled="selection.length === 0"
@click.stop="dialog.album = true"
class="action-clone"
@click.stop="dialog.album = true"
>
<v-icon>folder_special</v-icon>
<v-icon>bookmark</v-icon>
</v-btn>
<v-btn
v-if="context === 'album'"
fab dark small
color="remove"
:title="$gettext('Delete')"
@click.stop="dialog.delete = true"
:disabled="selection.length === 0"
class="action-delete"
@click.stop="dialog.delete = true"
>
<v-icon>delete</v-icon>
</v-btn>
<v-btn
fab dark small
color="accent"
@click.stop="clearClipboard()"
class="action-clear"
@click.stop="clearClipboard()"
>
<v-icon>clear</v-icon>
</v-btn>
@ -94,7 +94,7 @@ import Notify from "common/notify";
import Album from "model/album";
export default {
name: 'p-album-clipboard',
name: 'PAlbumClipboard',
props: {
selection: Array,
refresh: Function,
@ -122,9 +122,9 @@ export default {
this.model = new Album();
this.model.find(this.selection[0]).then(
(m) => {
this.edit(m);
}
(m) => {
this.edit(m);
}
);
},
shareDialog() {
@ -135,9 +135,9 @@ export default {
this.model = new Album();
this.model.find(this.selection[0]).then(
(m) => {
this.share(m);
}
(m) => {
this.share(m);
}
);
},
clearClipboard() {
@ -173,7 +173,7 @@ 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();

View File

@ -39,7 +39,7 @@
@click.stop="dialog.album = true"
class="action-album"
>
<v-icon>folder_special</v-icon>
<v-icon>bookmark</v-icon>
</v-btn>
<v-btn

View File

@ -39,7 +39,7 @@
@click.stop="dialog.album = true"
class="action-album"
>
<v-icon>folder_special</v-icon>
<v-icon>bookmark</v-icon>
</v-btn>
<v-btn
fab dark small

View File

@ -2,16 +2,16 @@
<div id="p-navigation">
<template v-if="$vuetify.breakpoint.smAndDown || !auth">
<v-toolbar dark :dense="$vuetify.breakpoint.smAndDown" fixed flat color="navigation darken-1" class="nav-small"
@click.stop="showNavigation()" scroll-off-screen>
scroll-off-screen @click.stop="showNavigation()">
<v-toolbar-side-icon class="nav-show" v-if="auth"></v-toolbar-side-icon>
<v-toolbar-side-icon v-if="auth" class="nav-show"></v-toolbar-side-icon>
<v-toolbar-title class="nav-title">{{ page.title }}</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon @click.stop="openUpload()" v-if="auth && !config.readonly && $config.feature('upload')"
class="action-upload" :title="$gettext('Upload')">
<v-btn v-if="auth && !config.readonly && $config.feature('upload')" icon class="action-upload"
:title="$gettext('Upload')" @click.stop="openUpload()">
<v-icon>cloud_upload</v-icon>
</v-btn>
@ -22,7 +22,7 @@
<v-navigation-drawer
v-if="auth"
v-model="drawer"
:mini-variant="mini"
:mini-variant="isMini"
:width="270"
:mobile-break-point="960"
:mini-variant-width="80"
@ -41,7 +41,7 @@
</v-list-tile-title>
</v-list-tile-content>
<v-list-tile-action class="hidden-sm-and-down">
<v-btn icon @click.stop="mini = !mini" class="nav-minimize">
<v-btn icon class="nav-minimize" @click.stop="isMini = !isMini">
<v-icon>chevron_left</v-icon>
</v-btn>
</v-list-tile-action>
@ -50,13 +50,13 @@
</v-toolbar>
<v-list class="pt-3">
<v-list-tile v-if="mini" @click.stop="mini = !mini" class="nav-expand">
<v-list-tile v-if="isMini" class="nav-expand" @click.stop="isMini = !isMini">
<v-list-tile-action>
<v-icon>chevron_right</v-icon>
</v-list-tile-action>
</v-list-tile>
<v-list-tile v-if="mini" to="/photos" @click="" class="nav-photos">
<v-list-tile v-if="isMini" to="/photos" class="nav-photos" @click.stop="">
<v-list-tile-action :title="$gettext('Photos')">
<v-icon>photo</v-icon>
</v-list-tile-action>
@ -68,8 +68,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-group v-if="!mini" prepend-icon="photo" no-action>
<v-list-tile slot="activator" to="/photos" @click.stop="" class="nav-photos">
<v-list-group v-if="!isMini" prepend-icon="photo" no-action>
<v-list-tile slot="activator" to="/photos" class="nav-photos" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Photos">Photos</translate>
@ -78,7 +78,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{name: 'photos', query: { q: 'mono:true quality:3 photo:true' }}" :exact="true" @click="">
<v-list-tile :to="{name: 'photos', query: { q: 'mono:true quality:3 photo:true' }}" :exact="true" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Monochrome</translate>
@ -86,8 +86,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{name: 'photos', query: { q: 'panorama:true' }}" :exact="true" @click=""
class="nav-panoramas">
<v-list-tile :to="{name: 'photos', query: { q: 'panorama:true' }}" :exact="true" class="nav-panoramas"
@click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Panoramas</translate>
@ -95,7 +95,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{name: 'photos', query: { q: 'stack:true' }}" :exact="true" @click="" class="nav-stacks">
<v-list-tile :to="{name: 'photos', query: { q: 'stack:true' }}" :exact="true" class="nav-stacks" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Stacks</translate>
@ -103,7 +103,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{name: 'photos', query: { q: 'scan:true' }}" :exact="true" @click="" class="nav-scans">
<v-list-tile :to="{name: 'photos', query: { q: 'scan:true' }}" :exact="true" class="nav-scans" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Scans</translate>
@ -111,8 +111,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/review" @click="" v-if="$config.feature('review')"
class="nav-review">
<v-list-tile v-if="$config.feature('review')" to="/review" class="nav-review"
@click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Review</translate>
@ -121,7 +121,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/archive" @click="" class="nav-archive" v-show="$config.feature('archive')">
<v-list-tile v-show="$config.feature('archive')" to="/archive" class="nav-archive" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Archive</translate>
@ -130,48 +130,9 @@
</v-list-tile>
</v-list-group>
<v-list-tile to="/favorites" @click="" class="nav-favorites">
<v-list-tile-action :title="$gettext('Favorites')">
<v-icon>favorite</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Favorites">Favorites</translate>
<span v-show="config.count.favorites > 0" class="nav-count">{{ config.count.favorites }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/private" @click="" class="nav-private" v-show="$config.feature('private')">
<v-list-tile-action :title="$gettext('Private')">
<v-icon>lock</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Private">Private</translate>
<span v-show="config.count.private > 0" class="nav-count">{{ config.count.private }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/videos" @click="" class="nav-video">
<v-list-tile-action :title="$gettext('Videos')">
<v-icon>movie_creation</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Videos">Videos</translate>
<span v-show="config.count.videos > 0" class="nav-count">{{ config.count.videos }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-if="mini" to="/albums" @click="" class="nav-albums">
<v-list-tile v-if="isMini" to="/albums" class="nav-albums" @click.stop="">
<v-list-tile-action :title="$gettext('Albums')">
<v-icon>folder_special</v-icon>
<v-icon>bookmarks</v-icon>
</v-list-tile-action>
<v-list-tile-content>
@ -181,8 +142,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-group v-if="!mini" prepend-icon="folder_special" no-action>
<v-list-tile slot="activator" to="/albums" @click.stop="" class="nav-albums">
<v-list-group v-if="!isMini" prepend-icon="bookmarks" no-action>
<v-list-tile slot="activator" to="/albums" class="nav-albums" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Albums">Albums</translate>
@ -200,9 +161,48 @@
</v-list-tile>
</v-list-group>
<v-list-tile :to="{ name: 'folders' }" @click="" class="nav-folders">
<v-list-tile to="/favorites" class="nav-favorites" @click.stop="">
<v-list-tile-action :title="$gettext('Favorites')">
<v-icon>favorite</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Favorites">Favorites</translate>
<span v-show="config.count.favorites > 0" class="nav-count">{{ config.count.favorites }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-show="$config.feature('private')" to="/private" class="nav-private" @click.stop="">
<v-list-tile-action :title="$gettext('Private')">
<v-icon>lock</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Private">Private</translate>
<span v-show="config.count.private > 0" class="nav-count">{{ config.count.private }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/videos" class="nav-video" @click.stop="">
<v-list-tile-action :title="$gettext('Videos')">
<v-icon>movie_creation</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>
<translate key="Videos">Videos</translate>
<span v-show="config.count.videos > 0" class="nav-count">{{ config.count.videos }}</span>
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{ name: 'folders' }" class="nav-folders" @click.stop="">
<v-list-tile-action :title="$gettext('Folders')">
<v-icon>inbox</v-icon>
<v-icon>folder</v-icon>
</v-list-tile-action>
<v-list-tile-content>
@ -214,7 +214,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{ name: 'calendar' }" @click="" class="nav-calendar">
<v-list-tile :to="{ name: 'calendar' }" class="nav-calendar" @click.stop="">
<v-list-tile-action :title="$gettext('Calendar')">
<v-icon>date_range</v-icon>
</v-list-tile-action>
@ -228,10 +228,10 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{ name: 'moments' }" @click="" class="nav-moments"
v-show="$config.feature('moments')">
<v-list-tile v-show="$config.feature('moments')" :to="{ name: 'moments' }" class="nav-moments"
@click.stop="">
<v-list-tile-action :title="$gettext('Moments')">
<v-icon>star</v-icon>
<v-icon>explore</v-icon>
</v-list-tile-action>
<v-list-tile-content>
@ -243,8 +243,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-if="mini" :to="{ name: 'places' }" @click="" class="nav-places"
v-show="$config.feature('places')">
<v-list-tile v-if="isMini" v-show="$config.feature('places')" :to="{ name: 'places' }" class="nav-places"
@click.stop="">
<v-list-tile-action :title="$gettext('Places')">
<v-icon>place</v-icon>
</v-list-tile-action>
@ -256,8 +256,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-group v-if="!mini" prepend-icon="place" no-action v-show="$config.feature('places')">
<v-list-tile slot="activator" to="/places" @click.stop="" class="nav-places">
<v-list-group v-if="!isMini" v-show="$config.feature('places')" prepend-icon="place" no-action>
<v-list-tile slot="activator" to="/places" class="nav-places" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Places">Places</translate>
@ -267,7 +267,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/states" @click="" class="nav-states">
<v-list-tile to="/states" class="nav-states" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="States">States</translate>
@ -277,7 +277,7 @@
</v-list-tile>
</v-list-group>
<v-list-tile to="/labels" @click="" class="nav-labels" v-show="$config.feature('labels')">
<v-list-tile v-show="$config.feature('labels')" to="/labels" class="nav-labels" @click.stop="">
<v-list-tile-action :title="$gettext('Labels')">
<v-icon>label</v-icon>
</v-list-tile-action>
@ -291,7 +291,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-if="mini && $config.feature('library')" to="/library" @click="" class="nav-library">
<v-list-tile v-if="isMini && $config.feature('library')" to="/library" class="nav-library" @click.stop="">
<v-list-tile-action :title="$gettext('Library')">
<v-icon>camera_roll</v-icon>
</v-list-tile-action>
@ -303,8 +303,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-group v-if="!mini && $config.feature('library')" prepend-icon="camera_roll" no-action>
<v-list-tile slot="activator" to="/library" @click.stop="" class="nav-library">
<v-list-group v-if="!isMini && $config.feature('library')" prepend-icon="camera_roll" no-action>
<v-list-tile slot="activator" to="/library" class="nav-library" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Library">Library</translate>
@ -312,7 +312,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/library/files" @click="" class="nav-originals" v-show="$config.feature('files')">
<v-list-tile v-show="$config.feature('files')" to="/library/files" class="nav-originals" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Originals">Originals</translate>
@ -321,7 +321,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/library/hidden" @click="" class="nav-hidden">
<v-list-tile to="/library/hidden" class="nav-hidden" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Hidden">Hidden</translate>
@ -330,7 +330,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/library/errors" @click="" class="nav-errors">
<v-list-tile to="/library/errors" class="nav-errors" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Errors">Errors</translate>
@ -340,7 +340,7 @@
</v-list-group>
<template v-if="!config.disable.settings">
<v-list-tile v-if="mini" to="/settings" @click="" class="nav-settings">
<v-list-tile v-if="isMini" to="/settings" class="nav-settings" @click.stop="">
<v-list-tile-action :title="$gettext('Settings')">
<v-icon>settings</v-icon>
</v-list-tile-action>
@ -353,7 +353,7 @@
</v-list-tile>
<v-list-group v-else prepend-icon="settings" no-action>
<v-list-tile slot="activator" to="/settings" @click.stop="" class="nav-settings">
<v-list-tile slot="activator" to="/settings" class="nav-settings" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="Settings">Settings</translate>
@ -361,7 +361,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{ name: 'about' }" :exact="true" @click="" class="nav-about">
<v-list-tile :to="{ name: 'about' }" :exact="true" class="nav-about" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>About</translate>
@ -369,8 +369,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{ name: 'feedback' }" :exact="true" @click="" v-show="!public && auth"
class="nav-feedback">
<v-list-tile v-show="!isPublic && auth" :to="{ name: 'feedback' }" :exact="true" class="nav-feedback"
@click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate>Feedback</translate>
@ -378,7 +378,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile :to="{ name: 'license' }" :exact="true" @click="" class="nav-license">
<v-list-tile :to="{ name: 'license' }" :exact="true" class="nav-license" @click.stop="">
<v-list-tile-content>
<v-list-tile-title>
<translate key="License">License</translate>
@ -388,7 +388,7 @@
</v-list-group>
</template>
<v-list-tile @click="logout" class="nav-logout" v-show="!public && auth">
<v-list-tile v-show="!isPublic && auth" class="nav-logout" @click="logout">
<v-list-tile-action :title="$gettext('Logout')">
<v-icon>power_settings_new</v-icon>
</v-list-tile-action>
@ -400,7 +400,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/login" @click="" class="nav-login" v-show="!auth">
<v-list-tile v-show="!auth" to="/login" class="nav-login" @click.stop="">
<v-list-tile-action :title="$gettext('Login')">
<v-icon>lock</v-icon>
</v-list-tile-action>
@ -412,8 +412,8 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile to="/help/websockets" @click="" class="nav-connecting navigation" v-show="$config.disconnected"
style="position:fixed; bottom: 0; left:0; right: 0;">
<v-list-tile v-show="$config.disconnected" to="/help/websockets" class="nav-connecting navigation" style="position:fixed; bottom: 0; left:0; right: 0;"
@click.stop="">
<v-list-tile-action :title="$gettext('Offline')">
<v-icon color="warning">wifi_off</v-icon>
</v-list-tile-action>
@ -439,14 +439,14 @@ import Album from "model/album";
import Event from "pubsub-js";
export default {
name: "p-navigation",
name: "PNavigation",
data() {
return {
drawer: null,
mini: true,
isMini: true,
isPublic: this.$config.get("public"),
isReadOnly: this.$config.get("readonly"),
session: this.$session,
public: this.$config.get("public"),
readonly: this.$config.get("readonly"),
config: this.$config.values,
page: this.$config.page,
reload: {
@ -468,38 +468,7 @@ export default {
},
computed: {
auth() {
return this.session.auth || this.public
},
},
methods: {
openUpload() {
if (this.auth && !this.readonly && this.$config.feature('upload')) {
this.upload.dialog = true;
} else {
this.goHome();
}
},
feature(name) {
return this.$config.values.settings.features[name];
},
goHome() {
if (this.$route.name !== "home") {
this.$router.push({name: "home"});
}
},
showNavigation() {
if (this.auth) {
this.drawer = true;
this.mini = false;
}
},
createAlbum() {
let name = "New Album";
const album = new Album({Title: name, Favorite: false});
album.save();
},
logout() {
this.$session.logout();
return this.session.auth || this.isPublic;
},
},
created() {
@ -519,6 +488,37 @@ export default {
Event.unsubscribe(this.reload.subscription);
Event.unsubscribe(this.upload.subscription);
Event.unsubscribe(this.edit.subscription);
},
methods: {
openUpload() {
if (this.auth && !this.isReadOnly && this.$config.feature('upload')) {
this.upload.dialog = true;
} else {
this.goHome();
}
},
feature(name) {
return this.$config.values.settings.features[name];
},
goHome() {
if (this.$route.name !== "home") {
this.$router.push({name: "home"});
}
},
showNavigation() {
if (this.auth) {
this.drawer = true;
this.isMini = false;
}
},
createAlbum() {
let name = "New Album";
const album = new Album({Title: name, Favorite: false});
album.save();
},
logout() {
this.$session.logout();
},
}
};
</script>

View File

@ -83,7 +83,7 @@
class="action-album"
@click.stop="dialog.album = true"
>
<v-icon>folder_special</v-icon>
<v-icon>bookmark</v-icon>
</v-btn>
<v-btn
v-if="!isAlbum && context !== 'archive' && config.settings.features.archive" fab dark
@ -116,7 +116,7 @@
class="action-delete"
@click.stop="removeFromAlbum"
>
<v-icon>remove</v-icon>
<v-icon>eject</v-icon>
</v-btn>
<v-btn
fab dark small

View File

@ -1,24 +1,26 @@
<template>
<div>
<v-card v-if="photos.length === 0" class="p-photos-empty secondary-light lighten-1 ma-1" flat>
<v-card-title primary-title>
<div>
<h3 v-if="filter.order === 'edited'" class="title ma-0 pa-0">
<translate>Couldn't find recently edited</translate>
</h3>
<h3 v-else class="title ma-0 pa-0">
<translate>Couldn't find anything</translate>
</h3>
<p class="mt-4 mb-0 pa-0">
<translate>Try again using other filters or keywords.</translate>
<translate>If a file you expect is missing, please re-index your library and wait until indexing has been completed.</translate>
<template v-if="config.settings.features.review" class="mt-2 mb-0 pa-0">
<translate>Non-photographic and low-quality images require a review before they appear in search results.</translate>
</template>
</p>
</div>
</v-card-title>
</v-card>
<div v-if="photos.length === 0" class="pa-2">
<v-card class="p-photos-empty secondary-light lighten-1 ma-1" flat>
<v-card-title primary-title>
<div>
<h3 v-if="filter.order === 'edited'" class="title ma-0 pa-0">
<translate>Couldn't find recently edited</translate>
</h3>
<h3 v-else class="title ma-0 pa-0">
<translate>Couldn't find anything</translate>
</h3>
<p class="mt-4 mb-0 pa-0">
<translate>Try again using other filters or keywords.</translate>
<translate>If a file you expect is missing, please re-index your library and wait until indexing has been completed.</translate>
<template v-if="config.settings.features.review" class="mt-2 mb-0 pa-0">
<translate>Non-photographic and low-quality images require a review before they appear in search results.</translate>
</template>
</p>
</div>
</v-card-title>
</v-card>
</div>
<v-data-table v-else
v-model="selected"
:headers="listColumns"

View File

@ -4,8 +4,7 @@
<v-container fluid class="pb-2 pr-2 pl-2">
<v-layout row wrap>
<v-flex xs3 text-xs-center>
<v-icon v-if="!album" size="54" color="secondary-dark lighten-1">create_new_folder</v-icon>
<v-icon v-else size="54" color="secondary-dark lighten-1">folder_special</v-icon>
<v-icon size="54" color="secondary-dark lighten-1">bookmark</v-icon>
</v-flex>
<v-flex xs9 text-xs-left align-self-center>
<v-autocomplete

View File

@ -44,7 +44,7 @@
class="v-chip--select-multi"
@input="data.parent.selectItem(data.item)"
>
<v-icon class="pr-1">folder_special</v-icon>
<v-icon class="pr-1">bookmark</v-icon>
{{ data.item.Title ? data.item.Title : data.item | truncate(40) }}
</v-chip>
</template>

View File

@ -1,7 +1,7 @@
<template>
<v-dialog
lazy
v-model="visible"
lazy
max-width="500"
>
<v-card class="pa-2">
@ -20,9 +20,9 @@
single-line
outline
color="secondary-dark"
@click.stop="selectText($event)"
:value="webdavUrl()"
class="input-url">
class="input-url"
@click.stop="selectText($event)">
</v-text-field>
</v-card-text>
@ -50,7 +50,7 @@
<script>
export default {
name: 'p-dialog-webdav',
name: 'PDialogWebdav',
props: {
show: Boolean,
},
@ -81,7 +81,7 @@ export default {
},
copyUrl() {
window.navigator.clipboard.writeText(this.webdavUrl())
.then(() => this.$notify.success(this.$gettext("Copied to clipboard")), () => this.$notify.error(this.$gettext("Failed copying to clipboard")));
.then(() => this.$notify.success(this.$gettext("Copied to clipboard")), () => this.$notify.error(this.$gettext("Failed copying to clipboard")));
},
webdavUrl() {
return `${window.location.protocol}//admin@${window.location.host}/originals/`;

View File

@ -1,28 +1,30 @@
<template>
<div>
<v-card v-if="photos.length === 0" class="p-photos-empty secondary-light lighten-1 ma-1" flat>
<v-card-title primary-title>
<div>
<h3 class="title ma-0 pa-0" v-if="filter.order === 'edited'">
<translate>Couldn't find recently edited</translate>
</h3>
<h3 class="title ma-0 pa-0" v-else>
<translate>Couldn't find anything</translate>
</h3>
<p class="mt-4 mb-0 pa-0">
<translate>Try again using other filters or keywords.</translate>
</p>
</div>
</v-card-title>
</v-card>
<div v-if="photos.length === 0" class="pa-2">
<v-card class="p-photos-empty secondary-light lighten-1 ma-1" flat>
<v-card-title primary-title>
<div>
<h3 v-if="filter.order === 'edited'" class="title ma-0 pa-0">
<translate>Couldn't find recently edited</translate>
</h3>
<h3 v-else class="title ma-0 pa-0">
<translate>Couldn't find anything</translate>
</h3>
<p class="mt-4 mb-0 pa-0">
<translate>Try again using other filters or keywords.</translate>
</p>
</div>
</v-card-title>
</v-card>
</div>
<v-data-table v-else
v-model="selected"
:headers="listColumns"
:items="photos"
hide-actions
class="elevation-0 p-photos p-photo-list p-results"
disable-initial-sort
item-key="ID"
v-model="selected"
:no-data-text="notFoundMessage"
>
<template slot="items" slot-scope="props">
@ -58,24 +60,24 @@
</td>
<td class="p-photo-desc clickable" :data-uid="props.item.UID"
@click.stop.prevent="openPhoto(props.index, false)" style="user-select: none;">
style="user-select: none;" @click.stop.prevent="openPhoto(props.index, false)">
{{ props.item.Title }}
</td>
<td class="p-photo-desc hidden-xs-only" :title="props.item.getDateString()"
@click.stop.prevent="openPhoto(props.index, false)" style="user-select: none;">
style="user-select: none;" @click.stop.prevent="openPhoto(props.index, false)">
{{ props.item.shortDateString() }}
</td>
<td class="p-photo-desc hidden-sm-and-down" style="user-select: none;">
{{ props.item.CameraMake }} {{ props.item.CameraModel }}
</td>
<td class="p-photo-desc hidden-xs-only">
<button @click.exact="downloadFile(props.index)"
title="Name" v-if="filter.order === 'name'">
<button v-if="filter.order === 'name'"
title="Name" @click.exact="downloadFile(props.index)">
{{ props.item.FileName }}
</button>
<button v-else-if="props.item.Country !== 'zz' && showLocation"
@click.stop.prevent="openPhoto(props.index, false)"
style="user-select: none;">
style="user-select: none;"
@click.stop.prevent="openPhoto(props.index, false)">
{{ props.item.locationInfo() }}
</button>
<span v-else>
@ -88,7 +90,7 @@
</template>
<script>
export default {
name: 'p-photo-list',
name: 'PPhotoList',
props: {
photos: Array,
selection: Array,
@ -103,7 +105,7 @@ export default {
m += " " + this.$gettext("Try again using other filters or keywords.");
let showName = this.filter.order === 'name'
let showName = this.filter.order === 'name';
return {
notFoundMessage: m,
@ -143,13 +145,18 @@ export default {
this.refreshSelection();
},
},
mounted: function () {
this.$nextTick(function () {
this.refreshSelection();
});
},
methods: {
downloadFile(index) {
const photo = this.photos[index];
const link = document.createElement('a')
const link = document.createElement('a');
link.href = `/api/v1/dl/${photo.Hash}?t=${this.$config.downloadToken()}`;
link.download = photo.FileName;
link.click()
link.click();
},
onSelect(ev, index) {
if (ev.shiftKey) {
@ -200,11 +207,6 @@ export default {
}
}
},
},
mounted: function () {
this.$nextTick(function () {
this.refreshSelection();
})
}
};
</script>

View File

@ -21,9 +21,23 @@ var fileIconSvg = []byte(`<svg xmlns="http://www.w3.org/2000/svg" height="24" vi
var videoIconSvg = []byte(`<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
<path d="M0 0h24v24H0z" fill="none"/><path d="M10 8v8l5-4-5-4zm9-5H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></svg>`)
var albumIconSvg = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>
<path d="M0 0h24v24H0z" fill="none"/></svg>`)
var albumIconSvg = []byte(`<svg id="f394fb39-4024-46e8-9a68-3f5e53f52bfd" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 276.76 276.76">
<defs>
<style>
.a8bd947d-a1f8-4a14-8069-c9663505e4b1{fill:url(#b905e2c4-4772-4914-b70f-44b4d19aca4b);}.a4ee1f07-8fee-4200-835a-e030a32bca90{fill:none;stroke:#1d1d1b;stroke-miterlimit:10;stroke-width:5px;}
</style>
<linearGradient id="b905e2c4-4772-4914-b70f-44b4d19aca4b" x1="45.04" y1="231.72" x2="231.72" y2="45.04"
gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#fff"/>
<stop offset="0" stop-color="#c2fde4"/>
<stop offset="1" stop-color="#cdc6e9"/>
</linearGradient>
</defs>
<circle class="a8bd947d-a1f8-4a14-8069-c9663505e4b1" cx="138.38" cy="138.38" r="132"/>
<path id="bfa29dbe-bd65-4058-95bb-bdb844b1d3b1" data-name="Logo Pfad" class="a4ee1f07-8fee-4200-835a-e030a32bca90"
d="M229.57,181.89l-4,24.19M47.29,182.88l14.81,14M157.86,59.23,62,196.69a.09.09,0,0,0,.07.15l163.41,9.37a.09.09,0,0,0,.09-.13L158,59.25A.1.1,0,0,0,157.86,59.23ZM138.12,45.94,47.18,182.69a.13.13,0,0,0,.11.19l182.18-.8a.12.12,0,0,0,.1-.19L138.33,45.94A.12.12,0,0,0,138.12,45.94Zm.11-.16L158,59.1"/>
</svg>`)
var labelIconSvg = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none"/><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg>`)