Calendar: Improve hiding empty months #1456
This commit is contained in:
parent
fb10bda98f
commit
92748180c1
6 changed files with 183 additions and 30 deletions
|
@ -201,7 +201,6 @@ func DeleteAlbum(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
conf := service.Config()
|
||||
id := c.Param("uid")
|
||||
|
||||
a, err := query.AlbumByUID(id)
|
||||
|
@ -211,9 +210,13 @@ func DeleteAlbum(router *gin.RouterGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
PublishAlbumEvent(EntityDeleted, id, c)
|
||||
if err := a.Delete(); err != nil {
|
||||
log.Errorf("album: %s (delete)", err)
|
||||
AbortDeleteFailed(c)
|
||||
return
|
||||
}
|
||||
|
||||
conf.Db().Delete(&a)
|
||||
PublishAlbumEvent(EntityDeleted, id, c)
|
||||
|
||||
UpdateClientConfig()
|
||||
|
||||
|
|
|
@ -387,7 +387,62 @@ func (m *Album) Create() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Returns the album title.
|
||||
// Delete marks the entity as deleted in the database.
|
||||
func (m *Album) Delete() error {
|
||||
if m.Deleted() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := Db().Delete(m).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch m.AlbumType {
|
||||
case AlbumDefault:
|
||||
event.Publish("count.albums", event.Data{"count": -1})
|
||||
case AlbumMoment:
|
||||
event.Publish("count.moments", event.Data{"count": -1})
|
||||
case AlbumMonth:
|
||||
event.Publish("count.months", event.Data{"count": -1})
|
||||
case AlbumFolder:
|
||||
event.Publish("count.folders", event.Data{"count": -1})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deleted tests if the entity is deleted.
|
||||
func (m *Album) Deleted() bool {
|
||||
return m.DeletedAt != nil
|
||||
}
|
||||
|
||||
// Restore restores the entity in the database.
|
||||
func (m *Album) Restore() error {
|
||||
if !m.Deleted() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := UnscopedDb().Model(m).Update("DeletedAt", nil).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.DeletedAt = nil
|
||||
|
||||
switch m.AlbumType {
|
||||
case AlbumDefault:
|
||||
event.Publish("count.albums", event.Data{"count": 1})
|
||||
case AlbumMoment:
|
||||
event.Publish("count.moments", event.Data{"count": 1})
|
||||
case AlbumMonth:
|
||||
event.Publish("count.months", event.Data{"count": 1})
|
||||
case AlbumFolder:
|
||||
event.Publish("count.folders", event.Data{"count": 1})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Title returns the album title.
|
||||
func (m *Album) Title() string {
|
||||
return m.AlbumTitle
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package entity
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
@ -13,6 +14,7 @@ type LabelPhotoCount struct {
|
|||
|
||||
type LabelPhotoCounts []LabelPhotoCount
|
||||
|
||||
// LabelCounts returns the number of photos for each label ID.
|
||||
func LabelCounts() LabelPhotoCounts {
|
||||
result := LabelPhotoCounts{}
|
||||
|
||||
|
@ -43,6 +45,8 @@ func LabelCounts() LabelPhotoCounts {
|
|||
|
||||
// UpdatePhotoCounts updates static photos counts and visibilities.
|
||||
func UpdatePhotoCounts() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
// Update places.
|
||||
if err = Db().Table("places").
|
||||
UpdateColumn("photo_count", gorm.Expr("(SELECT COUNT(*) FROM photos p "+
|
||||
|
@ -53,6 +57,10 @@ func UpdatePhotoCounts() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("places: updating photo counts completed in %s", time.Since(start))
|
||||
|
||||
start = time.Now()
|
||||
|
||||
// Update subjects.
|
||||
if err = Db().Table(Subject{}.TableName()).
|
||||
UpdateColumn("file_count", gorm.Expr("(SELECT COUNT(*) FROM files f "+
|
||||
|
@ -64,6 +72,10 @@ func UpdatePhotoCounts() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("subjects: updating file counts completed in %s", time.Since(start))
|
||||
|
||||
start = time.Now()
|
||||
|
||||
// Update labels.
|
||||
if IsDialect(MySQL) {
|
||||
if err = Db().
|
||||
|
@ -117,22 +129,30 @@ func UpdatePhotoCounts() (err error) {
|
|||
return fmt.Errorf("unknown sql dialect %s", DbDialect())
|
||||
}
|
||||
|
||||
log.Debugf("labels: updating photo counts completed in %s", time.Since(start))
|
||||
|
||||
/* TODO: Slow with many photos due to missing index.
|
||||
start = time.Now()
|
||||
|
||||
// Update calendar album visibility.
|
||||
switch DbDialect() {
|
||||
default:
|
||||
if err = UnscopedDb().Exec(`UPDATE albums SET deleted_at = ? WHERE album_type=? AND id NOT IN (
|
||||
SELECT a.id FROM albums a JOIN photos p ON a.album_month = p.photo_month AND a.album_year = p.photo_year
|
||||
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = 0 WHERE album_type=?)`,
|
||||
SELECT a.id FROM albums a JOIN photos p ON a.album_month = MONTH(p.taken_at) AND a.album_year = YEAR(p.taken_at)
|
||||
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = 0 WHERE album_type=? GROUP BY a.id)`,
|
||||
TimeStamp(), AlbumMonth, AlbumMonth).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err = UnscopedDb().Exec(`UPDATE albums SET deleted_at = NULL WHERE album_type=? AND id IN (
|
||||
SELECT a.id FROM albums a JOIN photos p ON a.album_month = p.photo_month AND a.album_year = p.photo_year
|
||||
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = 0 WHERE album_type=?)`,
|
||||
SELECT a.id FROM albums a JOIN photos p ON a.album_month = MONTH(p.taken_at) AND a.album_year = YEAR(p.taken_at)
|
||||
AND p.deleted_at IS NULL AND p.photo_quality > -1 AND p.photo_private = 0 WHERE album_type=? GROUP BY a.id)`,
|
||||
AlbumMonth, AlbumMonth).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("calendar: updating visibility completed in %s", time.Since(start))
|
||||
*/
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -102,11 +102,12 @@ func (w *Moments) Start() (err error) {
|
|||
} else {
|
||||
for _, mom := range results {
|
||||
if a := entity.FindAlbumBySlug(mom.Slug(), entity.AlbumMonth); a != nil {
|
||||
if a.DeletedAt != nil {
|
||||
// Nothing to do.
|
||||
log.Tracef("moments: %s was deleted (%s)", txt.Quote(a.AlbumTitle), a.AlbumFilter)
|
||||
} else {
|
||||
if !a.Deleted() {
|
||||
log.Tracef("moments: %s already exists (%s)", txt.Quote(a.AlbumTitle), a.AlbumFilter)
|
||||
} else if err := a.Restore(); err != nil {
|
||||
log.Errorf("moments: %s (restore month)", err.Error())
|
||||
} else {
|
||||
log.Infof("moments: %s restored", txt.Quote(a.AlbumTitle))
|
||||
}
|
||||
} else if a := entity.NewMonthAlbum(mom.Title(), mom.Slug(), mom.Year, mom.Month); a != nil {
|
||||
if err := a.Create(); err != nil {
|
||||
|
|
|
@ -58,7 +58,7 @@ func AlbumByUID(albumUID string) (album entity.Album, err error) {
|
|||
func AlbumCoverByUID(uid string) (file entity.File, err error) {
|
||||
a := entity.Album{}
|
||||
|
||||
if err := Db().Where("album_uid = ?", uid).First(&a).Error; err != nil {
|
||||
if err := UnscopedDb().Where("album_uid = ?", uid).First(&a).Error; err != nil {
|
||||
return file, err
|
||||
} else if a.AlbumType != entity.AlbumDefault { // TODO: Optimize
|
||||
f := form.PhotoSearch{Album: a.AlbumUID, Filter: a.AlbumFilter, Order: entity.SortOrderRelevance, Count: 1, Offset: 0, Merged: false}
|
||||
|
@ -75,7 +75,16 @@ func AlbumCoverByUID(uid string) (file entity.File, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
return file, fmt.Errorf("found no cover for moment")
|
||||
// Automatically hide empty months.
|
||||
if a.AlbumType == entity.AlbumMonth {
|
||||
if err := a.Delete(); err != nil {
|
||||
log.Errorf("album: %s (hide %s)", err, a.AlbumType)
|
||||
} else {
|
||||
log.Infof("album: %s hidden", txt.Quote(a.AlbumTitle))
|
||||
}
|
||||
}
|
||||
|
||||
return file, fmt.Errorf("no cover found")
|
||||
}
|
||||
|
||||
if err := Db().Where("files.file_primary = 1 AND files.file_missing = 0 AND files.file_type = 'jpg' AND files.deleted_at IS NULL").
|
||||
|
|
|
@ -2,14 +2,17 @@ package query
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
)
|
||||
|
||||
// UpdateAlbumDefaultPreviews updates default album preview images.
|
||||
func UpdateAlbumDefaultPreviews() error {
|
||||
return Db().Table(entity.Album{}.TableName()).
|
||||
func UpdateAlbumDefaultPreviews() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
err = Db().Table(entity.Album{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
SELECT f.file_hash FROM files f
|
||||
JOIN photos_albums pa ON pa.album_uid = albums.album_uid AND pa.photo_uid = f.photo_uid AND pa.hidden = 0
|
||||
|
@ -17,11 +20,17 @@ func UpdateAlbumDefaultPreviews() error {
|
|||
WHERE f.deleted_at IS NULL AND f.file_missing = 0 AND f.file_hash <> '' AND f.file_primary = 1 AND f.file_type = 'jpg'
|
||||
ORDER BY p.taken_at DESC LIMIT 1
|
||||
) WHERE thumb_src='' AND album_type = 'album' AND deleted_at IS NULL`)).Error
|
||||
|
||||
log.Debugf("albums: updating previews completed in %s", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateAlbumFolderPreviews updates folder album preview images.
|
||||
func UpdateAlbumFolderPreviews() error {
|
||||
return Db().Table(entity.Album{}.TableName()).
|
||||
func UpdateAlbumFolderPreviews() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
err = Db().Table(entity.Album{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
SELECT f.file_hash FROM files f
|
||||
JOIN photos p ON p.id = f.photo_id AND p.photo_path = albums.album_path AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > -1
|
||||
|
@ -29,19 +38,51 @@ func UpdateAlbumFolderPreviews() error {
|
|||
ORDER BY p.taken_at DESC LIMIT 1
|
||||
) WHERE thumb_src = '' AND album_type = 'folder' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
|
||||
log.Debugf("folders: updating previews completed in %s", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateAlbumMonthPreviews updates month album preview images.
|
||||
func UpdateAlbumMonthPreviews() error {
|
||||
return Db().Table(entity.Album{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
SELECT f.file_hash FROM files f
|
||||
JOIN photos p ON p.id = f.photo_id AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > -1
|
||||
AND p.photo_year = albums.album_year AND p.photo_month = albums.album_month AND p.photo_month = albums.album_month
|
||||
WHERE f.deleted_at IS NULL AND f.file_hash <> '' AND f.file_missing = 0 AND f.file_primary = 1 AND f.file_type = 'jpg'
|
||||
func UpdateAlbumMonthPreviews() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
err = Db().Table(entity.Album{}.TableName()).
|
||||
Where("album_type = ?", entity.AlbumMonth).
|
||||
Where("thumb IS NOT NULL AND thumb_src = ?", entity.SrcAuto).
|
||||
UpdateColumns(entity.Values{"thumb": nil}).Error
|
||||
|
||||
/* TODO: Slow with many photos due to missing index.
|
||||
|
||||
switch DbDialect() {
|
||||
case MySQL:
|
||||
err = Db().Table(entity.Album{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
SELECT f.file_hash FROM files f JOIN photos p ON p.id = f.photo_id
|
||||
WHERE YEAR(p.taken_at) = albums.album_year AND MONTH(p.taken_at) = albums.album_month
|
||||
AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > -1 AND f.deleted_at IS NULL
|
||||
AND f.file_hash <> '' AND f.file_missing = 0 AND f.file_primary = 1 AND f.file_type = 'jpg'
|
||||
ORDER BY p.taken_at DESC LIMIT 1
|
||||
) WHERE thumb_src = '' AND album_type = 'month' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
) WHERE thumb IS NULL AND thumb_src = '' AND album_type = 'month' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
case SQLite:
|
||||
err = Db().Table(entity.Album{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
SELECT f.file_hash FROM files f JOIN photos p ON p.id = f.photo_id
|
||||
WHERE strftime('%Y%m', p.taken_at) = (albums.album_year || printf('%02d', albums.album_month))
|
||||
AND p.photo_private = 0 AND p.deleted_at IS NULL AND p.photo_quality > -1 AND f.deleted_at IS NULL
|
||||
AND f.file_hash <> '' AND f.file_missing = 0 AND f.file_primary = 1 AND f.file_type = 'jpg'
|
||||
ORDER BY p.taken_at DESC LIMIT 1
|
||||
) WHERE thumb IS NULL AND thumb_src = '' AND album_type = 'month' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
log.Debugf("calendar: updating previews completed in %s", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateAlbumPreviews updates album preview images.
|
||||
|
@ -66,6 +107,8 @@ func UpdateAlbumPreviews() (err error) {
|
|||
|
||||
// UpdateLabelPreviews updates label preview images.
|
||||
func UpdateLabelPreviews() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
// Labels.
|
||||
if err = Db().Table(entity.Label{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
|
@ -79,6 +122,15 @@ func UpdateLabelPreviews() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("labels: updating previews completed in %s", time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateCategoryPreviews updates category preview images.
|
||||
func UpdateCategoryPreviews() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
// Categories.
|
||||
if err = Db().Table(entity.Label{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr(`(
|
||||
|
@ -93,11 +145,15 @@ func UpdateLabelPreviews() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("categories: updating previews completed in %s", time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSubjectPreviews updates subject preview images.
|
||||
func UpdateSubjectPreviews() error {
|
||||
func UpdateSubjectPreviews() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
/* Previous implementation for reference:
|
||||
|
||||
return Db().Table(entity.Subject{}.TableName()).
|
||||
|
@ -113,7 +169,7 @@ func UpdateSubjectPreviews() error {
|
|||
WHERE thumb_src='' AND deleted_at IS NULL`)).
|
||||
Error */
|
||||
|
||||
return Db().Table(entity.Subject{}.TableName()).
|
||||
err = Db().Table(entity.Subject{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr("(SELECT m.file_hash FROM "+
|
||||
fmt.Sprintf(
|
||||
"%s m WHERE m.subject_uid = %s.subject_uid AND m.subject_src = 'manual' ",
|
||||
|
@ -122,6 +178,10 @@ func UpdateSubjectPreviews() error {
|
|||
` AND m.file_hash <> '' ORDER BY m.size DESC LIMIT 1)
|
||||
WHERE thumb_src='' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
|
||||
log.Debugf("subjects: updating previews completed in %s", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdatePreviews updates album, labels, and subject preview images.
|
||||
|
@ -131,11 +191,16 @@ func UpdatePreviews() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
// Update Labels, and Categories.
|
||||
// Update Labels.
|
||||
if err = UpdateLabelPreviews(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update Categories.
|
||||
if err = UpdateCategoryPreviews(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update Subjects.
|
||||
if err = UpdateSubjectPreviews(); err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in a new issue