Proof-of-concept for batch like & delete

Requires additional code clean-up and unit / acceptance tests
This commit is contained in:
Michael Mayer 2019-06-14 16:35:18 -07:00
parent 9e761549e4
commit ea3f209f8f
4 changed files with 111 additions and 5 deletions

View file

@ -79,10 +79,14 @@
</v-speed-dial>
</template>
<script>
import Event from "pubsub-js";
import axios from "axios";
export default {
name: 'p-photo-clipboard',
props: {
selection: Array,
refresh: Function,
},
data() {
return {
@ -95,12 +99,32 @@
this.expanded = false;
},
batchLike() {
this.$alert.warning("Not implemented yet");
this.expanded = false;
Event.publish("ajax.start");
const ctx = this;
axios.post("/api/v1/batch/photos/like", {"ids": this.selection}).then(function () {
Event.publish("ajax.end");
Event.publish("alert.success", "Photos liked");
ctx.clearClipboard();
ctx.refresh();
}).catch(() => {
Event.publish("ajax.end");
});
},
batchDelete() {
this.$alert.warning("Not implemented yet");
this.expanded = false;
Event.publish("ajax.start");
const ctx = this;
axios.post("/api/v1/batch/photos/delete", {"ids": this.selection}).then(function () {
Event.publish("ajax.end");
Event.publish("alert.success", "Photos deleted");
ctx.clearClipboard();
ctx.refresh();
}).catch(() => {
Event.publish("ajax.end");
});
},
batchTag() {
this.$alert.warning("Not implemented yet");

View file

@ -6,7 +6,7 @@
:settings-change="updateQuery"></p-photo-search>
<v-container fluid>
<p-photo-clipboard :selection="selection"></p-photo-clipboard>
<p-photo-clipboard :refresh="refresh" :selection="selection"></p-photo-clipboard>
<p-photo-mosaic v-if="settings.view === 'mosaic'" :photos="results" :selection="selection"
:open-photo="openPhoto"></p-photo-mosaic>
@ -151,6 +151,10 @@
return params;
},
refresh() {
this.lastFilter = {};
this.search();
},
search() {
this.scrollDisabled = true;

75
internal/api/batch.go Normal file
View file

@ -0,0 +1,75 @@
package api
import (
"fmt"
"net/http"
"time"
"github.com/photoprism/photoprism/internal/config"
"github.com/photoprism/photoprism/internal/models"
"github.com/photoprism/photoprism/internal/util"
log "github.com/sirupsen/logrus"
"github.com/gin-gonic/gin"
)
type BatchParams struct {
Ids []int `json:"ids"`
}
// POST /api/v1/batch/photos/delete
func BatchPhotosDelete(router *gin.RouterGroup, conf *config.Config) {
router.POST("/batch/photos/delete", func(c *gin.Context) {
start := time.Now()
var params BatchParams
if err := c.BindJSON(&params); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst(err.Error())})
}
if len(params.Ids) == 0 {
log.Error("no photos selected")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst("no photos selected")})
}
log.Infof("deleting photos: %#v", params.Ids)
db := conf.Db()
db.Where("id IN (?)", params.Ids).Delete(&models.Photo{})
db.Where("photo_id IN (?)", params.Ids).Delete(&models.File{})
elapsed := time.Since(start)
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("photos deleted in %s", elapsed)})
})
}
// POST /api/v1/batch/photos/like
func BatchPhotosLike(router *gin.RouterGroup, conf *config.Config) {
router.POST("/batch/photos/like", func(c *gin.Context) {
start := time.Now()
var params BatchParams
if err := c.BindJSON(&params); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst(err.Error())})
}
if len(params.Ids) == 0 {
log.Error("no photos selected")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst("no photos selected")})
}
log.Infof("liking photos: %#v", params.Ids)
db := conf.Db()
db.Model(models.Photo{}).Where("id IN (?)", params.Ids).Updates(models.Photo{PhotoFavorite: true})
elapsed := time.Since(start)
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("photos liked in %s", elapsed)})
})
}

View file

@ -32,6 +32,9 @@ func registerRoutes(router *gin.Engine, conf *config.Config) {
api.Upload(v1, conf)
api.Import(v1, conf)
api.BatchPhotosDelete(v1, conf)
api.BatchPhotosLike(v1, conf)
}
// Default HTML page (client-side routing implemented via Vue.js)