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:
parent
b456c98c66
commit
e94cf7af2c
|
@ -47,6 +47,7 @@
|
||||||
<v-flex xs12 sm4 pa-2 class="p-year-select">
|
<v-flex xs12 sm4 pa-2 class="p-year-select">
|
||||||
<v-select :value="filter.year"
|
<v-select :value="filter.year"
|
||||||
:label="$gettext('Year')"
|
:label="$gettext('Year')"
|
||||||
|
:disabled="context === 'state'"
|
||||||
flat solo hide-details
|
flat solo hide-details
|
||||||
color="secondary-dark"
|
color="secondary-dark"
|
||||||
item-value="value"
|
item-value="value"
|
||||||
|
@ -268,7 +269,7 @@ export default {
|
||||||
const order = this.sortOrder();
|
const order = this.sortOrder();
|
||||||
const q = query["q"] ? query["q"] : "";
|
const q = query["q"] ? query["q"] : "";
|
||||||
const category = query["category"] ? query["category"] : "";
|
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 filter = {q, category, order, year};
|
||||||
const settings = {};
|
const settings = {};
|
||||||
const features = this.$config.settings().features;
|
const features = this.$config.settings().features;
|
||||||
|
@ -316,7 +317,7 @@ export default {
|
||||||
},
|
},
|
||||||
model: new Album(false),
|
model: new Album(false),
|
||||||
all: {
|
all: {
|
||||||
years: [{value: 0, text: this.$gettext("All Years")}],
|
years: [{value: "", text: this.$gettext("All Years")}],
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
'sorting': [
|
'sorting': [
|
||||||
|
@ -353,7 +354,7 @@ export default {
|
||||||
this.q = query["q"] ? query["q"] : "";
|
this.q = query["q"] ? query["q"] : "";
|
||||||
this.filter.q = this.q;
|
this.filter.q = this.q;
|
||||||
this.filter.category = query["category"] ? query["category"] : "";
|
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.filter.order = this.sortOrder();
|
||||||
|
|
||||||
this.search();
|
this.search();
|
||||||
|
|
|
@ -10,9 +10,9 @@ type SearchAlbums struct {
|
||||||
Slug string `form:"slug"`
|
Slug string `form:"slug"`
|
||||||
Title string `form:"title"`
|
Title string `form:"title"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
Year int `json:"year"`
|
Year string `form:"year" example:"year:1990|2003" notes:"Year Number, OR search with |"`
|
||||||
Month int `json:"month"`
|
Month string `form:"month" example:"month:7|10" notes:"Month (1-12), OR search with |"`
|
||||||
Day int `json:"day"`
|
Day string `form:"day" example:"day:3|13" notes:"Day of Month (1-31), OR search with |"`
|
||||||
Favorite bool `form:"favorite"`
|
Favorite bool `form:"favorite"`
|
||||||
Public bool `form:"public"`
|
Public bool `form:"public"`
|
||||||
Private bool `form:"private"`
|
Private bool `form:"private"`
|
||||||
|
|
|
@ -14,7 +14,7 @@ func TestAlbumSearchForm(t *testing.T) {
|
||||||
|
|
||||||
func TestParseQueryStringAlbum(t *testing.T) {
|
func TestParseQueryStringAlbum(t *testing.T) {
|
||||||
t.Run("valid query", func(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()
|
err := form.ParseQueryString()
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ func TestParseQueryStringAlbum(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, "album1", form.Slug)
|
assert.Equal(t, "album1", form.Slug)
|
||||||
assert.Equal(t, true, form.Favorite)
|
assert.Equal(t, true, form.Favorite)
|
||||||
|
assert.Equal(t, "2020", form.Year)
|
||||||
assert.Equal(t, 0, form.Count)
|
assert.Equal(t, 0, form.Count)
|
||||||
})
|
})
|
||||||
t.Run("valid query 2", func(t *testing.T) {
|
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, "album1", form.Title)
|
||||||
assert.Equal(t, false, form.Favorite)
|
assert.Equal(t, false, form.Favorite)
|
||||||
|
assert.Equal(t, "", form.Year)
|
||||||
assert.Equal(t, 0, form.Offset)
|
assert.Equal(t, 0, form.Offset)
|
||||||
assert.Equal(t, "", form.Order)
|
assert.Equal(t, "", form.Order)
|
||||||
assert.Equal(t, "query text", form.Query)
|
assert.Equal(t, "query text", form.Query)
|
||||||
})
|
})
|
||||||
t.Run("valid query with umlauts", func(t *testing.T) {
|
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()
|
err := form.ParseQueryString()
|
||||||
|
|
||||||
|
@ -57,6 +59,7 @@ func TestParseQueryStringAlbum(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, "tübingen", form.Query)
|
assert.Equal(t, "tübingen", form.Query)
|
||||||
|
assert.Equal(t, "1999", form.Year)
|
||||||
})
|
})
|
||||||
t.Run("query for invalid filter", func(t *testing.T) {
|
t.Run("query for invalid filter", func(t *testing.T) {
|
||||||
form := &SearchAlbums{Query: "xxx:false"}
|
form := &SearchAlbums{Query: "xxx:false"}
|
||||||
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dustin/go-humanize/english"
|
"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/acl"
|
||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
"github.com/photoprism/photoprism/internal/form"
|
"github.com/photoprism/photoprism/internal/form"
|
||||||
|
"github.com/photoprism/photoprism/pkg/rnd"
|
||||||
"github.com/photoprism/photoprism/pkg/txt"
|
"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))
|
s = s.Where("albums.album_country IN (?)", strings.Split(f.Country, txt.Or))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Favorites only?
|
||||||
if f.Favorite {
|
if f.Favorite {
|
||||||
s = s.Where("albums.album_favorite = 1")
|
s = s.Where("albums.album_favorite = 1")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f.Year > 0 && f.Year <= txt.YearMax) || f.Year == entity.UnknownYear {
|
// Filter by year?
|
||||||
s = s.Where("albums.album_year = ?", f.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 {
|
// Filter by month?
|
||||||
s = s.Where("albums.album_month = ?", f.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 {
|
// Filter by day?
|
||||||
s = s.Where("albums.album_day = ?", f.Day)
|
if txt.NotEmpty(f.Day) {
|
||||||
|
s = s.Where(AnyInt("albums.album_day", f.Day, txt.Or, entity.UnknownDay, txt.DayMax))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit result count.
|
// Limit result count.
|
||||||
|
|
|
@ -138,9 +138,9 @@ func TestAlbums(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("search for year/month/day", func(t *testing.T) {
|
t.Run("search for year/month/day", func(t *testing.T) {
|
||||||
f := form.SearchAlbums{
|
f := form.SearchAlbums{
|
||||||
Year: 2021,
|
Year: "2021",
|
||||||
Month: 10,
|
Month: "10",
|
||||||
Day: 3,
|
Day: "3",
|
||||||
Count: 0,
|
Count: 0,
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
Order: "",
|
Order: "",
|
||||||
|
|
Loading…
Reference in a new issue