mirror of
https://github.com/photoprism/photoprism.git
synced 2025-10-18 22:54:52 +08:00
WebDAV: Fix upload of complete albums #1376
This commit is contained in:
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
108
frontend/src/common/selection.js
Normal file
108
frontend/src/common/selection.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2018 - 2022 Michael Mayer <hello@photoprism.app>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under Version 3 of the GNU Affero General Public License (the "AGPL"):
|
||||||
|
<https://docs.photoprism.app/license/agpl>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The AGPL is supplemented by our Trademark and Brand Guidelines,
|
||||||
|
which describe how our Brand Assets may be used:
|
||||||
|
<https://photoprism.app/trademark>
|
||||||
|
|
||||||
|
Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
||||||
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
|
Additional information can be found in our Developer Guide:
|
||||||
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isObject(val) {
|
||||||
|
return val && val instanceof Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isModel(model) {
|
||||||
|
return (
|
||||||
|
model &&
|
||||||
|
typeof model.getId === "function" &&
|
||||||
|
typeof model.constructor.getCollectionResource === "function"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Selection {
|
||||||
|
/**
|
||||||
|
* @param {Object?} items
|
||||||
|
*/
|
||||||
|
constructor(items) {
|
||||||
|
this.clear();
|
||||||
|
this.addItems(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.files = [];
|
||||||
|
this.photos = [];
|
||||||
|
this.albums = [];
|
||||||
|
this.labels = [];
|
||||||
|
this.places = [];
|
||||||
|
this.subjects = [];
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} items
|
||||||
|
*/
|
||||||
|
addItems(items) {
|
||||||
|
if (isObject(items) && Object.keys(items).length > 0) {
|
||||||
|
for (const [key, value] of Object.entries(items)) {
|
||||||
|
if (this.hasOwnProperty(key) && Array.isArray(value) && value.length > 0) {
|
||||||
|
if (this[key].length === 0 || this[key][0] !== value[0]) {
|
||||||
|
this[key].push(...value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addModel(model) {
|
||||||
|
if (!isModel(model)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = model.getId();
|
||||||
|
const key = model.constructor.getCollectionResource();
|
||||||
|
|
||||||
|
if (!id || !key || !this.hasOwnProperty(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this[key].includes(id)) {
|
||||||
|
this[key].push(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isEmpty() {
|
||||||
|
for (const items of Object.values(this)) {
|
||||||
|
if (Array.isArray(items) && items.length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Selection;
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -100,7 +100,10 @@ import download from "common/download";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PAlbumClipboard',
|
name: 'PAlbumClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
clearSelection: Function,
|
clearSelection: Function,
|
||||||
share: Function,
|
share: Function,
|
||||||
|
@@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
<p-share-dialog :show="dialog.share" :model="album" @upload="webdavUpload"
|
<p-share-dialog :show="dialog.share" :model="album" @upload="webdavUpload"
|
||||||
@close="dialog.share = false"></p-share-dialog>
|
@close="dialog.share = false"></p-share-dialog>
|
||||||
<p-share-upload-dialog :show="dialog.upload" :selection="[album.getId()]" @cancel="dialog.upload = false"
|
<p-share-upload-dialog :show="dialog.upload" :items="{albums: album.getId()}" :model="album" @cancel="dialog.upload = false"
|
||||||
@confirm="dialog.upload = false"></p-share-upload-dialog>
|
@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>
|
<p-album-edit-dialog :show="dialog.edit" :album="album" @close="dialog.edit = false"></p-album-edit-dialog>
|
||||||
</v-form>
|
</v-form>
|
||||||
@@ -75,9 +75,18 @@ import download from "common/download";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PAlbumToolbar',
|
name: 'PAlbumToolbar',
|
||||||
props: {
|
props: {
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
settings: Object,
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
filterChange: Function,
|
filterChange: Function,
|
||||||
},
|
},
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -69,7 +69,10 @@ import download from "common/download";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PFileClipboard',
|
name: 'PFileClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
clearSelection: Function,
|
clearSelection: Function,
|
||||||
},
|
},
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -81,7 +81,10 @@ import download from "common/download";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PLabelClipboard',
|
name: 'PLabelClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
clearSelection: Function,
|
clearSelection: Function,
|
||||||
},
|
},
|
||||||
|
@@ -195,12 +195,21 @@ import {Input, InputInvalid, ClickShort, ClickLong} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoCards',
|
name: 'PPhotoCards',
|
||||||
props: {
|
props: {
|
||||||
photos: Array,
|
photos: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
openPhoto: Function,
|
openPhoto: Function,
|
||||||
editPhoto: Function,
|
editPhoto: Function,
|
||||||
openLocation: Function,
|
openLocation: Function,
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
selectMode: Boolean,
|
selectMode: Boolean,
|
||||||
},
|
},
|
||||||
|
@@ -148,7 +148,7 @@
|
|||||||
@confirm="batchDelete"></p-photo-delete-dialog>
|
@confirm="batchDelete"></p-photo-delete-dialog>
|
||||||
<p-photo-album-dialog :show="dialog.album" @cancel="dialog.album = false"
|
<p-photo-album-dialog :show="dialog.album" @cancel="dialog.album = false"
|
||||||
@confirm="addToAlbum"></p-photo-album-dialog>
|
@confirm="addToAlbum"></p-photo-album-dialog>
|
||||||
<p-share-upload-dialog :show="dialog.share" :selection="selection" :album="album" @cancel="dialog.share = false"
|
<p-share-upload-dialog :show="dialog.share" :items="{photos: selection}" :model="album" @cancel="dialog.share = false"
|
||||||
@confirm="onShared"></p-share-upload-dialog>
|
@confirm="onShared"></p-share-upload-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -162,9 +162,15 @@ import Photo from "model/photo";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoClipboard',
|
name: 'PPhotoClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
album: Object,
|
album: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -117,12 +117,21 @@ import Notify from "common/notify";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoList',
|
name: 'PPhotoList',
|
||||||
props: {
|
props: {
|
||||||
photos: Array,
|
photos: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
openPhoto: Function,
|
openPhoto: Function,
|
||||||
editPhoto: Function,
|
editPhoto: Function,
|
||||||
openLocation: Function,
|
openLocation: Function,
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
selectMode: Boolean,
|
selectMode: Boolean,
|
||||||
},
|
},
|
||||||
|
@@ -121,11 +121,20 @@ import {Input, InputInvalid, ClickShort, ClickLong} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoMosaic',
|
name: 'PPhotoMosaic',
|
||||||
props: {
|
props: {
|
||||||
photos: Array,
|
photos: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
openPhoto: Function,
|
openPhoto: Function,
|
||||||
editPhoto: Function,
|
editPhoto: Function,
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
selectMode: Boolean,
|
selectMode: Boolean,
|
||||||
},
|
},
|
||||||
|
@@ -156,8 +156,14 @@ export default {
|
|||||||
name: 'PPhotoToolbar',
|
name: 'PPhotoToolbar',
|
||||||
props: {
|
props: {
|
||||||
dirty: Boolean,
|
dirty: Boolean,
|
||||||
filter: Object,
|
filter: {
|
||||||
settings: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
filterChange: Function,
|
filterChange: Function,
|
||||||
},
|
},
|
||||||
|
@@ -177,7 +177,7 @@ export default {
|
|||||||
},
|
},
|
||||||
openPlayer(video) {
|
openPlayer(video) {
|
||||||
if (!video) {
|
if (!video) {
|
||||||
this.$notify.error("no video selected");
|
this.$notify.error(this.$gettext("No video selected"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -69,7 +69,10 @@ import download from "common/download";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PSubjectClipboard',
|
name: 'PSubjectClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
clearSelection: Function,
|
clearSelection: Function,
|
||||||
},
|
},
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -274,7 +274,11 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
scope: String,
|
scope: String,
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const thumbs = this.$config.values.thumbs;
|
const thumbs = this.$config.values.thumbs;
|
||||||
@@ -366,7 +370,7 @@ export default {
|
|||||||
},
|
},
|
||||||
sizes(thumbs) {
|
sizes(thumbs) {
|
||||||
const result = [
|
const result = [
|
||||||
{"text": this.$gettext("Original"), "value": ""}
|
{"text": this.$gettext("Originals"), "value": ""},
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i = 0; i < thumbs.length; i++) {
|
for (let i = 0; i < thumbs.length; i++) {
|
||||||
|
@@ -30,7 +30,10 @@ export default {
|
|||||||
name: 'PAccountDeleteDialog',
|
name: 'PAccountDeleteDialog',
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@@ -100,7 +100,10 @@ export default {
|
|||||||
name: 'PAlbumEditDialog',
|
name: 'PAlbumEditDialog',
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
album: Object,
|
album: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -128,8 +128,14 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
index: Number,
|
index: Number,
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
selection: Array,
|
selection: {
|
||||||
album: Object,
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
album: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -217,7 +223,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.selection || !this.selection[index]) {
|
if (!this.selection || !this.selection[index]) {
|
||||||
this.$notify.error("Invalid photo selected");
|
this.$notify.error(this.$gettext("Invalid photo selected"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -231,7 +231,10 @@ import Util from "common/util";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PTabPhotoFiles',
|
name: 'PTabPhotoFiles',
|
||||||
props: {
|
props: {
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
uid: String,
|
uid: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -268,7 +268,10 @@ import * as options from "options/options";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PTabPhotoAdvanced',
|
name: 'PTabPhotoAdvanced',
|
||||||
props: {
|
props: {
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
uid: String,
|
uid: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -92,7 +92,10 @@ import Label from "model/label";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PTabPhotoLabels',
|
name: 'PTabPhotoLabels',
|
||||||
props: {
|
props: {
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
uid: String,
|
uid: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -108,7 +108,10 @@
|
|||||||
export default {
|
export default {
|
||||||
name: 'PTabPhotoPeople',
|
name: 'PTabPhotoPeople',
|
||||||
props: {
|
props: {
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
uid: String,
|
uid: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog v-model="show" lazy persistent max-width="500" class="p-share-dialog" @keydown.esc="close">
|
<v-dialog :value="show" lazy persistent max-width="500" class="p-share-dialog" @keydown.esc="close">
|
||||||
<v-card raised elevation="24">
|
<v-card raised elevation="24">
|
||||||
<v-card-title primary-title class="pb-0">
|
<v-card-title primary-title class="pb-0">
|
||||||
<v-layout row wrap>
|
<v-layout row wrap>
|
||||||
@@ -134,7 +134,10 @@ export default {
|
|||||||
name: 'PShareDialog',
|
name: 'PShareDialog',
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
model: Object,
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -181,9 +184,9 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const url = link.url();
|
const url = link.url();
|
||||||
await Util.copyToMachineClipboard(url);
|
await Util.copyToMachineClipboard(url);
|
||||||
this.$notify.success(this.$gettext("Copied to clipboard"))
|
this.$notify.success(this.$gettext("Copied to clipboard"));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$notify.error(this.$gettext("Failed copying to clipboard"))
|
this.$notify.error(this.$gettext("Failed copying to clipboard"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
expires(link) {
|
expires(link) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog v-model="show" lazy persistent max-width="400" class="p-share-upload-dialog" @keydown.esc="cancel">
|
<v-dialog :value="show" lazy persistent max-width="400" class="p-share-upload-dialog" @keydown.esc="cancel">
|
||||||
<v-card raised elevation="24">
|
<v-card raised elevation="24">
|
||||||
<v-card-title primary-title class="pb-0">
|
<v-card-title primary-title class="pb-0">
|
||||||
<v-layout row wrap>
|
<v-layout row wrap>
|
||||||
@@ -68,12 +68,20 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Account from "model/account";
|
import Account from "model/account";
|
||||||
|
import Selection from "common/selection";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PShareUploadDialog',
|
name: 'PShareUploadDialog',
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
selection: Array,
|
items: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -82,6 +90,7 @@ export default {
|
|||||||
search: null,
|
search: null,
|
||||||
account: {},
|
account: {},
|
||||||
accounts: [],
|
accounts: [],
|
||||||
|
selection: new Selection({}),
|
||||||
path: "/",
|
path: "/",
|
||||||
paths: [
|
paths: [
|
||||||
{"abs": "/"}
|
{"abs": "/"}
|
||||||
@@ -107,6 +116,8 @@ export default {
|
|||||||
show: function (show) {
|
show: function (show) {
|
||||||
if (show) {
|
if (show) {
|
||||||
this.load();
|
this.load();
|
||||||
|
} else if (this.selection) {
|
||||||
|
this.selection.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -129,7 +140,7 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
if (files.length === 1) {
|
if (files.length === 1) {
|
||||||
this.$notify.success("One file uploaded");
|
this.$notify.success(this.$gettext("One file uploaded"));
|
||||||
} else {
|
} else {
|
||||||
this.$notify.success(this.$gettextInterpolate(this.$gettext("%{n} files uploaded"), {n: files.length}));
|
this.$notify.success(this.$gettextInterpolate(this.$gettext("%{n} files uploaded"), {n: files.length}));
|
||||||
}
|
}
|
||||||
@@ -154,6 +165,18 @@ export default {
|
|||||||
load() {
|
load() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
|
this.selection.clear().addItems(this.items);
|
||||||
|
|
||||||
|
if (this.selection.isEmpty()) {
|
||||||
|
this.selection.addModel(this.model);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selection.isEmpty()) {
|
||||||
|
this.loading = false;
|
||||||
|
this.$emit('cancel');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
share: true,
|
share: true,
|
||||||
count: 1000,
|
count: 1000,
|
||||||
|
@@ -59,7 +59,7 @@ export default {
|
|||||||
},
|
},
|
||||||
play(fullscreen) {
|
play(fullscreen) {
|
||||||
if (!this.video) {
|
if (!this.video) {
|
||||||
this.$notify.error("no video selected");
|
this.$notify.error(this.$gettext("No video selected"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -75,10 +75,16 @@ export class Account extends RestModel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Share(photos, dest) {
|
Share(selection, folder) {
|
||||||
const values = { Photos: photos, Destination: dest };
|
if (!selection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return Api.post(this.getEntityResource() + "/share", values).then((response) =>
|
if (Array.isArray(selection)) {
|
||||||
|
selection = { Photos: selection };
|
||||||
|
}
|
||||||
|
|
||||||
|
return Api.post(this.getEntityResource() + "/share", { selection, folder }).then((response) =>
|
||||||
Promise.resolve(response.data)
|
Promise.resolve(response.data)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -198,7 +198,7 @@
|
|||||||
</v-container>
|
</v-container>
|
||||||
<p-share-dialog :show="dialog.share" :model="model" @upload="webdavUpload"
|
<p-share-dialog :show="dialog.share" :model="model" @upload="webdavUpload"
|
||||||
@close="dialog.share = false"></p-share-dialog>
|
@close="dialog.share = false"></p-share-dialog>
|
||||||
<p-share-upload-dialog :show="dialog.upload" :selection="selection" @cancel="dialog.upload = false"
|
<p-share-upload-dialog :show="dialog.upload" :items="{albums: selection}" :model="model" @cancel="dialog.upload = false"
|
||||||
@confirm="dialog.upload = false"></p-share-upload-dialog>
|
@confirm="dialog.upload = false"></p-share-upload-dialog>
|
||||||
<p-album-edit-dialog :show="dialog.edit" :album="model" @close="dialog.edit = false"></p-album-edit-dialog>
|
<p-album-edit-dialog :show="dialog.edit" :album="model" @close="dialog.edit = false"></p-album-edit-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -135,7 +135,10 @@ import {ClickLong, ClickShort, Input, InputInvalid} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPageFaces',
|
name: 'PPageFaces',
|
||||||
props: {
|
props: {
|
||||||
staticFilter: Object,
|
staticFilter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -180,7 +180,10 @@ import {ClickLong, ClickShort, Input, InputInvalid} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPageSubjects',
|
name: 'PPageSubjects',
|
||||||
props: {
|
props: {
|
||||||
staticFilter: Object,
|
staticFilter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -51,7 +51,10 @@ import download from "common/download";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PAlbumClipboard',
|
name: 'PAlbumClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
clearSelection: Function,
|
clearSelection: Function,
|
||||||
context: String,
|
context: String,
|
||||||
|
@@ -118,7 +118,10 @@ import {Input, InputInvalid, ClickShort, ClickLong} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPageAlbums',
|
name: 'PPageAlbums',
|
||||||
props: {
|
props: {
|
||||||
staticFilter: Object,
|
staticFilter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
view: String,
|
view: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -146,12 +146,21 @@ import {Input, InputInvalid, ClickShort, ClickLong} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoCards',
|
name: 'PPhotoCards',
|
||||||
props: {
|
props: {
|
||||||
photos: Array,
|
photos: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
openPhoto: Function,
|
openPhoto: Function,
|
||||||
editPhoto: Function,
|
editPhoto: Function,
|
||||||
openLocation: Function,
|
openLocation: Function,
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
selectMode: Boolean,
|
selectMode: Boolean,
|
||||||
},
|
},
|
||||||
|
@@ -54,9 +54,15 @@ import Photo from "model/photo";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoClipboard',
|
name: 'PPhotoClipboard',
|
||||||
props: {
|
props: {
|
||||||
selection: Array,
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
refresh: Function,
|
refresh: Function,
|
||||||
album: Object,
|
album: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@@ -97,12 +97,21 @@ import Notify from "common/notify";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoList',
|
name: 'PPhotoList',
|
||||||
props: {
|
props: {
|
||||||
photos: Array,
|
photos: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
openPhoto: Function,
|
openPhoto: Function,
|
||||||
editPhoto: Function,
|
editPhoto: Function,
|
||||||
openLocation: Function,
|
openLocation: Function,
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
selectMode: Boolean,
|
selectMode: Boolean,
|
||||||
},
|
},
|
||||||
|
@@ -100,11 +100,20 @@ import {Input, InputInvalid, ClickShort, ClickLong} from "common/input";
|
|||||||
export default {
|
export default {
|
||||||
name: 'PPhotoMosaic',
|
name: 'PPhotoMosaic',
|
||||||
props: {
|
props: {
|
||||||
photos: Array,
|
photos: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
openPhoto: Function,
|
openPhoto: Function,
|
||||||
editPhoto: Function,
|
editPhoto: Function,
|
||||||
album: Object,
|
album: {
|
||||||
filter: Object,
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
context: String,
|
context: String,
|
||||||
selectMode: Boolean,
|
selectMode: Boolean,
|
||||||
},
|
},
|
||||||
|
@@ -19,7 +19,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package acl
|
package acl
|
||||||
|
@@ -117,6 +117,8 @@ func GetAccountFolders(router *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShareWithAccount uploads files to the selected account.
|
||||||
|
//
|
||||||
// GET /api/v1/accounts/:id/share
|
// GET /api/v1/accounts/:id/share
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
@@ -146,8 +148,15 @@ func ShareWithAccount(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := f.Destination
|
folder := f.Folder
|
||||||
files, err := query.FilesByUID(f.Photos, 1000, 0)
|
|
||||||
|
// Select files to be shared.
|
||||||
|
o := query.FileSelection{
|
||||||
|
Video: true,
|
||||||
|
OriginalsOnly: m.ShareOriginals(),
|
||||||
|
PrimaryOnly: !m.ShareOriginals(),
|
||||||
|
}
|
||||||
|
files, err := query.SelectedFiles(f.Selection, o)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
AbortEntityNotFound(c)
|
AbortEntityNotFound(c)
|
||||||
@@ -157,7 +166,7 @@ func ShareWithAccount(router *gin.RouterGroup) {
|
|||||||
var aliases = make(map[string]int)
|
var aliases = make(map[string]int)
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
alias := path.Join(dst, file.ShareBase(0))
|
alias := path.Join(folder, file.ShareBase(0))
|
||||||
key := strings.ToLower(alias)
|
key := strings.ToLower(alias)
|
||||||
|
|
||||||
if seq := aliases[key]; seq > 0 {
|
if seq := aliases[key]; seq > 0 {
|
||||||
@@ -175,6 +184,8 @@ func ShareWithAccount(router *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateAccount creates a new remote account configuration.
|
||||||
|
//
|
||||||
// POST /api/v1/accounts
|
// POST /api/v1/accounts
|
||||||
func CreateAccount(router *gin.RouterGroup) {
|
func CreateAccount(router *gin.RouterGroup) {
|
||||||
router.POST("/accounts", func(c *gin.Context) {
|
router.POST("/accounts", func(c *gin.Context) {
|
||||||
@@ -219,6 +230,8 @@ func CreateAccount(router *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateAccount updates a remote account configuration.
|
||||||
|
//
|
||||||
// PUT /api/v1/accounts/:id
|
// PUT /api/v1/accounts/:id
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
@@ -288,6 +301,8 @@ func UpdateAccount(router *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteAccount removes a remote account configuration.
|
||||||
|
//
|
||||||
// DELETE /api/v1/accounts/:id
|
// DELETE /api/v1/accounts/:id
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
|
@@ -365,7 +365,8 @@ func AddPhotosToAlbum(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
photos, err := query.PhotoSelection(f)
|
// Fetch selection from index.
|
||||||
|
photos, err := query.SelectedPhotos(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("album: %s", err)
|
log.Errorf("album: %s", err)
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package api
|
package api
|
||||||
|
@@ -44,7 +44,8 @@ func BatchPhotosArchive(router *gin.RouterGroup) {
|
|||||||
log.Infof("photos: archiving %s", sanitize.Log(f.String()))
|
log.Infof("photos: archiving %s", sanitize.Log(f.String()))
|
||||||
|
|
||||||
if service.Config().BackupYaml() {
|
if service.Config().BackupYaml() {
|
||||||
photos, err := query.PhotoSelection(f)
|
// Fetch selection from index.
|
||||||
|
photos, err := query.SelectedPhotos(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
AbortEntityNotFound(c)
|
AbortEntityNotFound(c)
|
||||||
@@ -107,7 +108,8 @@ func BatchPhotosRestore(router *gin.RouterGroup) {
|
|||||||
log.Infof("photos: restoring %s", sanitize.Log(f.String()))
|
log.Infof("photos: restoring %s", sanitize.Log(f.String()))
|
||||||
|
|
||||||
if service.Config().BackupYaml() {
|
if service.Config().BackupYaml() {
|
||||||
photos, err := query.PhotoSelection(f)
|
// Fetch selection from index.
|
||||||
|
photos, err := query.SelectedPhotos(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
AbortEntityNotFound(c)
|
AbortEntityNotFound(c)
|
||||||
@@ -168,7 +170,8 @@ func BatchPhotosApprove(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
log.Infof("photos: approving %s", sanitize.Log(f.String()))
|
log.Infof("photos: approving %s", sanitize.Log(f.String()))
|
||||||
|
|
||||||
photos, err := query.PhotoSelection(f)
|
// Fetch selection from index.
|
||||||
|
photos, err := query.SelectedPhotos(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
AbortEntityNotFound(c)
|
AbortEntityNotFound(c)
|
||||||
@@ -267,7 +270,8 @@ func BatchPhotosPrivate(router *gin.RouterGroup) {
|
|||||||
// Update precalculated photo and file counts.
|
// Update precalculated photo and file counts.
|
||||||
logWarn("index", entity.UpdateCounts())
|
logWarn("index", entity.UpdateCounts())
|
||||||
|
|
||||||
if photos, err := query.PhotoSelection(f); err == nil {
|
// Fetch selection from index.
|
||||||
|
if photos, err := query.SelectedPhotos(f); err == nil {
|
||||||
for _, p := range photos {
|
for _, p := range photos {
|
||||||
SavePhotoAsYaml(p)
|
SavePhotoAsYaml(p)
|
||||||
}
|
}
|
||||||
@@ -362,7 +366,8 @@ func BatchPhotosDelete(router *gin.RouterGroup) {
|
|||||||
|
|
||||||
log.Infof("photos: deleting %s", sanitize.Log(f.String()))
|
log.Infof("photos: deleting %s", sanitize.Log(f.String()))
|
||||||
|
|
||||||
photos, err := query.PhotoSelection(f)
|
// Fetch selection from index.
|
||||||
|
photos, err := query.SelectedPhotos(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
AbortEntityNotFound(c)
|
AbortEntityNotFound(c)
|
||||||
|
@@ -19,7 +19,7 @@ import (
|
|||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// hash: string The photo or video file hash as returned by the search API
|
// hash: string The photo or video file hash as returned by the search API
|
||||||
// type: string Video type
|
// type: string Video format
|
||||||
func GetVideo(router *gin.RouterGroup) {
|
func GetVideo(router *gin.RouterGroup) {
|
||||||
router.GET("/videos/:hash/:token/:type", func(c *gin.Context) {
|
router.GET("/videos/:hash/:token/:type", func(c *gin.Context) {
|
||||||
if InvalidPreviewToken(c) {
|
if InvalidPreviewToken(c) {
|
||||||
|
@@ -25,6 +25,8 @@ import (
|
|||||||
"github.com/photoprism/photoprism/pkg/sanitize"
|
"github.com/photoprism/photoprism/pkg/sanitize"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CreateZip creates a zip file archive for download.
|
||||||
|
//
|
||||||
// POST /api/v1/zip
|
// POST /api/v1/zip
|
||||||
func CreateZip(router *gin.RouterGroup) {
|
func CreateZip(router *gin.RouterGroup) {
|
||||||
router.POST("/zip", func(c *gin.Context) {
|
router.POST("/zip", func(c *gin.Context) {
|
||||||
@@ -55,7 +57,8 @@ func CreateZip(router *gin.RouterGroup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := query.FileSelection(f)
|
// Select files to be downloaded.
|
||||||
|
files, err := query.SelectedFiles(f, query.FileSelectionAll())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error(c, http.StatusBadRequest, err, i18n.ErrZipFailed)
|
Error(c, http.StatusBadRequest, err, i18n.ErrZipFailed)
|
||||||
@@ -132,6 +135,8 @@ func CreateZip(router *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownloadZip downloads a zip file archive.
|
||||||
|
//
|
||||||
// GET /api/v1/zip/:filename
|
// GET /api/v1/zip/:filename
|
||||||
func DownloadZip(router *gin.RouterGroup) {
|
func DownloadZip(router *gin.RouterGroup) {
|
||||||
router.GET("/zip/:filename", func(c *gin.Context) {
|
router.GET("/zip/:filename", func(c *gin.Context) {
|
||||||
@@ -159,6 +164,7 @@ func DownloadZip(router *gin.RouterGroup) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addFileToZip adds a file to a zip archive.
|
||||||
func addFileToZip(zipWriter *zip.Writer, fileName, fileAlias string) error {
|
func addFileToZip(zipWriter *zip.Writer, fileName, fileAlias string) error {
|
||||||
fileToZip, err := os.Open(fileName)
|
fileToZip, err := os.Open(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package auto
|
package auto
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package classify
|
package classify
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package config
|
package config
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package crop
|
package crop
|
||||||
|
@@ -137,3 +137,8 @@ func (m *Account) Save() error {
|
|||||||
func (m *Account) Create() error {
|
func (m *Account) Create() error {
|
||||||
return Db().Create(m).Error
|
return Db().Create(m).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShareOriginals tests if the unmodified originals should be shared.
|
||||||
|
func (m *Account) ShareOriginals() bool {
|
||||||
|
return m.ShareSize == ""
|
||||||
|
}
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package face
|
package face
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
package form
|
package form
|
||||||
|
|
||||||
type AccountShare struct {
|
type AccountShare struct {
|
||||||
Photos []string `json:"photos"`
|
Selection Selection `json:"selection"`
|
||||||
Destination string `json:"destination"`
|
Folder string `json:"folder"`
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package form
|
package form
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package hub
|
package hub
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package places
|
package places
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package i18n
|
package i18n
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package maps
|
package maps
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package meta
|
package meta
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package migrate
|
package migrate
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package nsfw
|
package nsfw
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package photoprism
|
package photoprism
|
||||||
|
105
internal/query/file_selection.go
Normal file
105
internal/query/file_selection.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
|
"github.com/photoprism/photoprism/internal/form"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileSelection represents a selection filter to include/exclude certain files.
|
||||||
|
type FileSelection struct {
|
||||||
|
Video bool
|
||||||
|
Sidecar bool
|
||||||
|
PrimaryOnly bool
|
||||||
|
OriginalsOnly bool
|
||||||
|
SizeLimit int
|
||||||
|
Include []string
|
||||||
|
Exclude []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileSelectionAll returns options that include videos and sidecar files.
|
||||||
|
func FileSelectionAll() FileSelection {
|
||||||
|
return FileSelection{
|
||||||
|
Video: true,
|
||||||
|
Sidecar: true,
|
||||||
|
PrimaryOnly: false,
|
||||||
|
OriginalsOnly: false,
|
||||||
|
SizeLimit: 0,
|
||||||
|
Include: []string{},
|
||||||
|
Exclude: []string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectedFiles finds files based on the given selection form, e.g. for downloading or sharing.
|
||||||
|
func SelectedFiles(f form.Selection, o FileSelection) (results entity.Files, err error) {
|
||||||
|
if f.Empty() {
|
||||||
|
return results, errors.New("no items selected")
|
||||||
|
}
|
||||||
|
|
||||||
|
var concat string
|
||||||
|
|
||||||
|
switch DbDialect() {
|
||||||
|
case MySQL:
|
||||||
|
concat = "CONCAT(a.path, '/%')"
|
||||||
|
case SQLite3:
|
||||||
|
concat = "a.path || '/%'"
|
||||||
|
default:
|
||||||
|
return results, fmt.Errorf("unknown sql dialect: %s", DbDialect())
|
||||||
|
}
|
||||||
|
|
||||||
|
where := fmt.Sprintf(`photos.photo_uid IN (?)
|
||||||
|
OR photos.place_id IN (?)
|
||||||
|
OR photos.photo_uid IN (SELECT photo_uid FROM files WHERE file_uid IN (?))
|
||||||
|
OR photos.photo_path IN (
|
||||||
|
SELECT a.path FROM folders a WHERE a.folder_uid IN (?) UNION
|
||||||
|
SELECT b.path FROM folders a JOIN folders b ON b.path LIKE %s WHERE a.folder_uid IN (?))
|
||||||
|
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND album_uid IN (?))
|
||||||
|
OR files.file_uid IN (SELECT file_uid FROM %s m WHERE m.subj_uid IN (?))
|
||||||
|
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN labels l ON pl.label_id = l.id AND l.deleted_at IS NULL WHERE l.label_uid IN (?))
|
||||||
|
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN categories c ON c.label_id = pl.label_id JOIN labels lc ON lc.id = c.category_id AND lc.deleted_at IS NULL WHERE lc.label_uid IN (?))`,
|
||||||
|
concat, entity.Marker{}.TableName())
|
||||||
|
|
||||||
|
s := UnscopedDb().Table("files").
|
||||||
|
Select("files.*").
|
||||||
|
Joins("JOIN photos ON photos.id = files.photo_id").
|
||||||
|
Where("photos.deleted_at IS NULL").
|
||||||
|
Where("files.file_missing = 0").
|
||||||
|
Where(where, f.Photos, f.Places, f.Files, f.Files, f.Files, f.Albums, f.Subjects, f.Labels, f.Labels).
|
||||||
|
Group("files.id")
|
||||||
|
|
||||||
|
if o.OriginalsOnly {
|
||||||
|
s = s.Where("file_root = '/'")
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.PrimaryOnly {
|
||||||
|
s = s.Where("file_primary = 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !o.Sidecar {
|
||||||
|
s = s.Where("file_sidecar = 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !o.Video {
|
||||||
|
s = s.Where("file_video = 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.SizeLimit > 0 {
|
||||||
|
s = s.Where("file_size < ?", o.SizeLimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.Include) > 0 {
|
||||||
|
s = s.Where("file_type IN (?)", o.Include)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.Exclude) > 0 {
|
||||||
|
s = s.Where("file_type NOT IN (?)", o.Exclude)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := s.Scan(&results); result.Error != nil {
|
||||||
|
return results, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
@@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/photoprism/photoprism/internal/form"
|
"github.com/photoprism/photoprism/internal/form"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PhotoSelection queries all selected photos.
|
// SelectedPhotos finds photos based on the given selection form, e.g. for adding them to an album.
|
||||||
func PhotoSelection(f form.Selection) (results entity.Photos, err error) {
|
func SelectedPhotos(f form.Selection) (results entity.Photos, err error) {
|
||||||
if f.Empty() {
|
if f.Empty() {
|
||||||
return results, errors.New("no items selected")
|
return results, errors.New("no items selected")
|
||||||
}
|
}
|
||||||
@@ -47,47 +47,3 @@ func PhotoSelection(f form.Selection) (results entity.Photos, err error) {
|
|||||||
|
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileSelection queries all selected files e.g. for downloading.
|
|
||||||
func FileSelection(f form.Selection) (results entity.Files, err error) {
|
|
||||||
if f.Empty() {
|
|
||||||
return results, errors.New("no items selected")
|
|
||||||
}
|
|
||||||
|
|
||||||
var concat string
|
|
||||||
|
|
||||||
switch DbDialect() {
|
|
||||||
case MySQL:
|
|
||||||
concat = "CONCAT(a.path, '/%')"
|
|
||||||
case SQLite3:
|
|
||||||
concat = "a.path || '/%'"
|
|
||||||
default:
|
|
||||||
return results, fmt.Errorf("unknown sql dialect: %s", DbDialect())
|
|
||||||
}
|
|
||||||
|
|
||||||
where := fmt.Sprintf(`photos.photo_uid IN (?)
|
|
||||||
OR photos.place_id IN (?)
|
|
||||||
OR photos.photo_uid IN (SELECT photo_uid FROM files WHERE file_uid IN (?))
|
|
||||||
OR photos.photo_path IN (
|
|
||||||
SELECT a.path FROM folders a WHERE a.folder_uid IN (?) UNION
|
|
||||||
SELECT b.path FROM folders a JOIN folders b ON b.path LIKE %s WHERE a.folder_uid IN (?))
|
|
||||||
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND album_uid IN (?))
|
|
||||||
OR files.file_uid IN (SELECT file_uid FROM %s m WHERE m.subj_uid IN (?))
|
|
||||||
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN labels l ON pl.label_id = l.id AND l.deleted_at IS NULL WHERE l.label_uid IN (?))
|
|
||||||
OR photos.id IN (SELECT pl.photo_id FROM photos_labels pl JOIN categories c ON c.label_id = pl.label_id JOIN labels lc ON lc.id = c.category_id AND lc.deleted_at IS NULL WHERE lc.label_uid IN (?))`,
|
|
||||||
concat, entity.Marker{}.TableName())
|
|
||||||
|
|
||||||
s := UnscopedDb().Table("files").
|
|
||||||
Select("files.*").
|
|
||||||
Joins("JOIN photos ON photos.id = files.photo_id").
|
|
||||||
Where("photos.deleted_at IS NULL").
|
|
||||||
Where("files.file_missing = 0").
|
|
||||||
Where(where, f.Photos, f.Places, f.Files, f.Files, f.Files, f.Albums, f.Subjects, f.Labels, f.Labels).
|
|
||||||
Group("files.id")
|
|
||||||
|
|
||||||
if result := s.Scan(&results); result.Error != nil {
|
|
||||||
return results, result.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
@@ -14,7 +14,7 @@ func TestPhotoSelection(t *testing.T) {
|
|||||||
Photos: []string{},
|
Photos: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := PhotoSelection(f)
|
r, err := SelectedPhotos(f)
|
||||||
|
|
||||||
assert.Equal(t, "no items selected", err.Error())
|
assert.Equal(t, "no items selected", err.Error())
|
||||||
assert.Empty(t, r)
|
assert.Empty(t, r)
|
||||||
@@ -24,7 +24,7 @@ func TestPhotoSelection(t *testing.T) {
|
|||||||
Photos: []string{"pt9jtdre2lvl0yh7", "pt9jtdre2lvl0yh8"},
|
Photos: []string{"pt9jtdre2lvl0yh7", "pt9jtdre2lvl0yh8"},
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := PhotoSelection(f)
|
r, err := SelectedPhotos(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -41,7 +41,7 @@ func TestFileSelection(t *testing.T) {
|
|||||||
Photos: []string{},
|
Photos: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := FileSelection(f)
|
r, err := SelectedFiles(f, FileSelectionAll())
|
||||||
|
|
||||||
assert.Equal(t, "no items selected", err.Error())
|
assert.Equal(t, "no items selected", err.Error())
|
||||||
assert.Empty(t, r)
|
assert.Empty(t, r)
|
||||||
@@ -51,7 +51,7 @@ func TestFileSelection(t *testing.T) {
|
|||||||
Photos: []string{"pt9jtdre2lvl0yh7", "pt9jtdre2lvl0yh8"},
|
Photos: []string{"pt9jtdre2lvl0yh7", "pt9jtdre2lvl0yh8"},
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := FileSelection(f)
|
r, err := SelectedFiles(f, FileSelectionAll())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@@ -21,7 +21,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package query
|
package query
|
||||||
|
@@ -24,7 +24,7 @@ Feel free to send an e-mail to hello@photoprism.app if you have questions,
|
|||||||
want to support our work, or just want to say hello.
|
want to support our work, or just want to say hello.
|
||||||
|
|
||||||
Additional information can be found in our Developer Guide:
|
Additional information can be found in our Developer Guide:
|
||||||
https://docs.photoprism.app/developer-guide/
|
<https://docs.photoprism.app/developer-guide/>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package remote
|
package remote
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user