Add album edit dialog

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2020-06-30 11:27:02 +02:00
parent b01faead9c
commit 95802d9f6c
14 changed files with 212 additions and 138 deletions

View file

@ -208,6 +208,14 @@ class Config {
previewToken() {
return this.values["previewToken"];
}
albumCategories() {
if(this.values["albumCategories"]) {
return this.values["albumCategories"];
}
return [];
}
}
export default Config;

View file

@ -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"),

View file

@ -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')},

View file

@ -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);

View 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>

View file

@ -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>

View file

@ -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>

View file

@ -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')">

View file

@ -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() {

View file

@ -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;

View file

@ -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>

View file

@ -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,

View file

@ -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

View file

@ -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")