Albums: Improve UX and indexing
This commit is contained in:
parent
def8d50995
commit
ee49073cf2
8 changed files with 53 additions and 19 deletions
frontend/src
internal
|
@ -91,7 +91,7 @@
|
|||
:title="$gettext('Archive')"
|
||||
@click.stop="dialog.archive = true"
|
||||
:disabled="selection.length === 0"
|
||||
v-if="!manualAlbum && context !== 'archive' && $config.feature('archive')"
|
||||
v-if="!isAlbum && context !== 'archive' && $config.feature('archive')"
|
||||
class="action-archive"
|
||||
>
|
||||
<v-icon>archive</v-icon>
|
||||
|
@ -113,7 +113,7 @@
|
|||
color="remove"
|
||||
@click.stop="removeFromAlbum"
|
||||
:disabled="selection.length === 0"
|
||||
v-if="manualAlbum"
|
||||
v-if="isAlbum"
|
||||
class="action-delete"
|
||||
>
|
||||
<v-icon>remove</v-icon>
|
||||
|
@ -153,7 +153,7 @@ export default {
|
|||
return {
|
||||
config: this.$config.values,
|
||||
expanded: false,
|
||||
manualAlbum: this.album && this.album.Type === 'album',
|
||||
isAlbum: this.album && this.album.Type === 'album',
|
||||
dialog: {
|
||||
archive: false,
|
||||
album: false,
|
||||
|
|
|
@ -174,6 +174,11 @@
|
|||
<translate>Add photos or videos from search results by selecting them.</translate>
|
||||
</button>
|
||||
</div>
|
||||
<div class="caption mb-2" v-else-if="album.Type === 'folder'">
|
||||
<button @click.exact="edit(album)">
|
||||
/{{ album.Path | truncate(100) }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="caption mb-2 d-block" v-if="album.Location">
|
||||
<button @click.exact="edit(album)">
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
func ClearAlbumThumbCache(uid string) {
|
||||
cache := service.Cache()
|
||||
|
||||
for typeName, _ := range thumb.Types {
|
||||
for typeName := range thumb.Types {
|
||||
cacheKey := fmt.Sprintf("album-thumbs:%s:%s", uid, typeName)
|
||||
|
||||
if err := cache.Delete(cacheKey); err == nil {
|
||||
|
@ -229,7 +229,6 @@ func LikeAlbum(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
conf := service.Config()
|
||||
id := c.Param("uid")
|
||||
album, err := query.AlbumByUID(id)
|
||||
|
||||
|
@ -238,8 +237,10 @@ func LikeAlbum(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
album.AlbumFavorite = true
|
||||
conf.Db().Save(&album)
|
||||
if err := album.Update("AlbumFavorite", true); err != nil {
|
||||
Abort(c, http.StatusInternalServerError, i18n.ErrSaveFailed)
|
||||
return
|
||||
}
|
||||
|
||||
UpdateClientConfig()
|
||||
PublishAlbumEvent(EntityUpdated, id, c)
|
||||
|
@ -261,7 +262,6 @@ func DislikeAlbum(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
conf := service.Config()
|
||||
id := c.Param("uid")
|
||||
album, err := query.AlbumByUID(id)
|
||||
|
||||
|
@ -270,8 +270,10 @@ func DislikeAlbum(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
album.AlbumFavorite = false
|
||||
conf.Db().Save(&album)
|
||||
if err := album.Update("AlbumFavorite", false); err != nil {
|
||||
Abort(c, http.StatusInternalServerError, i18n.ErrSaveFailed)
|
||||
return
|
||||
}
|
||||
|
||||
UpdateClientConfig()
|
||||
PublishAlbumEvent(EntityUpdated, id, c)
|
||||
|
|
|
@ -31,6 +31,7 @@ type Album struct {
|
|||
CoverUID string `gorm:"type:VARBINARY(42);" json:"CoverUID" yaml:"CoverUID,omitempty"`
|
||||
FolderUID string `gorm:"type:VARBINARY(42);index;" json:"FolderUID" yaml:"FolderUID,omitempty"`
|
||||
AlbumSlug string `gorm:"type:VARBINARY(255);index;" json:"Slug" yaml:"Slug"`
|
||||
AlbumPath string `gorm:"type:VARBINARY(768);index;" json:"Path" yaml:"-"`
|
||||
AlbumType string `gorm:"type:VARBINARY(8);default:'album';" json:"Type" yaml:"Type,omitempty"`
|
||||
AlbumTitle string `gorm:"type:VARCHAR(255);" json:"Title" yaml:"Title"`
|
||||
AlbumLocation string `gorm:"type:VARCHAR(255);" json:"Location" yaml:"Location,omitempty"`
|
||||
|
@ -41,7 +42,6 @@ type Album struct {
|
|||
AlbumFilter string `gorm:"type:VARBINARY(1024);" json:"Filter" yaml:"Filter,omitempty"`
|
||||
AlbumOrder string `gorm:"type:VARBINARY(32);" json:"Order" yaml:"Order,omitempty"`
|
||||
AlbumTemplate string `gorm:"type:VARBINARY(255);" json:"Template" yaml:"Template,omitempty"`
|
||||
AlbumPath string `gorm:"type:VARBINARY(768);" json:"Path" yaml:"-"`
|
||||
AlbumCountry string `gorm:"type:VARBINARY(2);index:idx_albums_country_year_month;default:'zz'" json:"Country" yaml:"Country,omitempty"`
|
||||
AlbumYear int `gorm:"index:idx_albums_country_year_month;" json:"Year" yaml:"Year,omitempty"`
|
||||
AlbumMonth int `gorm:"index:idx_albums_country_year_month;" json:"Month" yaml:"Month,omitempty"`
|
||||
|
@ -212,10 +212,21 @@ func NewMonthAlbum(albumTitle, albumSlug string, year, month int) *Album {
|
|||
}
|
||||
|
||||
// FindAlbumBySlug finds a matching album or returns nil.
|
||||
func FindAlbumBySlug(slug, albumType string) *Album {
|
||||
func FindAlbumBySlug(albumSlug, albumType string) *Album {
|
||||
result := Album{}
|
||||
|
||||
if err := UnscopedDb().Where("album_slug = ? AND album_type = ?", slug, albumType).First(&result).Error; err != nil {
|
||||
if err := UnscopedDb().Where("album_slug = ? AND album_type = ?", albumSlug, albumType).First(&result).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &result
|
||||
}
|
||||
|
||||
// FindFolderAlbum finds a matching folder album or returns nil.
|
||||
func FindFolderAlbum(albumSlug, albumPath string) *Album {
|
||||
result := Album{}
|
||||
|
||||
if err := UnscopedDb().Where("((album_slug <> '' AND album_slug = ?) OR album_path = ?) AND album_type = ?", albumSlug, albumPath, AlbumFolder).First(&result).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -309,6 +320,17 @@ func (m *Album) Update(attr string, value interface{}) error {
|
|||
return UnscopedDb().Model(m).UpdateColumn(attr, value).Error
|
||||
}
|
||||
|
||||
// UpdatePath sets a unique path for an albums.
|
||||
func (m *Album) UpdatePath(albumPath string) error {
|
||||
if err := m.Update("AlbumPath", albumPath); err != nil {
|
||||
return err
|
||||
} else if err := UnscopedDb().Exec("UPDATE albums SET album_path = NULL WHERE album_path = ? AND id <> ?", albumPath, m.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Save updates the existing or inserts a new row.
|
||||
func (m *Album) Save() error {
|
||||
return Db().Save(m).Error
|
||||
|
|
|
@ -126,7 +126,12 @@ func (m *Folder) SetValuesFromPath() {
|
|||
|
||||
// Slug returns a slug based on the folder title.
|
||||
func (m *Folder) Slug() string {
|
||||
return slug.Make(m.FolderTitle)
|
||||
return slug.Make(m.Path)
|
||||
}
|
||||
|
||||
// RootPath returns the full folder path including root.
|
||||
func (m *Folder) RootPath() string {
|
||||
return path.Join(m.Root, m.Path)
|
||||
}
|
||||
|
||||
// Title returns a human readable folder title.
|
||||
|
|
|
@ -127,8 +127,8 @@ func TestFolder_SetValuesFromPath(t *testing.T) {
|
|||
|
||||
func TestFolder_Slug(t *testing.T) {
|
||||
t.Run("/", func(t *testing.T) {
|
||||
folder := Folder{FolderTitle: "Beautiful beach"}
|
||||
assert.Equal(t, "beautiful-beach", folder.Slug())
|
||||
folder := Folder{FolderTitle: "Beautiful beach", Root: "sidecar", Path: "ugly/beach"}
|
||||
assert.Equal(t, "ugly-beach", folder.Slug())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -72,11 +72,11 @@ func (m *Moments) Start() (err error) {
|
|||
Public: true,
|
||||
}
|
||||
|
||||
if a := entity.FindAlbumBySlug(mom.Slug(), entity.AlbumFolder); a != nil {
|
||||
if a := entity.FindFolderAlbum(mom.Slug(), mom.Path); a != nil {
|
||||
if a.DeletedAt != nil {
|
||||
// Nothing to do.
|
||||
log.Tracef("moments: %s was deleted (%s)", txt.Quote(a.AlbumTitle), a.AlbumFilter)
|
||||
} else if err := a.Update("AlbumPath", mom.Path); err != nil {
|
||||
} else if err := a.UpdatePath(mom.Path); err != nil {
|
||||
log.Errorf("moments: %s (update folder album)", err.Error())
|
||||
} else {
|
||||
log.Tracef("moments: %s already exists (%s)", txt.Quote(a.AlbumTitle), a.AlbumFilter)
|
||||
|
|
|
@ -113,7 +113,7 @@ func AlbumSearch(f form.AlbumSearch) (results AlbumResults, err error) {
|
|||
Select("albums.*, cp.photo_count, cl.link_count").
|
||||
Joins("LEFT JOIN (SELECT album_uid, count(photo_uid) AS photo_count FROM photos_albums WHERE hidden = 0 GROUP BY album_uid) AS cp ON cp.album_uid = albums.album_uid").
|
||||
Joins("LEFT JOIN (SELECT share_uid, count(share_uid) AS link_count FROM links GROUP BY share_uid) AS cl ON cl.share_uid = albums.album_uid").
|
||||
Where("albums.album_type <> 'folder' OR albums.album_path IS NULL OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.deleted_at IS NULL)").
|
||||
Where("albums.album_type <> 'folder' OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.deleted_at IS NULL)").
|
||||
Where("albums.deleted_at IS NULL")
|
||||
|
||||
if f.ID != "" {
|
||||
|
|
Loading…
Reference in a new issue