Albums: Implement year filter work for all types except states #353

States do not have an explicit year, so they cannot be filtered at this
time. If needed, a special query for the contained pictures could be
implemented later on. Select may also need changes to work with SQLite.

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2023-01-02 16:17:59 +01:00
parent b456c98c66
commit e94cf7af2c
5 changed files with 35 additions and 18 deletions

View file

@ -47,6 +47,7 @@
<v-flex xs12 sm4 pa-2 class="p-year-select">
<v-select :value="filter.year"
:label="$gettext('Year')"
:disabled="context === 'state'"
flat solo hide-details
color="secondary-dark"
item-value="value"
@ -268,7 +269,7 @@ export default {
const order = this.sortOrder();
const q = query["q"] ? query["q"] : "";
const category = query["category"] ? query["category"] : "";
const year = query['year'] ? parseInt(query['year']) : 0;
const year = query['year'] ? parseInt(query['year']) : "";
const filter = {q, category, order, year};
const settings = {};
const features = this.$config.settings().features;
@ -316,7 +317,7 @@ export default {
},
model: new Album(false),
all: {
years: [{value: 0, text: this.$gettext("All Years")}],
years: [{value: "", text: this.$gettext("All Years")}],
},
options: {
'sorting': [
@ -353,7 +354,7 @@ export default {
this.q = query["q"] ? query["q"] : "";
this.filter.q = this.q;
this.filter.category = query["category"] ? query["category"] : "";
this.filter.year = query['year'] ? parseInt(query['year']) : 0;
this.filter.year = query['year'] ? parseInt(query['year']) : "";
this.filter.order = this.sortOrder();
this.search();

View file

@ -10,9 +10,9 @@ type SearchAlbums struct {
Slug string `form:"slug"`
Title string `form:"title"`
Country string `json:"country"`
Year int `json:"year"`
Month int `json:"month"`
Day int `json:"day"`
Year string `form:"year" example:"year:1990|2003" notes:"Year Number, OR search with |"`
Month string `form:"month" example:"month:7|10" notes:"Month (1-12), OR search with |"`
Day string `form:"day" example:"day:3|13" notes:"Day of Month (1-31), OR search with |"`
Favorite bool `form:"favorite"`
Public bool `form:"public"`
Private bool `form:"private"`

View file

@ -14,7 +14,7 @@ func TestAlbumSearchForm(t *testing.T) {
func TestParseQueryStringAlbum(t *testing.T) {
t.Run("valid query", func(t *testing.T) {
form := &SearchAlbums{Query: "slug:album1 favorite:true"}
form := &SearchAlbums{Query: "slug:album1 favorite:true", Year: "2020"}
err := form.ParseQueryString()
@ -26,6 +26,7 @@ func TestParseQueryStringAlbum(t *testing.T) {
assert.Equal(t, "album1", form.Slug)
assert.Equal(t, true, form.Favorite)
assert.Equal(t, "2020", form.Year)
assert.Equal(t, 0, form.Count)
})
t.Run("valid query 2", func(t *testing.T) {
@ -41,12 +42,13 @@ func TestParseQueryStringAlbum(t *testing.T) {
assert.Equal(t, "album1", form.Title)
assert.Equal(t, false, form.Favorite)
assert.Equal(t, "", form.Year)
assert.Equal(t, 0, form.Offset)
assert.Equal(t, "", form.Order)
assert.Equal(t, "query text", form.Query)
})
t.Run("valid query with umlauts", func(t *testing.T) {
form := &SearchAlbums{Query: "q:\"tübingen\""}
form := &SearchAlbums{Query: "q:\"tübingen\" year:1999"}
err := form.ParseQueryString()
@ -57,6 +59,7 @@ func TestParseQueryStringAlbum(t *testing.T) {
}
assert.Equal(t, "tübingen", form.Query)
assert.Equal(t, "1999", form.Year)
})
t.Run("query for invalid filter", func(t *testing.T) {
form := &SearchAlbums{Query: "xxx:false"}

View file

@ -5,11 +5,12 @@ import (
"time"
"github.com/dustin/go-humanize/english"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/internal/acl"
"github.com/photoprism/photoprism/internal/entity"
"github.com/photoprism/photoprism/internal/form"
"github.com/photoprism/photoprism/pkg/rnd"
"github.com/photoprism/photoprism/pkg/txt"
)
@ -169,20 +170,32 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
s = s.Where("albums.album_country IN (?)", strings.Split(f.Country, txt.Or))
}
// Favorites only?
if f.Favorite {
s = s.Where("albums.album_favorite = 1")
}
if (f.Year > 0 && f.Year <= txt.YearMax) || f.Year == entity.UnknownYear {
s = s.Where("albums.album_year = ?", f.Year)
// Filter by year?
if txt.NotEmpty(f.Year) {
// Filter by the pictures included if it is a manually managed album, as these do not have an explicit
// year assigned to them, unlike calendar albums and moments for example.
if f.Type == entity.AlbumDefault {
s = s.Where("? OR albums.album_uid IN (SELECT DISTINCT pay.album_uid FROM photos_albums pay "+
"JOIN photos py ON pay.photo_uid = py.photo_uid WHERE py.photo_year IN (?) AND pay.hidden = 0 AND pay.missing = 0)",
gorm.Expr(AnyInt("albums.album_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax)), strings.Split(f.Year, txt.Or))
} else {
s = s.Where(AnyInt("albums.album_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax))
}
}
if (f.Month >= txt.MonthMin && f.Month <= txt.MonthMax) || f.Month == entity.UnknownMonth {
s = s.Where("albums.album_month = ?", f.Month)
// Filter by month?
if txt.NotEmpty(f.Month) {
s = s.Where(AnyInt("albums.album_month", f.Month, txt.Or, entity.UnknownMonth, txt.MonthMax))
}
if (f.Day >= txt.DayMin && f.Month <= txt.DayMax) || f.Day == entity.UnknownDay {
s = s.Where("albums.album_day = ?", f.Day)
// Filter by day?
if txt.NotEmpty(f.Day) {
s = s.Where(AnyInt("albums.album_day", f.Day, txt.Or, entity.UnknownDay, txt.DayMax))
}
// Limit result count.

View file

@ -138,9 +138,9 @@ func TestAlbums(t *testing.T) {
})
t.Run("search for year/month/day", func(t *testing.T) {
f := form.SearchAlbums{
Year: 2021,
Month: 10,
Day: 3,
Year: "2021",
Month: "10",
Day: "3",
Count: 0,
Offset: 0,
Order: "",