Albums: Code clean-up and small fixes #15

This commit is contained in:
Michael Mayer 2019-06-18 06:37:10 +02:00
parent 94d670a277
commit df5aa57e68
8 changed files with 54 additions and 23 deletions

View file

@ -88,9 +88,9 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile @click="">
<v-list-tile @click.stop="$alert.warning('Work in progress')">
<v-list-tile-content>
<v-list-tile-title>Not implemented yet</v-list-tile-title>
<v-list-tile-title>Work in progress...</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list-group>

View file

@ -19,7 +19,7 @@
<v-spacer></v-spacer>
<v-btn icon @click.prevent="create">
<v-icon>create_new_folder</v-icon>
<v-icon>add</v-icon>
</v-btn>
</v-toolbar>
</v-form>
@ -32,7 +32,7 @@
<v-card-title primary-title>
<div>
<h3 class="title mb-3">No albums matched your search</h3>
<div>Try again using a different name or <a @click.prevent="create" href="#">create a new album</a>.</div>
<div><v-btn @click.prevent.stop="create" small>Create a new album</v-btn> or try again using a different term.</div>
</div>
</v-card-title>
</v-card>
@ -218,13 +218,16 @@
this.pageSize = pageSize;
},
create() {
const name = "New Album " + Date.now();
const name = "New Album";
const album = new Album({"AlbumName": name});
album.save().then(() => {
this.$alert.success(name + " created");
this.refresh();
this.filter.q = "";
this.lastFilter = {};
this.search();
})
},
},

View file

@ -1,10 +1,12 @@
package api
import (
"github.com/photoprism/photoprism/internal/models"
"fmt"
"net/http"
"strconv"
"github.com/photoprism/photoprism/internal/models"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/photoprism/photoprism/internal/config"
@ -52,20 +54,18 @@ func CreateAlbum(router *gin.RouterGroup, conf *config.Config) {
if err := c.BindJSON(&params); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst(err.Error())})
return
}
if len(params.AlbumName) == 0 {
log.Error("album name empty")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst("album name empty")})
}
album := &models.Album{AlbumName: params.AlbumName}
album := models.NewAlbum(params.AlbumName)
if res := conf.Db().Create(album); res.Error != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": util.UcFirst(res.Error.Error())})
log.Error(res.Error.Error())
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("\"%s\" already exists", album.AlbumName)})
return
}
c.JSON(http.StatusOK, http.Response{})
c.JSON(http.StatusOK, album)
})
}

View file

@ -26,11 +26,13 @@ func BatchPhotosDelete(router *gin.RouterGroup, conf *config.Config) {
if err := c.BindJSON(&params); 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("deleting photos: %#v", params.Ids)
@ -55,11 +57,13 @@ func BatchPhotosPrivate(router *gin.RouterGroup, conf *config.Config) {
if err := c.BindJSON(&params); 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 private: %#v", params.Ids)

View file

@ -5,3 +5,7 @@ var photoIconSvg = []byte(`
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
</svg>`)
var albumIconSvg = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>
<path d="M0 0h24v24H0z" fill="none"/></svg>`)

View file

@ -129,6 +129,7 @@ func LabelThumbnail(router *gin.RouterGroup, conf *config.Config) {
func AlbumThumbnail(router *gin.RouterGroup, conf *config.Config) {
router.GET("/albums/:uuid/thumbnail/:type", func(c *gin.Context) {
typeName := c.Param("type")
uuid := c.Param("uuid")
thumbType, ok := photoprism.ThumbnailTypes[typeName]
@ -140,15 +141,11 @@ func AlbumThumbnail(router *gin.RouterGroup, conf *config.Config) {
search := photoprism.NewSearch(conf.OriginalsPath(), conf.Db())
// log.Infof("Searching for album uuid: %s", c.Param("uuid"))
file, err := search.FindAlbumThumbByUUID(c.Param("uuid"))
// log.Infof("Album thumb file: %#v", file)
file, err := search.FindAlbumThumbByUUID(uuid)
if err != nil {
c.Data(http.StatusNotFound, "image/svg+xml", photoIconSvg)
// c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": util.UcFirst(err.Error())})
log.Debugf("album has no photos yet, using generic thumb image: %s", uuid)
c.Data(http.StatusOK, "image/svg+xml", albumIconSvg)
return
}

View file

@ -33,6 +33,7 @@ type PhotoSearchForm struct {
Mono bool `form:"mono"`
Portrait bool `form:"portrait"`
Location bool `form:"location"`
Album string `form:"album"`
Label string `form:"label"`
Country string `form:"country"`
Color string `form:"color"`

View file

@ -1,6 +1,9 @@
package models
import (
"strings"
"github.com/gosimple/slug"
"github.com/jinzhu/gorm"
uuid "github.com/satori/go.uuid"
)
@ -9,7 +12,7 @@ import (
type Album struct {
Model
AlbumUUID string `gorm:"unique_index;"`
AlbumSlug string `gorm:"unique_index;"`
AlbumSlug string `gorm:"index;"`
AlbumName string
AlbumDescription string `gorm:"type:text;"`
AlbumNotes string `gorm:"type:text;"`
@ -23,3 +26,22 @@ type Album struct {
func (m *Album) BeforeCreate(scope *gorm.Scope) error {
return scope.SetColumn("AlbumUUID", uuid.NewV4().String())
}
func NewAlbum(albumName string) *Album {
albumName = strings.TrimSpace(albumName)
if albumName == "" {
albumName = "New Album"
}
albumSlug := slug.Make(albumName)
albumUUID := uuid.NewV4().String()
result := &Album{
AlbumUUID: albumUUID,
AlbumSlug: albumSlug,
AlbumName: albumName,
}
return result
}