Add photos from other albums (clone)
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
d89356c715
commit
961fda3b11
|
@ -35,7 +35,18 @@
|
|||
>
|
||||
<v-icon>get_app</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
fab
|
||||
dark
|
||||
small
|
||||
:title="labels.clone"
|
||||
color="album"
|
||||
:disabled="selection.length === 0"
|
||||
@click.stop="dialog.album = true"
|
||||
class="p-album-clipboard-clone"
|
||||
>
|
||||
<v-icon>folder</v-icon>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
fab
|
||||
dark
|
||||
|
@ -61,6 +72,8 @@
|
|||
</v-btn>
|
||||
</v-speed-dial>
|
||||
</v-container>
|
||||
<p-photo-album-dialog :show="dialog.album" @cancel="dialog.album = false"
|
||||
@confirm="cloneAlbums"></p-photo-album-dialog>
|
||||
<p-album-delete-dialog :show="dialog.delete" @cancel="dialog.delete = false"
|
||||
@confirm="batchDelete"></p-album-delete-dialog>
|
||||
</div>
|
||||
|
@ -81,10 +94,12 @@
|
|||
expanded: false,
|
||||
dialog: {
|
||||
delete: false,
|
||||
album: false,
|
||||
edit: false,
|
||||
},
|
||||
labels: {
|
||||
download: this.$gettext("Download"),
|
||||
clone: this.$gettext("Add to album"),
|
||||
delete: this.$gettext("Delete"),
|
||||
},
|
||||
|
||||
|
@ -95,6 +110,14 @@
|
|||
this.clearSelection();
|
||||
this.expanded = false;
|
||||
},
|
||||
cloneAlbums(ppid) {
|
||||
this.dialog.album = false;
|
||||
|
||||
Api.post(`albums/${ppid}/clone`, {"albums": this.selection}).then(() => this.onCloned());
|
||||
},
|
||||
onCloned() {
|
||||
this.clearClipboard();
|
||||
},
|
||||
batchDelete() {
|
||||
this.dialog.delete = false;
|
||||
|
||||
|
|
|
@ -242,6 +242,58 @@ func DislikeAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
})
|
||||
}
|
||||
|
||||
// POST /api/v1/albums/:uid/clone
|
||||
func CloneAlbums(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.POST("/albums/:uid/clone", func(c *gin.Context) {
|
||||
if Unauthorized(c, conf) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
a, err := query.AlbumByUID(c.Param("uid"))
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, ErrAlbumNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
var f form.Selection
|
||||
|
||||
if err := c.BindJSON(&f); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": txt.UcFirst(err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
var added []entity.PhotoAlbum
|
||||
|
||||
for _, uid := range f.Albums {
|
||||
cloneAlbum, err := query.AlbumByUID(uid)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("album: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
photos, err := query.AlbumPhotos(cloneAlbum, 10000)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("album: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
added = append(added, a.AddPhotos(photos.UIDs())...)
|
||||
}
|
||||
|
||||
if len(added) > 0 {
|
||||
event.Success(fmt.Sprintf("selection added to %s", txt.Quote(a.Title())))
|
||||
|
||||
PublishAlbumEvent(EntityUpdated, a.AlbumUID, c)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "album contents cloned", "album": a, "added": added})
|
||||
})
|
||||
}
|
||||
|
||||
// POST /api/v1/albums/:uid/photos
|
||||
func AddPhotosToAlbum(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.POST("/albums/:uid/photos", func(c *gin.Context) {
|
||||
|
@ -333,7 +385,7 @@ func RemovePhotosFromAlbum(router *gin.RouterGroup, conf *config.Config) {
|
|||
})
|
||||
}
|
||||
|
||||
// GET /albums/:uid/dl
|
||||
// GET /api/v1/albums/:uid/dl
|
||||
func DownloadAlbum(router *gin.RouterGroup, conf *config.Config) {
|
||||
router.GET("/albums/:uid/dl", func(c *gin.Context) {
|
||||
if InvalidDownloadToken(c, conf) {
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
type Photos []Photo
|
||||
|
||||
// UIDs returns a slice of unique photo IDs.
|
||||
// UIDs returns a slice of photo UIDs.
|
||||
func (m Photos) UIDs() []string {
|
||||
result := make([]string, len(m))
|
||||
|
||||
|
|
|
@ -88,6 +88,17 @@ type PhotoResult struct {
|
|||
|
||||
type PhotoResults []PhotoResult
|
||||
|
||||
// UIDs returns a slice of photo UIDs.
|
||||
func (m PhotoResults) UIDs() []string {
|
||||
result := make([]string, len(m))
|
||||
|
||||
for i, el := range m {
|
||||
result[i] = el.PhotoUID
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (m PhotoResults) Merged() (PhotoResults, int, error) {
|
||||
count := len(m)
|
||||
merged := make([]PhotoResult, 0, count)
|
||||
|
|
|
@ -31,7 +31,7 @@ func PhotoSelection(f form.Selection) (results entity.Photos, err error) {
|
|||
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 album_uid IN (?))
|
||||
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND album_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)
|
||||
|
@ -70,7 +70,7 @@ func FileSelection(f form.Selection) (results entity.Files, err error) {
|
|||
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 album_uid IN (?))
|
||||
OR photos.photo_uid IN (SELECT photo_uid FROM photos_albums WHERE hidden = 0 AND album_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)
|
||||
|
|
|
@ -87,6 +87,7 @@ func registerRoutes(router *gin.Engine, conf *config.Config) {
|
|||
api.LikeAlbum(v1, conf)
|
||||
api.DislikeAlbum(v1, conf)
|
||||
api.AlbumThumbnail(v1, conf)
|
||||
api.CloneAlbums(v1, conf)
|
||||
api.AddPhotosToAlbum(v1, conf)
|
||||
api.RemovePhotosFromAlbum(v1, conf)
|
||||
|
||||
|
|
Loading…
Reference in a new issue