diff --git a/frontend/src/component/p-photo-clipboard.vue b/frontend/src/component/p-photo-clipboard.vue index 49d87cb4b..b2cec00a6 100644 --- a/frontend/src/component/p-photo-clipboard.vue +++ b/frontend/src/component/p-photo-clipboard.vue @@ -33,9 +33,20 @@ dark small color="cyan accent-4" - @click.stop="batchTag()" + v-if="selection.length" + @click.stop="batchStory()" > - label + mms + + + info clear @@ -105,7 +115,21 @@ axios.post("/api/v1/batch/photos/private", {"ids": this.selection}).then(function () { Event.publish("ajax.end"); - Event.publish("alert.success", "Photos marked as private"); + Event.publish("alert.success", "Toggled private flag"); + ctx.clearClipboard(); + ctx.refresh(); + }).catch(() => { + Event.publish("ajax.end"); + }); + }, + batchStory() { + Event.publish("ajax.start"); + + const ctx = this; + + axios.post("/api/v1/batch/photos/story", {"ids": this.selection}).then(function () { + Event.publish("ajax.end"); + Event.publish("alert.success", "Toggled story flag"); ctx.clearClipboard(); ctx.refresh(); }).catch(() => { @@ -138,6 +162,9 @@ this.$alert.warning("Not implemented yet"); this.expanded = false; }, + openDocs() { + window.open('https://docs.photoprism.org/en/latest/', '_blank'); + }, } }; diff --git a/frontend/src/component/p-photo-details.vue b/frontend/src/component/p-photo-details.vue index 202a3593c..328741883 100644 --- a/frontend/src/component/p-photo-details.vue +++ b/frontend/src/component/p-photo-details.vue @@ -60,7 +60,8 @@

{{ photo.PhotoTitle | truncate(80) }} - vpn_key + vpn_key + mms

date_range diff --git a/frontend/src/pages/albums.vue b/frontend/src/pages/albums.vue index b68e4e85c..8be67e364 100644 --- a/frontend/src/pages/albums.vue +++ b/frontend/src/pages/albums.vue @@ -32,7 +32,7 @@

No albums matched your search

-
Create a new album or try again using a different term.
+
Try again using a different term or create a new album
diff --git a/internal/api/batch.go b/internal/api/batch.go index 2eafc61a0..25dd579a4 100644 --- a/internal/api/batch.go +++ b/internal/api/batch.go @@ -5,6 +5,7 @@ import ( "net/http" "time" + "github.com/jinzhu/gorm" "github.com/photoprism/photoprism/internal/config" "github.com/photoprism/photoprism/internal/models" "github.com/photoprism/photoprism/internal/util" @@ -70,10 +71,43 @@ func BatchPhotosPrivate(router *gin.RouterGroup, conf *config.Config) { db := conf.Db() - db.Model(models.Photo{}).Where("id IN (?)", params.Ids).Updates(models.Photo{PhotoPrivate: true}) + db.Model(models.Photo{}).Where("id IN (?)", params.Ids).UpdateColumn("photo_private", gorm.Expr("IF (`photo_private`, 0, 1)")) elapsed := time.Since(start) c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("photos marked as private in %s", elapsed)}) }) } + +// POST /api/v1/batch/photos/story +func BatchPhotosStory(router *gin.RouterGroup, conf *config.Config) { + router.POST("/batch/photos/story", func(c *gin.Context) { + start := time.Now() + + var params BatchParams + + if err := c.BindJSON(¶ms); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst(err.Error())}) + return + } + + if len(params.Ids) == 0 { + log.Error("no photos selected") + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst("no photos selected")}) + return + } + + log.Infof("marking photos as story: %#v", params.Ids) + + db := conf.Db() + + db.Model(models.Photo{}).Where("id IN (?)", params.Ids).Updates(map[string]interface{}{ + "photo_story": gorm.Expr("IF (`photo_story`, 0, 1)"), + "photo_private": "0", + }) + + elapsed := time.Since(start) + + c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("photos marked as story in %s", elapsed)}) + }) +} diff --git a/internal/photoprism/search_result.go b/internal/photoprism/search_result.go index c7e0a7875..1ce483f16 100644 --- a/internal/photoprism/search_result.go +++ b/internal/photoprism/search_result.go @@ -23,6 +23,7 @@ type PhotoSearchResult struct { PhotoFavorite bool PhotoPrivate bool PhotoSensitive bool + PhotoStory bool // Camera CameraID uint diff --git a/internal/server/routes.go b/internal/server/routes.go index 0f38dd9b5..058326cfa 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -36,6 +36,7 @@ func registerRoutes(router *gin.Engine, conf *config.Config) { api.BatchPhotosDelete(v1, conf) api.BatchPhotosPrivate(v1, conf) + api.BatchPhotosStory(v1, conf) api.GetAlbums(v1, conf) api.LikeAlbum(v1, conf)