Add album form
parent
67206643b7
commit
c9a2c8a021
|
@ -37,15 +37,15 @@ trait TimelineQueryAlbums
|
||||||
);
|
);
|
||||||
|
|
||||||
// WHERE these are items with this album
|
// WHERE these are items with this album
|
||||||
$query->innerJoin('pa', 'photos_albums_files', 'paf', $query->expr()->andX(
|
$query->leftJoin('pa', 'photos_albums_files', 'paf', $query->expr()->andX(
|
||||||
$query->expr()->eq('paf.album_id', 'pa.album_id'),
|
$query->expr()->eq('paf.album_id', 'pa.album_id'),
|
||||||
));
|
));
|
||||||
|
|
||||||
// WHERE these items are memories indexed photos
|
// WHERE these items are memories indexed photos
|
||||||
$query->innerJoin('paf', 'memories', 'm', $query->expr()->eq('m.fileid', 'paf.file_id'));
|
$query->leftJoin('paf', 'memories', 'm', $query->expr()->eq('m.fileid', 'paf.file_id'));
|
||||||
|
|
||||||
// WHERE these photos are in the filecache
|
// WHERE these photos are in the filecache
|
||||||
$query->innerJoin('m', 'filecache', 'f', $query->expr()->eq('m.fileid', 'f.fileid'));
|
$query->leftJoin('m', 'filecache', 'f', $query->expr()->eq('m.fileid', 'f.fileid'));
|
||||||
|
|
||||||
// GROUP and ORDER by
|
// GROUP and ORDER by
|
||||||
$query->groupBy('pa.album_id');
|
$query->groupBy('pa.album_id');
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
<!--
|
||||||
|
- @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>
|
||||||
|
-
|
||||||
|
- @author Louis Chemineau <louis@chmn.me>
|
||||||
|
-
|
||||||
|
- @license AGPL-3.0-or-later
|
||||||
|
-
|
||||||
|
- This program is free software: you can redistribute it and/or modify
|
||||||
|
- it under the terms of the GNU Affero General Public License as
|
||||||
|
- published by the Free Software Foundation, either version 3 of the
|
||||||
|
- License, or (at your option) any later version.
|
||||||
|
-
|
||||||
|
- This program is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
- GNU Affero General Public License for more details.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the GNU Affero General Public License
|
||||||
|
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<form v-if="!showCollaboratorView" class="album-form" @submit.prevent="submit">
|
||||||
|
<div class="form-inputs">
|
||||||
|
<NcTextField ref="nameInput"
|
||||||
|
:value.sync="albumName"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
:required="true"
|
||||||
|
autofocus="true"
|
||||||
|
:placeholder="t('photos', 'Name of the album')" />
|
||||||
|
<label>
|
||||||
|
<NcTextField :value.sync="albumLocation"
|
||||||
|
name="location"
|
||||||
|
type="text"
|
||||||
|
:placeholder="t('photos', 'Location of the album')" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-buttons">
|
||||||
|
<span class="left-buttons">
|
||||||
|
<NcButton v-if="displayBackButton"
|
||||||
|
:aria-label="t('photos', 'Go back to the previous view.')"
|
||||||
|
type="tertiary"
|
||||||
|
@click="back">
|
||||||
|
{{ t('photos', 'Back') }}
|
||||||
|
</NcButton>
|
||||||
|
</span>
|
||||||
|
<span class="right-buttons">
|
||||||
|
<NcButton v-if="sharingEnabled && !editMode"
|
||||||
|
:aria-label="t('photos', 'Go to the add collaborators view.')"
|
||||||
|
type="secondary"
|
||||||
|
:disabled="albumName.trim() === '' || loading"
|
||||||
|
@click="showCollaboratorView = true">
|
||||||
|
<template #icon>
|
||||||
|
<AccountMultiplePlus />
|
||||||
|
</template>
|
||||||
|
{{ t('photos', 'Add collaborators') }}
|
||||||
|
</NcButton>
|
||||||
|
<NcButton :aria-label="editMode ? t('photos', 'Save.') : t('photos', 'Create the album.')"
|
||||||
|
type="primary"
|
||||||
|
:disabled="albumName === '' || loading"
|
||||||
|
@click="submit()">
|
||||||
|
<template #icon>
|
||||||
|
<NcLoadingIcon v-if="loading" />
|
||||||
|
<Send v-else />
|
||||||
|
</template>
|
||||||
|
{{ editMode ? t('photos', 'Save') : t('photos', 'Create album') }}
|
||||||
|
</NcButton>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<!-- <CollaboratorsSelectionForm v-else
|
||||||
|
:album-name="albumName"
|
||||||
|
:allow-public-link="false">
|
||||||
|
<template slot-scope="{collaborators}">
|
||||||
|
<span class="left-buttons">
|
||||||
|
<NcButton :aria-label="t('photos', 'Back to the new album form.')"
|
||||||
|
type="tertiary"
|
||||||
|
@click="showCollaboratorView = false">
|
||||||
|
{{ t('photos', 'Back') }}
|
||||||
|
</NcButton>
|
||||||
|
</span>
|
||||||
|
<span class="right-buttons">
|
||||||
|
<NcButton :aria-label="editMode ? t('photos', 'Save.') : t('photos', 'Create the album.')"
|
||||||
|
type="primary"
|
||||||
|
:disabled="albumName.trim() === '' || loading"
|
||||||
|
@click="submit(collaborators)">
|
||||||
|
<template #icon>
|
||||||
|
<NcLoadingIcon v-if="loading" />
|
||||||
|
<Send v-else />
|
||||||
|
</template>
|
||||||
|
{{ editMode ? t('photos', 'Save') : t('photos', 'Create album') }}
|
||||||
|
</NcButton>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</CollaboratorsSelectionForm> -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator';
|
||||||
|
import GlobalMixin from '../../mixins/GlobalMixin';
|
||||||
|
|
||||||
|
import { getCurrentUser } from '@nextcloud/auth'
|
||||||
|
import { NcButton, NcLoadingIcon, NcTextField } from '@nextcloud/vue'
|
||||||
|
import { IAlbum } from '../../types';
|
||||||
|
import moment from 'moment';
|
||||||
|
import * as dav from '../../services/DavRequests';
|
||||||
|
|
||||||
|
// import CollaboratorsSelectionForm from './CollaboratorsSelectionForm.vue'
|
||||||
|
|
||||||
|
import Send from 'vue-material-design-icons/Send.vue'
|
||||||
|
import AccountMultiplePlus from 'vue-material-design-icons/AccountMultiplePlus.vue'
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
NcButton,
|
||||||
|
NcLoadingIcon,
|
||||||
|
NcTextField,
|
||||||
|
// CollaboratorsSelectionForm,
|
||||||
|
|
||||||
|
Send,
|
||||||
|
AccountMultiplePlus,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class AlbumForm extends Mixins(GlobalMixin) {
|
||||||
|
@Prop() private album: IAlbum;
|
||||||
|
@Prop() private displayBackButton: boolean;
|
||||||
|
|
||||||
|
private showCollaboratorView = false;
|
||||||
|
private albumName = '';
|
||||||
|
private albumLocation = '';
|
||||||
|
private loading = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether sharing is enabled.
|
||||||
|
*/
|
||||||
|
get editMode(): boolean {
|
||||||
|
return Boolean(this.album);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether sharing is enabled.
|
||||||
|
*/
|
||||||
|
get sharingEnabled(): boolean {
|
||||||
|
return window.OC.Share !== undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (this.editMode) {
|
||||||
|
this.albumName = this.album.name
|
||||||
|
this.albumLocation = this.album.location
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
(<any>this.$refs.nameInput).$el.getElementsByTagName('input')[0].focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
submit(collaborators = []) {
|
||||||
|
if (this.albumName === '' || this.loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.editMode) {
|
||||||
|
this.handleUpdateAlbum()
|
||||||
|
} else {
|
||||||
|
this.handleCreateAlbum(collaborators)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleCreateAlbum(collaborators = []) {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
let album = {
|
||||||
|
basename: this.albumName,
|
||||||
|
filename: `/photos/${getCurrentUser().uid}/albums/${this.albumName}`,
|
||||||
|
nbItems: 0,
|
||||||
|
location: this.albumLocation,
|
||||||
|
lastPhoto: -1,
|
||||||
|
date: moment().format('MMMM YYYY'),
|
||||||
|
collaborators,
|
||||||
|
}
|
||||||
|
await dav.createAlbum(album.basename);
|
||||||
|
|
||||||
|
if (this.albumLocation !== '' || collaborators.length !== 0) {
|
||||||
|
album = await dav.updateAlbum(album, {
|
||||||
|
albumName: this.albumName,
|
||||||
|
properties: {
|
||||||
|
location: this.albumLocation,
|
||||||
|
collaborators,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('done', { album })
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleUpdateAlbum() {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
let album = { ...this.album }
|
||||||
|
if (this.album.name !== this.albumName) {
|
||||||
|
album = await this.renameAlbum({ currentAlbumName: this.album.name, newAlbumName: this.albumName })
|
||||||
|
}
|
||||||
|
if (this.album.location !== this.albumLocation) {
|
||||||
|
album.location = await this.updateAlbum({ albumName: this.albumName, properties: { location: this.albumLocation } })
|
||||||
|
}
|
||||||
|
this.$emit('done', { album })
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Emit('back')
|
||||||
|
back() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.album-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 350px;
|
||||||
|
padding: 16px;
|
||||||
|
.form-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.form-subtitle {
|
||||||
|
color: var(--color-text-lighter);
|
||||||
|
}
|
||||||
|
.form-inputs {
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-items: flex-end;
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 16px;
|
||||||
|
:deep svg {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.form-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.left-buttons, .right-buttons {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.right-buttons {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.left-buttons {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -56,17 +56,18 @@
|
||||||
</NcButton>
|
</NcButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <AlbumForm v-else
|
<AlbumForm v-else
|
||||||
:display-back-button="true"
|
:display-back-button="true"
|
||||||
:title="t('photos', 'New album')"
|
:title="t('photos', 'New album')"
|
||||||
@back="showAlbumCreationForm = false"
|
@back="showAlbumCreationForm = false"
|
||||||
@done="albumCreatedHandler" /> -->
|
@done="albumCreatedHandler" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Emit, Mixins } from 'vue-property-decorator';
|
import { Component, Emit, Mixins } from 'vue-property-decorator';
|
||||||
import GlobalMixin from '../../mixins/GlobalMixin';
|
import GlobalMixin from '../../mixins/GlobalMixin';
|
||||||
|
|
||||||
|
import AlbumForm from './AlbumForm.vue'
|
||||||
import Plus from 'vue-material-design-icons/Plus.vue'
|
import Plus from 'vue-material-design-icons/Plus.vue'
|
||||||
import ImageMultiple from 'vue-material-design-icons/ImageMultiple.vue'
|
import ImageMultiple from 'vue-material-design-icons/ImageMultiple.vue'
|
||||||
|
|
||||||
|
@ -75,16 +76,14 @@ import { generateUrl } from '@nextcloud/router'
|
||||||
import { IAlbum } from '../../types';
|
import { IAlbum } from '../../types';
|
||||||
import axios from '@nextcloud/axios'
|
import axios from '@nextcloud/axios'
|
||||||
|
|
||||||
// import AlbumForm from './AlbumForm.vue'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
AlbumForm,
|
||||||
Plus,
|
Plus,
|
||||||
ImageMultiple,
|
ImageMultiple,
|
||||||
NcButton,
|
NcButton,
|
||||||
NcListItem,
|
NcListItem,
|
||||||
NcLoadingIcon,
|
NcLoadingIcon,
|
||||||
// AlbumForm,
|
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
toCoverUrl(fileId: string) {
|
toCoverUrl(fileId: string) {
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator';
|
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator';
|
||||||
|
import GlobalMixin from '../../mixins/GlobalMixin';
|
||||||
|
|
||||||
import { NcButton, NcTextField } from '@nextcloud/vue';
|
import { NcButton, NcTextField } from '@nextcloud/vue';
|
||||||
import { showError } from '@nextcloud/dialogs';
|
import { showError } from '@nextcloud/dialogs';
|
||||||
import { getCurrentUser } from '@nextcloud/auth';
|
import { getCurrentUser } from '@nextcloud/auth';
|
||||||
|
@ -26,7 +28,6 @@ import Tag from '../frame/Tag.vue';
|
||||||
import FaceList from './FaceList.vue';
|
import FaceList from './FaceList.vue';
|
||||||
|
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import GlobalMixin from '../../mixins/GlobalMixin';
|
|
||||||
import client from '../../services/DavClient';
|
import client from '../../services/DavClient';
|
||||||
import * as dav from '../../services/DavRequests';
|
import * as dav from '../../services/DavRequests';
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="name" class="face-top-matter">
|
||||||
|
<NcActions>
|
||||||
|
<NcActionButton :aria-label="t('memories', 'Back')" @click="back()">
|
||||||
|
{{ t('memories', 'Back') }}
|
||||||
|
<template #icon> <BackIcon :size="20" /> </template>
|
||||||
|
</NcActionButton>
|
||||||
|
</NcActions>
|
||||||
|
|
||||||
|
<div class="name">{{ name }}</div>
|
||||||
|
|
||||||
|
<div class="right-actions">
|
||||||
|
<NcActions :inline="1">
|
||||||
|
<NcActionButton :aria-label="t('memories', 'Rename person')" @click="$refs.editModal.open()" close-after-click>
|
||||||
|
{{ t('memories', 'Rename person') }}
|
||||||
|
<template #icon> <EditIcon :size="20" /> </template>
|
||||||
|
</NcActionButton>
|
||||||
|
<NcActionButton :aria-label="t('memories', 'Merge with different person')" @click="$refs.mergeModal.open()" close-after-click>
|
||||||
|
{{ t('memories', 'Merge with different person') }}
|
||||||
|
<template #icon> <MergeIcon :size="20" /> </template>
|
||||||
|
</NcActionButton>
|
||||||
|
<NcActionCheckbox :aria-label="t('memories', 'Mark person in preview')" :checked.sync="config_showFaceRect" @change="changeShowFaceRect">
|
||||||
|
{{ t('memories', 'Mark person in preview') }}
|
||||||
|
</NcActionCheckbox>
|
||||||
|
<NcActionButton :aria-label="t('memories', 'Remove person')" @click="$refs.deleteModal.open()" close-after-click>
|
||||||
|
{{ t('memories', 'Remove person') }}
|
||||||
|
<template #icon> <DeleteIcon :size="20" /> </template>
|
||||||
|
</NcActionButton>
|
||||||
|
</NcActions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FaceEditModal ref="editModal" />
|
||||||
|
<FaceDeleteModal ref="deleteModal" />
|
||||||
|
<FaceMergeModal ref="mergeModal" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Mixins, Watch } from 'vue-property-decorator';
|
||||||
|
import GlobalMixin from '../../mixins/GlobalMixin';
|
||||||
|
import UserConfig from "../../mixins/UserConfig";
|
||||||
|
|
||||||
|
import { NcActions, NcActionButton, NcActionCheckbox } from '@nextcloud/vue';
|
||||||
|
import FaceEditModal from '../modal/FaceEditModal.vue';
|
||||||
|
import FaceDeleteModal from '../modal/FaceDeleteModal.vue';
|
||||||
|
import FaceMergeModal from '../modal/FaceMergeModal.vue';
|
||||||
|
import BackIcon from 'vue-material-design-icons/ArrowLeft.vue';
|
||||||
|
import EditIcon from 'vue-material-design-icons/Pencil.vue';
|
||||||
|
import DeleteIcon from 'vue-material-design-icons/Close.vue';
|
||||||
|
import MergeIcon from 'vue-material-design-icons/Merge.vue';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
NcActions,
|
||||||
|
NcActionButton,
|
||||||
|
NcActionCheckbox,
|
||||||
|
FaceEditModal,
|
||||||
|
FaceDeleteModal,
|
||||||
|
FaceMergeModal,
|
||||||
|
BackIcon,
|
||||||
|
EditIcon,
|
||||||
|
DeleteIcon,
|
||||||
|
MergeIcon,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class FaceTopMatter extends Mixins(GlobalMixin, UserConfig) {
|
||||||
|
private name: string = '';
|
||||||
|
|
||||||
|
@Watch('$route')
|
||||||
|
async routeChange(from: any, to: any) {
|
||||||
|
this.createMatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.createMatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
createMatter() {
|
||||||
|
this.name = this.$route.params.name || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
back() {
|
||||||
|
this.$router.push({ name: 'people' });
|
||||||
|
}
|
||||||
|
|
||||||
|
changeShowFaceRect() {
|
||||||
|
localStorage.setItem('memories_showFaceRect', this.config_showFaceRect ? '1' : '0');
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$router.go(0); // refresh page
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.face-top-matter {
|
||||||
|
display: flex;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 40px;
|
||||||
|
padding-left: 3px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-actions {
|
||||||
|
margin-right: 40px;
|
||||||
|
z-index: 50;
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -655,3 +655,65 @@ export async function* removeFromAlbum(id: number, fileIds: number[]) {
|
||||||
|
|
||||||
yield* runInParallel(calls, 10);
|
yield* runInParallel(calls, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an album.
|
||||||
|
*/
|
||||||
|
export async function createAlbum(albumName: string) {
|
||||||
|
try {
|
||||||
|
await client.createDirectory(`/photos/${getCurrentUser()?.uid}/albums/${albumName}`)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
showError(t('photos', 'Failed to create {albumName}.', { albumName }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an album's properties.
|
||||||
|
*
|
||||||
|
* @param {object} album Album to update
|
||||||
|
* @param {object} data destructuring object
|
||||||
|
* @param {string} data.albumName - The name of the album.
|
||||||
|
* @param {object} data.properties - The properties to update.
|
||||||
|
*/
|
||||||
|
export async function updateAlbum(album: any, { albumName, properties }: any) {
|
||||||
|
const stringifiedProperties = Object
|
||||||
|
.entries(properties)
|
||||||
|
.map(([name, value]) => {
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'string':
|
||||||
|
return `<nc:${name}>${value}</nc:${name}>`
|
||||||
|
case 'object':
|
||||||
|
return `<nc:${name}>${JSON.stringify(value)}</nc:${name}>`
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join()
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.customRequest(
|
||||||
|
album.filename,
|
||||||
|
{
|
||||||
|
method: 'PROPPATCH',
|
||||||
|
data: `<?xml version="1.0"?>
|
||||||
|
<d:propertyupdate xmlns:d="DAV:"
|
||||||
|
xmlns:oc="http://owncloud.org/ns"
|
||||||
|
xmlns:nc="http://nextcloud.org/ns"
|
||||||
|
xmlns:ocs="http://open-collaboration-services.org/ns">
|
||||||
|
<d:set>
|
||||||
|
<d:prop>
|
||||||
|
${stringifiedProperties}
|
||||||
|
</d:prop>
|
||||||
|
</d:set>
|
||||||
|
</d:propertyupdate>`,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return album;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
showError(t('photos', 'Failed to update properties of {albumName} with {properties}.', { albumName, properties: JSON.stringify(properties) }))
|
||||||
|
return album
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue