Add album edit dialog
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
b01faead9c
commit
95802d9f6c
14 changed files with 212 additions and 138 deletions
|
@ -208,6 +208,14 @@ class Config {
|
|||
previewToken() {
|
||||
return this.values["previewToken"];
|
||||
}
|
||||
|
||||
albumCategories() {
|
||||
if(this.values["albumCategories"]) {
|
||||
return this.values["albumCategories"];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export default Config;
|
||||
|
|
|
@ -3,26 +3,9 @@
|
|||
ref="form" autocomplete="off" class="p-photo-toolbar p-album-toolbar" accept-charset="UTF-8"
|
||||
@submit.prevent="filterChange">
|
||||
<v-toolbar flat color="secondary">
|
||||
<v-edit-dialog
|
||||
:return-value.sync="album.Title"
|
||||
lazy
|
||||
@save="updateAlbum()"
|
||||
class="p-inline-edit">
|
||||
<v-toolbar-title>
|
||||
{{ album.Title }}
|
||||
</v-toolbar-title>
|
||||
<template v-slot:input>
|
||||
<v-text-field
|
||||
v-model="album.Title"
|
||||
:rules="[titleRule]"
|
||||
:label="labels.title"
|
||||
color="secondary-dark"
|
||||
single-line
|
||||
autofocus
|
||||
class="input-title"
|
||||
></v-text-field>
|
||||
</template>
|
||||
</v-edit-dialog>
|
||||
<v-toolbar-title :title="album.Title">
|
||||
{{ album.Title }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
|
@ -30,6 +13,10 @@
|
|||
<v-icon>refresh</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn icon @click.stop="dialog.edit = true">
|
||||
<v-icon>edit</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn icon @click.stop="dialog.share = true" v-if="$config.feature('share')">
|
||||
<v-icon>share</v-icon>
|
||||
</v-btn>
|
||||
|
@ -48,80 +35,30 @@
|
|||
class="hidden-sm-and-down">
|
||||
<v-icon>cloud_upload</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn icon @click.stop="expand" class="p-expand-search">
|
||||
<v-icon>{{ searchExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
||||
<v-card class="pt-1"
|
||||
flat
|
||||
color="secondary-light"
|
||||
v-show="searchExpanded">
|
||||
<v-card-text>
|
||||
<v-layout row wrap>
|
||||
<v-flex xs12 sm6 md3 pa-2 class="p-countries-select">
|
||||
<v-combobox flat solo hide-details color="secondary-dark"
|
||||
v-model="album.Category"
|
||||
:items="categories"
|
||||
:label="labels.category"
|
||||
@change="updateAlbum"
|
||||
:allow-overflow="false"
|
||||
return-masked-value
|
||||
class="input-category"
|
||||
></v-combobox>
|
||||
</v-flex>
|
||||
<v-flex xs12 sm6 md3 pa-2 class="p-camera-select">
|
||||
<v-select @change="dropdownChange"
|
||||
:label="labels.camera"
|
||||
flat solo hide-details
|
||||
color="secondary-dark"
|
||||
item-value="ID"
|
||||
item-text="Name"
|
||||
v-model="filter.camera"
|
||||
:items="options.cameras">
|
||||
</v-select>
|
||||
</v-flex>
|
||||
<v-flex xs12 sm6 md3 pa-2 class="p-view-select">
|
||||
<v-select @change="dropdownChange"
|
||||
:label="labels.view"
|
||||
flat solo hide-details
|
||||
color="secondary-dark"
|
||||
v-model="settings.view"
|
||||
:items="options.views"
|
||||
id="viewSelect">
|
||||
</v-select>
|
||||
</v-flex>
|
||||
<v-flex xs12 sm6 md3 pa-2 class="p-time-select">
|
||||
<v-select @change="dropdownChange"
|
||||
:label="labels.sort"
|
||||
flat solo hide-details
|
||||
color="secondary-dark"
|
||||
v-model="filter.order"
|
||||
:items="options.sorting">
|
||||
</v-select>
|
||||
</v-flex>
|
||||
<v-flex xs12 pa-2>
|
||||
<v-textarea flat solo auto-grow
|
||||
browser-autocomplete="off"
|
||||
:label="labels.description"
|
||||
:rows="2"
|
||||
:key="growDesc"
|
||||
color="secondary-dark"
|
||||
style="background-color: white"
|
||||
v-model="album.Description"
|
||||
@change="updateAlbum"
|
||||
class="input-description"
|
||||
>
|
||||
</v-textarea>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<template v-if="album.Description">
|
||||
<v-card flat class="px-2 py-1 hidden-sm-and-down"
|
||||
color="secondary-light"
|
||||
>
|
||||
<v-card-text>
|
||||
{{ album.Description }}
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-card flat class="pa-0 hidden-md-and-up"
|
||||
color="secondary-light"
|
||||
>
|
||||
<v-card-text>
|
||||
{{ album.Description }}
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<p-share-dialog :show="dialog.share" :model="album" @upload="webdavUpload"
|
||||
@close="dialog.share = false"></p-share-dialog>
|
||||
<p-share-upload-dialog :show="dialog.upload" :selection="[album.getId()]" @cancel="dialog.upload = false"
|
||||
@confirm="dialog.upload = false"></p-share-upload-dialog>
|
||||
<p-album-edit-dialog :show="dialog.edit" :album="album" @close="dialog.edit = false"></p-album-edit-dialog>
|
||||
</v-form>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -146,12 +83,10 @@
|
|||
Name: this.$gettext('All Countries')
|
||||
}].concat(this.$config.get('countries'));
|
||||
|
||||
const configValues = this.$config.values;
|
||||
|
||||
return {
|
||||
experimental: this.$config.get("experimental"),
|
||||
isFullScreen: !!document.fullscreenElement,
|
||||
categories: configValues.albumCategories ? configValues.albumCategories : [],
|
||||
categories: this.$config.albumCategories(),
|
||||
searchExpanded: false,
|
||||
options: {
|
||||
'views': [
|
||||
|
@ -162,7 +97,7 @@
|
|||
'countries': countries,
|
||||
'cameras': cameras,
|
||||
'sorting': [
|
||||
{value: 'imported', text: this.$gettext('Recently added')},
|
||||
{value: 'added', text: this.$gettext('Recently added')},
|
||||
{value: 'newest', text: this.$gettext('Newest first')},
|
||||
{value: 'oldest', text: this.$gettext('Oldest first')},
|
||||
{value: 'name', text: this.$gettext('Sort by file name')},
|
||||
|
@ -173,6 +108,7 @@
|
|||
dialog: {
|
||||
share: false,
|
||||
upload: false,
|
||||
edit: false,
|
||||
},
|
||||
labels: {
|
||||
title: this.$gettext("Album Name"),
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
{value: 'list', text: this.$gettext('List')},
|
||||
],
|
||||
'sorting': [
|
||||
{value: 'imported', text: this.$gettext('Recently added')},
|
||||
{value: 'added', text: this.$gettext('Recently added')},
|
||||
{value: 'newest', text: this.$gettext('Newest first')},
|
||||
{value: 'oldest', text: this.$gettext('Oldest first')},
|
||||
{value: 'name', text: this.$gettext('Sort by file name')},
|
||||
|
|
|
@ -34,6 +34,7 @@ import PAccountEditDialog from "./account/edit.vue";
|
|||
import PPhotoArchiveDialog from "./p-photo-archive-dialog.vue";
|
||||
import PPhotoAlbumDialog from "./p-photo-album-dialog.vue";
|
||||
import PPhotoEditDialog from "./p-photo-edit-dialog.vue";
|
||||
import PAlbumEditDialog from "./p-album-edit-dialog.vue";
|
||||
import PAlbumDeleteDialog from "./album/delete.vue";
|
||||
import PLabelDeleteDialog from "./label/delete.vue";
|
||||
import PUploadDialog from "./p-upload-dialog.vue";
|
||||
|
@ -50,6 +51,7 @@ dialogs.install = (Vue) => {
|
|||
Vue.component("p-photo-archive-dialog", PPhotoArchiveDialog);
|
||||
Vue.component("p-photo-album-dialog", PPhotoAlbumDialog);
|
||||
Vue.component("p-photo-edit-dialog", PPhotoEditDialog);
|
||||
Vue.component("p-album-edit-dialog", PAlbumEditDialog);
|
||||
Vue.component("p-album-delete-dialog", PAlbumDeleteDialog);
|
||||
Vue.component("p-label-delete-dialog", PLabelDeleteDialog);
|
||||
Vue.component("p-upload-dialog", PUploadDialog);
|
||||
|
|
142
frontend/src/dialog/p-album-edit-dialog.vue
Normal file
142
frontend/src/dialog/p-album-edit-dialog.vue
Normal file
|
@ -0,0 +1,142 @@
|
|||
<template>
|
||||
<v-dialog lazy v-model="show" persistent max-width="500" class="dialog-album-edit" color="application"
|
||||
@keydown.esc="close">
|
||||
<v-form lazy-validation dense
|
||||
ref="form" class="form-album-edit" accept-charset="UTF-8"
|
||||
@submit.prevent="confirm">
|
||||
<v-card raised elevation="24">
|
||||
<v-card-title primary-title class="pb-0">
|
||||
<v-layout row wrap>
|
||||
<v-flex xs12>
|
||||
<h3 class="headline mx-2 mb-0">
|
||||
<translate :translate-params="{name: model.modelName()}">Edit %{name}</translate>
|
||||
</h3>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-container fluid class="pa-0">
|
||||
<v-layout row wrap>
|
||||
<v-flex xs12 pa-2>
|
||||
<v-text-field hide-details
|
||||
v-model="model.Title"
|
||||
:rules="[titleRule]"
|
||||
:label="labels.title"
|
||||
color="secondary-dark"
|
||||
class="input-title"
|
||||
></v-text-field>
|
||||
</v-flex>
|
||||
<v-flex xs12 pa-2>
|
||||
<v-textarea auto-grow hide-details
|
||||
browser-autocomplete="off"
|
||||
:label="labels.description"
|
||||
:rows="1"
|
||||
:key="growDesc"
|
||||
v-model="model.Description"
|
||||
class="input-description"
|
||||
color="secondary-dark">
|
||||
</v-textarea>
|
||||
</v-flex>
|
||||
<v-flex xs12 md6 pa-2>
|
||||
<v-combobox hide-details
|
||||
v-model="model.Category"
|
||||
:items="categories"
|
||||
:label="labels.category"
|
||||
:allow-overflow="false"
|
||||
return-masked-value
|
||||
color="secondary-dark"
|
||||
class="input-category"
|
||||
></v-combobox>
|
||||
</v-flex>
|
||||
<v-flex xs12 md6 pa-2>
|
||||
<v-select
|
||||
:label="labels.sort"
|
||||
hide-details
|
||||
v-model="model.Order"
|
||||
:items="sorting"
|
||||
item-value="value"
|
||||
item-text="text"
|
||||
color="secondary-dark">
|
||||
</v-select>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
<v-card-actions class="pt-0">
|
||||
<v-layout row wrap class="pa-2">
|
||||
<v-flex xs12 text-xs-right>
|
||||
<v-btn @click.stop="close" depressed
|
||||
color="secondary-light"
|
||||
class="action-cancel">
|
||||
<translate>Cancel</translate>
|
||||
</v-btn>
|
||||
<v-btn @click.stop="confirm" depressed dark
|
||||
color="secondary-dark"
|
||||
class="action-confirm">
|
||||
<translate>Save</translate>
|
||||
</v-btn>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-form>
|
||||
</v-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import Album from "model/album";
|
||||
|
||||
export default {
|
||||
name: 'p-album-edit-dialog',
|
||||
props: {
|
||||
show: Boolean,
|
||||
album: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: new Album(),
|
||||
growDesc: false,
|
||||
loading: false,
|
||||
sorting: [
|
||||
{value: 'added', text: this.$gettext('Recently added')},
|
||||
{value: 'newest', text: this.$gettext('Newest first')},
|
||||
{value: 'oldest', text: this.$gettext('Oldest first')},
|
||||
{value: 'name', text: this.$gettext('Sort by file name')},
|
||||
{value: 'similar', text: this.$gettext('Group by similarity')},
|
||||
{value: 'relevance', text: this.$gettext('Most relevant')},
|
||||
],
|
||||
categories: this.$config.albumCategories(),
|
||||
titleRule: v => v.length <= this.$config.get('clip') || this.$gettext("Name too long"),
|
||||
labels: {
|
||||
title: this.$gettext("Name"),
|
||||
description: this.$gettext("Description"),
|
||||
search: this.$gettext("Search"),
|
||||
view: this.$gettext("View"),
|
||||
country: this.$gettext("Country"),
|
||||
camera: this.$gettext("Camera"),
|
||||
sort: this.$gettext("Sort Order"),
|
||||
category: this.$gettext("Category"),
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
expand() {
|
||||
this.growDesc = !this.growDesc;
|
||||
},
|
||||
close() {
|
||||
this.$emit('close');
|
||||
},
|
||||
confirm() {
|
||||
this.$emit('close');
|
||||
this.model.update();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
show: function (show) {
|
||||
if (show) {
|
||||
this.model = this.album.clone();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -27,11 +27,11 @@
|
|||
</v-autocomplete>
|
||||
</v-flex>
|
||||
<v-flex xs12 text-xs-right class="pt-3">
|
||||
<v-btn @click.stop="cancel" depressed color="grey lighten-3" class="p-photo-dialog-cancel">
|
||||
<v-btn @click.stop="cancel" depressed color="secondary-light" class=action-cancel">
|
||||
<translate key="Cancel">Cancel</translate>
|
||||
</v-btn>
|
||||
<v-btn color="blue-grey lighten-2" depressed dark @click.stop="confirm"
|
||||
class="p-photo-dialog-confirm">
|
||||
<v-btn color="secondary-dark" depressed dark @click.stop="confirm"
|
||||
class="action-confirm">
|
||||
<span v-if="newAlbum">{{ labels.createAlbum }}</span>
|
||||
<span v-else>{{ labels.addToAlbum }}</span>
|
||||
</v-btn>
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
<div class="subheading pr-1"><translate key="Are you sure">Are you sure you want to archive these photos?</translate></div>
|
||||
</v-flex>
|
||||
<v-flex xs12 text-xs-right class="pt-3">
|
||||
<v-btn @click.stop="cancel" depressed color="grey lighten-3" class="p-photo-dialog-cancel">
|
||||
<v-btn @click.stop="cancel" depressed color="secondary-light" class="action-cancel">
|
||||
<translate key="Cancel">Cancel</translate>
|
||||
</v-btn>
|
||||
<v-btn color="blue-grey lighten-2" depressed dark @click.stop="confirm"
|
||||
class="p-photo-dialog-confirm"><translate key="Archive">Archive</translate>
|
||||
<v-btn color="secondary-dark" depressed dark @click.stop="confirm"
|
||||
class="action-confirm"><translate key="Archive">Archive</translate>
|
||||
</v-btn>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<v-card-title primary-title class="pb-0">
|
||||
<v-layout row wrap>
|
||||
<v-flex xs9>
|
||||
<h3 class="headline mb-0">Share {{model.modelName()}}<!-- TODO: translate--></h3>
|
||||
<h3 class="headline mb-0"><translate :translate-params="{name: model.modelName()}">Share %{name}</translate></h3>
|
||||
</v-flex>
|
||||
<v-flex xs3 text-xs-right>
|
||||
<v-btn icon flat dark color="secondary-dark" class="ma-0 action-add-link" @click.stop="add" :title="$gettext('Add Link')">
|
||||
|
|
|
@ -134,7 +134,8 @@ export class Rest extends Model {
|
|||
}
|
||||
|
||||
static getCollectionResource() {
|
||||
throw new Error("getCollectionResource() needs to be implemented");
|
||||
// Needs to be implemented!
|
||||
return "";
|
||||
}
|
||||
|
||||
static getCreateResource() {
|
||||
|
|
|
@ -132,32 +132,11 @@
|
|||
</v-btn>
|
||||
</v-img>
|
||||
|
||||
<v-card-actions primary-title class="pl-3 pr-2 pb-1" style="user-select: none;"
|
||||
@click.stop.prevent="">
|
||||
<v-edit-dialog
|
||||
:return-value.sync="album.Title"
|
||||
lazy
|
||||
@save="onSave(album)"
|
||||
class="p-inline-edit"
|
||||
>
|
||||
<span v-if="album.Title" class="body-2 ma-0">
|
||||
{{ album.Title }}
|
||||
</span>
|
||||
<span v-else>
|
||||
<v-icon>edit</v-icon>
|
||||
</span>
|
||||
<template v-slot:input>
|
||||
<v-text-field
|
||||
v-model="album.Title"
|
||||
:rules="[titleRule]"
|
||||
:label="labels.title"
|
||||
color="secondary-dark"
|
||||
class="input-title"
|
||||
single-line
|
||||
autofocus
|
||||
></v-text-field>
|
||||
</template>
|
||||
</v-edit-dialog>
|
||||
<v-card-actions primary-title class="pl-3 pr-2 pb-1" style="user-select: none;" @click.stop.prevent="">
|
||||
<h3 :title="album.Title " @click.stop.prevent="edit(album)" class="body-2 ma-0 action-title-edit"
|
||||
:data-uid="album.UID">
|
||||
{{ album.Title }}
|
||||
</h3>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
|
@ -169,8 +148,8 @@
|
|||
</v-card-actions>
|
||||
|
||||
<v-card-text class="pl-3 pr-3 pt-0 pb-3 p-album-desc" v-if="album.Description">
|
||||
<div class="caption" title="Description">
|
||||
{{ album.Description }}
|
||||
<div class="caption" title="Description" @click.stop.prevent="edit(album)">
|
||||
{{ album.Description | truncate(100) }}
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-text class="pl-3 pr-3 pt-0 pb-3 p-album-desc"
|
||||
|
@ -197,6 +176,7 @@
|
|||
@close="dialog.share = false"></p-share-dialog>
|
||||
<p-share-upload-dialog :show="dialog.upload" :selection="selection" @cancel="dialog.upload = false"
|
||||
@confirm="dialog.upload = false"></p-share-upload-dialog>
|
||||
<p-album-edit-dialog :show="dialog.edit" :album="album" @close="dialog.edit = false"></p-album-edit-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -233,8 +213,8 @@
|
|||
|
||||
let categories = [{"value": "", "text": this.$gettext("All Categories")}];
|
||||
|
||||
if (this.$config.values.albumCategories) {
|
||||
categories = categories.concat(this.$config.values.albumCategories.map(cat => {
|
||||
if (this.$config.albumCategories().length > 0) {
|
||||
categories = categories.concat(this.$config.albumCategories().map(cat => {
|
||||
return {"value": cat, "text": cat};
|
||||
}));
|
||||
}
|
||||
|
@ -270,6 +250,7 @@
|
|||
dialog: {
|
||||
share: false,
|
||||
upload: false,
|
||||
edit: false,
|
||||
},
|
||||
album: new Album(),
|
||||
};
|
||||
|
@ -279,6 +260,10 @@
|
|||
this.album = album;
|
||||
this.dialog.share = true;
|
||||
},
|
||||
edit(album) {
|
||||
this.album = album;
|
||||
this.dialog.edit = true;
|
||||
},
|
||||
webdavUpload() {
|
||||
this.dialog.share = false;
|
||||
this.dialog.upload = true;
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
</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">
|
||||
{{ album.Description }}
|
||||
{{ album.Description | truncate(100) }}
|
||||
</div>
|
||||
<div class="caption" title="Description" v-else>
|
||||
<translate>Shared with you.</translate>
|
||||
|
|
|
@ -124,7 +124,7 @@ func NewFolderAlbum(albumTitle, albumSlug, albumFilter string) *Album {
|
|||
now := Timestamp()
|
||||
|
||||
result := &Album{
|
||||
AlbumOrder: SortOrderOldest,
|
||||
AlbumOrder: SortOrderAdded,
|
||||
AlbumType: AlbumFolder,
|
||||
AlbumTitle: albumTitle,
|
||||
AlbumSlug: albumSlug,
|
||||
|
@ -166,7 +166,7 @@ func NewStateAlbum(albumTitle, albumSlug, albumFilter string) *Album {
|
|||
now := Timestamp()
|
||||
|
||||
result := &Album{
|
||||
AlbumOrder: SortOrderOldest,
|
||||
AlbumOrder: SortOrderNewest,
|
||||
AlbumType: AlbumState,
|
||||
AlbumTitle: albumTitle,
|
||||
AlbumSlug: albumSlug,
|
||||
|
|
|
@ -15,12 +15,12 @@ const (
|
|||
SrcImage = classify.SrcImage
|
||||
|
||||
// Sort orders.
|
||||
SortOrderRelevance = "relevance"
|
||||
SortOrderAdded = "added"
|
||||
SortOrderNewest = "newest"
|
||||
SortOrderOldest = "oldest"
|
||||
SortOrderImported = "imported"
|
||||
SortOrderSimilar = "similar"
|
||||
SortOrderName = "name"
|
||||
SortOrderSimilar = "similar"
|
||||
SortOrderRelevance = "relevance"
|
||||
|
||||
// Unknown values.
|
||||
YearUnknown = -1
|
||||
|
|
|
@ -317,7 +317,7 @@ func PhotoSearch(f form.PhotoSearch) (results PhotoResults, count int, err error
|
|||
s = s.Order("taken_at DESC, photos.photo_uid, files.file_primary DESC")
|
||||
case entity.SortOrderOldest:
|
||||
s = s.Order("taken_at, photos.photo_uid, files.file_primary DESC")
|
||||
case entity.SortOrderImported:
|
||||
case entity.SortOrderAdded:
|
||||
s = s.Order("photos.id DESC, files.file_primary DESC")
|
||||
case entity.SortOrderSimilar:
|
||||
s = s.Where("files.file_diff > 0")
|
||||
|
|
Loading…
Reference in a new issue