Backend: Update label photo count and refactor entity fixtures
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
406737e180
commit
8ccaaff4e5
|
@ -131,15 +131,16 @@ func (c *Config) ClientConfig() ClientConfig {
|
|||
Take(&position)
|
||||
|
||||
var count = struct {
|
||||
Photos uint `json:"photos"`
|
||||
Hidden uint `json:"hidden"`
|
||||
Favorites uint `json:"favorites"`
|
||||
Private uint `json:"private"`
|
||||
Stories uint `json:"stories"`
|
||||
Labels uint `json:"labels"`
|
||||
Albums uint `json:"albums"`
|
||||
Countries uint `json:"countries"`
|
||||
Places uint `json:"places"`
|
||||
Photos uint `json:"photos"`
|
||||
Hidden uint `json:"hidden"`
|
||||
Favorites uint `json:"favorites"`
|
||||
Private uint `json:"private"`
|
||||
Stories uint `json:"stories"`
|
||||
Albums uint `json:"albums"`
|
||||
Countries uint `json:"countries"`
|
||||
Places uint `json:"places"`
|
||||
Labels uint `json:"labels"`
|
||||
LabelMaxPhotos uint `json:"labelMaxPhotos"`
|
||||
}{}
|
||||
|
||||
db.Table("photos").
|
||||
|
@ -148,8 +149,10 @@ func (c *Config) ClientConfig() ClientConfig {
|
|||
Take(&count)
|
||||
|
||||
db.Table("labels").
|
||||
Select("COUNT(*) AS labels").
|
||||
Where("(label_priority >= 0 || label_favorite = 1) && deleted_at IS NULL").
|
||||
Select("MAX(photo_count) as label_max_photos, COUNT(*) AS labels").
|
||||
Where("photo_count > 0").
|
||||
Where("deleted_at IS NULL").
|
||||
Where("(label_priority >= 0 || label_favorite = 1)").
|
||||
Take(&count)
|
||||
|
||||
db.Table("albums").
|
||||
|
|
|
@ -5,7 +5,9 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var AccountFixtures = map[string]Account{
|
||||
type AccountMap map[string]Account
|
||||
|
||||
var AccountFixtures = AccountMap{
|
||||
"webdav-dummy": {
|
||||
ID: 1000000,
|
||||
AccName: "Test Account",
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var AlbumFixtures = map[string]Album{
|
||||
type AlbumMap map[string]Album
|
||||
|
||||
var AlbumFixtures = AlbumMap{
|
||||
"christmas2030": {
|
||||
ID: 1000000,
|
||||
CoverUUID: "",
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var CameraFixtures = map[string]Camera{
|
||||
type CameraMap map[string]Camera
|
||||
|
||||
var CameraFixtures = CameraMap{
|
||||
"apple-iphone-se": {
|
||||
ID: 1000000,
|
||||
CameraSlug: "apple-iphone-se",
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package entity
|
||||
|
||||
var CategoryFixtures = map[string]Category{
|
||||
"1": {
|
||||
"flower_landscape": {
|
||||
LabelID: 1000001,
|
||||
Label: LabelFixtures.Pointer("flower"),
|
||||
CategoryID: 1000000,
|
||||
Label: &LabelFixtureFlower,
|
||||
Category: &LabelFixtureLandscape,
|
||||
Category: LabelFixtures.Pointer("landscape"),
|
||||
},
|
||||
}
|
||||
|
||||
// CreateCategoryFixtures inserts known entities into the database for testing.
|
||||
func CreateCategoryFixtures() {
|
||||
for _, entity := range KeywordFixtures {
|
||||
for _, entity := range CategoryFixtures {
|
||||
Db().Create(&entity)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package entity
|
||||
|
||||
var CountryFixtures = map[string]Country{
|
||||
type CountryMap map[string]Country
|
||||
|
||||
var CountryFixtures = CountryMap{
|
||||
"apple-iphone-se": {
|
||||
ID: "de",
|
||||
CountrySlug: "germany",
|
||||
|
|
|
@ -1,6 +1,26 @@
|
|||
package entity
|
||||
|
||||
var DescriptionFixtures = map[string]Description{
|
||||
type DescriptionMap map[string]Description
|
||||
|
||||
func (m DescriptionMap) Get(name string, photoId uint) Description {
|
||||
if result, ok := m[name]; ok {
|
||||
result.PhotoID = photoId
|
||||
return result
|
||||
}
|
||||
|
||||
return Description{PhotoID: photoId}
|
||||
}
|
||||
|
||||
func (m DescriptionMap) Pointer(name string, photoId uint) *Description {
|
||||
if result, ok := m[name]; ok {
|
||||
result.PhotoID = photoId
|
||||
return &result
|
||||
}
|
||||
|
||||
return &Description{PhotoID: photoId}
|
||||
}
|
||||
|
||||
var DescriptionFixtures = DescriptionMap{
|
||||
"lake": {
|
||||
PhotoID: 1000000,
|
||||
PhotoDescription: "photo description",
|
||||
|
@ -12,11 +32,3 @@ var DescriptionFixtures = map[string]Description{
|
|||
PhotoLicense: "MIT",
|
||||
},
|
||||
}
|
||||
var DescriptionFixtureLake = DescriptionFixtures["lake"]
|
||||
|
||||
// CreateDescriptionFixtures inserts known entities into the database for testing.
|
||||
func CreateDescriptionFixtures() {
|
||||
for _, entity := range DescriptionFixtures {
|
||||
Db().Create(&entity)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
var FileFixtures = map[string]File{
|
||||
"exampleFileName.jpg": {
|
||||
ID: 1000000,
|
||||
Photo: &PhotoFixture19800101_000002_D640C559,
|
||||
Photo: PhotoFixtures.Pointer("19800101_000002_D640C559"),
|
||||
PhotoID: 1000000,
|
||||
PhotoUUID: "pt9jtdre2lvl0yh7",
|
||||
FileUUID: "ft8es39w45bnlqdw",
|
||||
|
@ -46,7 +46,7 @@ var FileFixtures = map[string]File{
|
|||
},
|
||||
"exampleDNGFile.dng": {
|
||||
ID: 1000001,
|
||||
Photo: &PhotoFixturePhoto01,
|
||||
Photo: PhotoFixtures.Pointer("Photo01"),
|
||||
PhotoID: 1000001,
|
||||
PhotoUUID: "pt9jtdre2lvl0yh8",
|
||||
FileUUID: "ft9es39w45bnlqdw",
|
||||
|
@ -85,7 +85,7 @@ var FileFixtures = map[string]File{
|
|||
},
|
||||
"exampleXmpFile.xmp": {
|
||||
ID: 1000002,
|
||||
Photo: &PhotoFixturePhoto01,
|
||||
Photo: PhotoFixtures.Pointer("Photo01"),
|
||||
PhotoID: 1000001,
|
||||
PhotoUUID: "pt9jtdre2lvl0yh8",
|
||||
FileUUID: "ft1es39w45bnlqdw",
|
||||
|
@ -124,7 +124,7 @@ var FileFixtures = map[string]File{
|
|||
},
|
||||
"bridge.jpg": {
|
||||
ID: 1000003,
|
||||
Photo: &PhotoFixturePhoto04,
|
||||
Photo: PhotoFixtures.Pointer("Photo04"),
|
||||
PhotoID: 1000004,
|
||||
PhotoUUID: "pt9jtdre2lvl0y11",
|
||||
FileUUID: "ft2es39w45bnlqdw",
|
||||
|
@ -163,7 +163,7 @@ var FileFixtures = map[string]File{
|
|||
},
|
||||
"reunion.jpg": {
|
||||
ID: 1000004,
|
||||
Photo: &PhotoFixturePhoto05,
|
||||
Photo: PhotoFixtures.Pointer("Photo05"),
|
||||
PhotoID: 1000005,
|
||||
PhotoUUID: "pt9jtdre2lvl0y12",
|
||||
FileUUID: "ft3es39w45bnlqdw",
|
||||
|
|
|
@ -14,8 +14,6 @@ func CreateTestFixtures() {
|
|||
CreateKeywordFixtures()
|
||||
CreatePhotoKeywordFixtures()
|
||||
CreateCategoryFixtures()
|
||||
CreatePhotoLabelFixtures()
|
||||
CreateLocationFixtures()
|
||||
CreatePlaceFixtures()
|
||||
CreateDescriptionFixtures()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package entity
|
||||
|
||||
var KeywordFixtures = map[string]Keyword{
|
||||
type KeywordMap map[string]Keyword
|
||||
|
||||
var KeywordFixtures = KeywordMap{
|
||||
"bridge": {
|
||||
ID: 1000000,
|
||||
Keyword: "bridge",
|
||||
|
|
|
@ -23,7 +23,7 @@ type Label struct {
|
|||
LabelNotes string `gorm:"type:text;"`
|
||||
LabelCategories []*Label `gorm:"many2many:categories;association_jointable_foreignkey:category_id"`
|
||||
Links []Link `gorm:"foreignkey:ShareUUID;association_foreignkey:LabelUUID"`
|
||||
PhotoCount int
|
||||
PhotoCount int `gorm:"default:1"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time `sql:"index"`
|
||||
|
@ -55,6 +55,7 @@ func NewLabel(name string, priority int) *Label {
|
|||
CustomSlug: labelSlug,
|
||||
LabelName: labelName,
|
||||
LabelPriority: priority,
|
||||
PhotoCount: 1,
|
||||
}
|
||||
|
||||
return result
|
||||
|
|
|
@ -4,7 +4,34 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var LabelFixtures = map[string]Label{
|
||||
type LabelMap map[string]Label
|
||||
|
||||
func (m LabelMap) Get(name string) Label {
|
||||
if result, ok := m[name]; ok {
|
||||
return result
|
||||
}
|
||||
|
||||
return *NewLabel(name, 0)
|
||||
}
|
||||
|
||||
func (m LabelMap) Pointer(name string) *Label {
|
||||
if result, ok := m[name]; ok {
|
||||
return &result
|
||||
}
|
||||
|
||||
return NewLabel(name, 0)
|
||||
}
|
||||
|
||||
func (m LabelMap) PhotoLabel(photoId uint, labelName string, uncertainty int, source string) PhotoLabel {
|
||||
label := m.Get(labelName)
|
||||
|
||||
photoLabel := NewPhotoLabel(photoId, label.ID, uncertainty, source)
|
||||
photoLabel.Label = &label
|
||||
|
||||
return *photoLabel
|
||||
}
|
||||
|
||||
var LabelFixtures = LabelMap{
|
||||
"landscape": {
|
||||
ID: 1000000,
|
||||
LabelUUID: "lt9k3pw1wowuy3c2",
|
||||
|
@ -15,6 +42,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: true,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 1,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -32,6 +60,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: true,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 2,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -49,6 +78,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: false,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 3,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -66,6 +96,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: true,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 4,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -83,6 +114,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: true,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 5,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -100,6 +132,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: false,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 1,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -117,6 +150,7 @@ var LabelFixtures = map[string]Label{
|
|||
LabelFavorite: false,
|
||||
LabelDescription: "",
|
||||
LabelNotes: "",
|
||||
PhotoCount: 1,
|
||||
LabelCategories: []*Label{},
|
||||
Links: []Link{},
|
||||
CreatedAt: time.Now(),
|
||||
|
@ -126,12 +160,6 @@ var LabelFixtures = map[string]Label{
|
|||
},
|
||||
}
|
||||
|
||||
var LabelFixtureLandscape = LabelFixtures["landscape"]
|
||||
var LabelFixtureFlower = LabelFixtures["flower"]
|
||||
var LabelFixtureCake = LabelFixtures["cake"]
|
||||
var LabelFixtureCow = LabelFixtures["cow"]
|
||||
var LabelFixtureUpdatePhotoLabel = LabelFixtures["updatePhotoLabel"]
|
||||
|
||||
// CreateLabelFixtures inserts known entities into the database for testing.
|
||||
func CreateLabelFixtures() {
|
||||
for _, entity := range LabelFixtures {
|
||||
|
|
|
@ -53,7 +53,8 @@ func TestLabel_SetName(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLabel_FirstOrCreate(t *testing.T) {
|
||||
r := LabelFixtureFlower.FirstOrCreate()
|
||||
label := LabelFixtures.Get("flower")
|
||||
r := label.FirstOrCreate()
|
||||
assert.Equal(t, "Flower", r.LabelName)
|
||||
assert.Equal(t, "flower", r.LabelSlug)
|
||||
}
|
||||
|
@ -100,7 +101,7 @@ func TestLabel_Update(t *testing.T) {
|
|||
})
|
||||
t.Run("update name and Categories", func(t *testing.T) {
|
||||
classifyLabel := &classify.Label{Name: "classify", Uncertainty: 30, Source: "manual", Priority: 5, Categories: []string{"flower", "plant"}}
|
||||
Label := &Label{LabelName: "label34", LabelSlug: "labelslug2", CustomSlug: "labelslug2", LabelPriority: 5, LabelCategories: []*Label{&LabelFixtureFlower}}
|
||||
Label := &Label{LabelName: "label34", LabelSlug: "labelslug2", CustomSlug: "labelslug2", LabelPriority: 5, LabelCategories: []*Label{LabelFixtures.Pointer("flower")}}
|
||||
|
||||
assert.Equal(t, 5, Label.LabelPriority)
|
||||
assert.Equal(t, "labelslug2", Label.LabelSlug)
|
||||
|
|
|
@ -4,7 +4,9 @@ import "time"
|
|||
|
||||
var date = time.Date(2050, 3, 6, 2, 6, 51, 0, time.UTC)
|
||||
|
||||
var LinkFixtures = map[string]Link{
|
||||
type LinkMap map[string]Link
|
||||
|
||||
var LinkFixtures = LinkMap{
|
||||
"1jxf3jfn2k": {
|
||||
LinkToken: "1jxf3jfn2k",
|
||||
LinkPassword: "somepassword",
|
||||
|
|
|
@ -2,21 +2,31 @@ package entity
|
|||
|
||||
import "time"
|
||||
|
||||
var LocationFixtures = map[string]Location{
|
||||
type LocationMap map[string]Location
|
||||
|
||||
var LocationFixtures = LocationMap{
|
||||
"mexico": {
|
||||
ID: "1000000",
|
||||
PlaceID: "1000000",
|
||||
ID: "85d1ea7d382c",
|
||||
PlaceID: PlaceFixtures.Get("teotihuacan").ID,
|
||||
LocName: "Adosada Platform",
|
||||
LocCategory: "tourism",
|
||||
Place: &PlaceFixtureTeotihuacan,
|
||||
Place: PlaceFixtures.Pointer("teotihuacan"),
|
||||
LocSource: "places",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
"caravan park": {
|
||||
ID: "1000001",
|
||||
PlaceID: "",
|
||||
Place: nil,
|
||||
ID: "1ef75a71a36c",
|
||||
PlaceID: "1ef75a71a36c",
|
||||
Place: &Place{
|
||||
ID: "1ef75a71a36",
|
||||
LocLabel: "Mandeni, KwaZulu-Natal, South Africa",
|
||||
LocCity: "Mandeni",
|
||||
LocState: "KwaZulu-Natal",
|
||||
LocCountry: "za",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
LocName: "Lobotes Caravan Park",
|
||||
LocCategory: "camping",
|
||||
LocSource: "manual",
|
||||
|
@ -24,9 +34,9 @@ var LocationFixtures = map[string]Location{
|
|||
UpdatedAt: time.Now(),
|
||||
},
|
||||
"zinkwazi": {
|
||||
ID: "1000002",
|
||||
PlaceID: "",
|
||||
Place: &PlaceFixtureZinkwazi,
|
||||
ID: "1ef744d1e28c",
|
||||
PlaceID: PlaceFixtures.Get("zinkwazi").ID,
|
||||
Place: PlaceFixtures.Pointer("zinkwazi"),
|
||||
LocName: "Zinkwazi Beach",
|
||||
LocCategory: "",
|
||||
LocSource: "places",
|
||||
|
@ -35,10 +45,6 @@ var LocationFixtures = map[string]Location{
|
|||
},
|
||||
}
|
||||
|
||||
var LocationFixtureMexico = LocationFixtures["mexico"]
|
||||
var LocationFixtureCaravanPark = LocationFixtures["caravan park"]
|
||||
var LocationFixtureZinkawzi = LocationFixtures["zinkwazi"]
|
||||
|
||||
// CreateLocationFixtures inserts known entities into the database for testing.
|
||||
func CreateLocationFixtures() {
|
||||
for _, entity := range LocationFixtures {
|
||||
|
|
|
@ -11,7 +11,7 @@ func TestNewLocation(t *testing.T) {
|
|||
l := NewLocation(1, 1)
|
||||
l.LocCategory = "restaurant"
|
||||
l.LocName = "LocationName"
|
||||
l.Place = &PlaceFixtureZinkwazi
|
||||
l.Place = PlaceFixtures.Pointer("zinkwazi")
|
||||
l.LocSource = "places"
|
||||
|
||||
assert.Equal(t, "restaurant", l.Category())
|
||||
|
@ -34,19 +34,22 @@ func TestNewLocation(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLocation_Keywords(t *testing.T) {
|
||||
t.Run("location with place", func(t *testing.T) {
|
||||
r := LocationFixtureMexico.Keywords()
|
||||
t.Run("mexico", func(t *testing.T) {
|
||||
m := LocationFixtures["mexico"]
|
||||
r := m.Keywords()
|
||||
assert.Equal(t, []string{"adosada", "ancient", "mexico", "platform", "pyramid", "teotihuacán", "tourism"}, r)
|
||||
})
|
||||
t.Run("location without place", func(t *testing.T) {
|
||||
r := LocationFixtureCaravanPark.Keywords()
|
||||
assert.Nil(t, r)
|
||||
t.Run("caravan park", func(t *testing.T) {
|
||||
m := LocationFixtures["caravan park"]
|
||||
r := m.Keywords()
|
||||
assert.Equal(t, []string{"camping", "caravan", "kwazulu-natal", "lobotes", "mandeni", "park", "south-africa"}, r)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLocation_Find(t *testing.T) {
|
||||
t.Run("place in db", func(t *testing.T) {
|
||||
r := LocationFixtureMexico.Find("")
|
||||
m := LocationFixtures["mexico"]
|
||||
r := m.Find("")
|
||||
assert.Nil(t, r)
|
||||
})
|
||||
t.Run("invalid api", func(t *testing.T) {
|
||||
|
|
|
@ -9,7 +9,7 @@ var PhotoAlbumFixtures = map[string]PhotoAlbum{
|
|||
Order: 0,
|
||||
CreatedAt: time.Date(2020, 3, 6, 2, 6, 51, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 3, 28, 14, 6, 0, 0, time.UTC),
|
||||
Photo: &PhotoFixture19800101_000002_D640C559,
|
||||
Photo: PhotoFixtures.Pointer("19800101_000002_D640C559"),
|
||||
Album: &AlbumFixtureHoliday2030,
|
||||
},
|
||||
"2": {
|
||||
|
@ -18,7 +18,7 @@ var PhotoAlbumFixtures = map[string]PhotoAlbum{
|
|||
Order: 0,
|
||||
CreatedAt: time.Date(2020, 2, 6, 2, 6, 51, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 4, 28, 14, 6, 0, 0, time.UTC),
|
||||
Photo: &PhotoFixturePhoto04,
|
||||
Photo: PhotoFixtures.Pointer("Photo04"),
|
||||
Album: &AlbumFixtureBerlin2019,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -6,7 +6,25 @@ import (
|
|||
|
||||
var editTime = time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
var PhotoFixtures = map[string]Photo{
|
||||
type PhotoMap map[string]Photo
|
||||
|
||||
func (m PhotoMap) Get(name string) Photo {
|
||||
if result, ok := m[name]; ok {
|
||||
return result
|
||||
}
|
||||
|
||||
return Photo{PhotoName: name}
|
||||
}
|
||||
|
||||
func (m PhotoMap) Pointer(name string) *Photo {
|
||||
if result, ok := m[name]; ok {
|
||||
return &result
|
||||
}
|
||||
|
||||
return &Photo{PhotoName: name}
|
||||
}
|
||||
|
||||
var PhotoFixtures = PhotoMap{
|
||||
"19800101_000002_D640C559": {
|
||||
ID: 1000000,
|
||||
PhotoUUID: "pt9jtdre2lvl0yh7",
|
||||
|
@ -40,7 +58,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
PhotoCountry: "zz",
|
||||
PhotoYear: 2790,
|
||||
PhotoMonth: 2,
|
||||
Description: DescriptionFixtureLake,
|
||||
Description: DescriptionFixtures.Get("lake", 1000000),
|
||||
DescriptionSrc: "",
|
||||
Camera: &CameraFixtureEOS6D,
|
||||
Lens: nil,
|
||||
|
@ -50,7 +68,10 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{
|
||||
LabelFixtures.PhotoLabel(1000000, "flower", 38, "image"),
|
||||
LabelFixtures.PhotoLabel(1000000, "cake", 38, "manual"),
|
||||
},
|
||||
CreatedAt: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -148,7 +169,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{LabelFixtures.PhotoLabel(1000002, "cake", 20, "image")},
|
||||
CreatedAt: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -197,7 +218,10 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{
|
||||
LabelFixtures.PhotoLabel(1000003, "cow", 20, "image"),
|
||||
LabelFixtures.PhotoLabel(1000003, "updatePhotoLabel", 20, "manual"),
|
||||
},
|
||||
CreatedAt: time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -246,7 +270,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{LabelFixtures.PhotoLabel(1000004, "batchdelete", 20, "image")},
|
||||
CreatedAt: time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -295,7 +319,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{LabelFixtures.PhotoLabel(1000005, "updateLabel", 20, "image")},
|
||||
CreatedAt: time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -344,7 +368,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{LabelFixtures.PhotoLabel(1000006, "updatePhotoLabel", 20, "image")},
|
||||
CreatedAt: time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -393,7 +417,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{LabelFixtures.PhotoLabel(1000007, "landscape", 20, "image")},
|
||||
CreatedAt: time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: &editTime,
|
||||
|
@ -442,7 +466,7 @@ var PhotoFixtures = map[string]Photo{
|
|||
Keywords: []Keyword{},
|
||||
Albums: []Album{},
|
||||
Files: []File{},
|
||||
Labels: []PhotoLabel{},
|
||||
Labels: []PhotoLabel{LabelFixtures.PhotoLabel(1000008, "landscape", 20, "image")},
|
||||
CreatedAt: time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
UpdatedAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
EditedAt: nil,
|
||||
|
@ -450,15 +474,6 @@ var PhotoFixtures = map[string]Photo{
|
|||
},
|
||||
}
|
||||
|
||||
var PhotoFixture19800101_000002_D640C559 = PhotoFixtures["19800101_000002_D640C559"]
|
||||
var PhotoFixturePhoto04 = PhotoFixtures["Photo04"]
|
||||
var PhotoFixturePhoto01 = PhotoFixtures["Photo01"]
|
||||
var PhotoFixturePhoto05 = PhotoFixtures["Photo05"]
|
||||
var PhotoFixturePhoto03 = PhotoFixtures["Photo03"]
|
||||
var PhotoFixturePhoto06 = PhotoFixtures["Photo06"]
|
||||
var PhotoFixturePhoto07 = PhotoFixtures["Photo07"]
|
||||
var PhotoFixturePhoto08 = PhotoFixtures["Photo08"]
|
||||
|
||||
// CreatePhotoFixtures inserts known entities into the database for testing.
|
||||
func CreatePhotoFixtures() {
|
||||
for _, entity := range PhotoFixtures {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package entity
|
||||
|
||||
var PhotoKeywordFixtures = map[string]PhotoKeyword{
|
||||
type PhotoKeywordMap map[string]PhotoKeyword
|
||||
|
||||
var PhotoKeywordFixtures = PhotoKeywordMap{
|
||||
"1": {
|
||||
PhotoID: 1000004,
|
||||
KeywordID: 1000000,
|
||||
},
|
||||
}
|
||||
|
||||
var PhotoKeywordFixture1 = PhotoKeywordFixtures["1"]
|
||||
|
||||
// CreatePhotoKeywordFixtures inserts known entities into the database for testing.
|
||||
func CreatePhotoKeywordFixtures() {
|
||||
for _, entity := range PhotoKeywordFixtures {
|
||||
|
|
|
@ -22,6 +22,7 @@ func TestPhotoKeyword_TableName(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPhotoKeywords_FirstOrCreate(t *testing.T) {
|
||||
r := PhotoKeywordFixture1.FirstOrCreate()
|
||||
m := PhotoKeywordFixtures["1"]
|
||||
r := m.FirstOrCreate()
|
||||
assert.Equal(t, uint(0xf4244), r.PhotoID)
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package entity
|
||||
|
||||
var PhotoLabelFixtures = map[string]PhotoLabel{
|
||||
"1": {
|
||||
PhotoID: 1000000,
|
||||
LabelID: 1000001,
|
||||
LabelSrc: "image",
|
||||
Uncertainty: 38,
|
||||
Photo: &PhotoFixture19800101_000002_D640C559,
|
||||
Label: &LabelFixtureFlower,
|
||||
},
|
||||
"2": {
|
||||
PhotoID: 1000000,
|
||||
LabelID: 1000002,
|
||||
LabelSrc: "manual",
|
||||
Uncertainty: 38,
|
||||
Photo: &PhotoFixture19800101_000002_D640C559,
|
||||
Label: &LabelFixtureCake,
|
||||
},
|
||||
"3": {
|
||||
PhotoID: 1000003,
|
||||
LabelID: 1000006,
|
||||
LabelSrc: "manual",
|
||||
Uncertainty: 20,
|
||||
Photo: &PhotoFixturePhoto03,
|
||||
Label: &LabelFixtureUpdatePhotoLabel,
|
||||
},
|
||||
}
|
||||
|
||||
var PhotoLabelFixture1 = PhotoLabelFixtures["1"]
|
||||
|
||||
// CreatePhotoLabelFixtures inserts known entities into the database for testing.
|
||||
func CreatePhotoLabelFixtures() {
|
||||
for _, entity := range PhotoLabelFixtures {
|
||||
Db().Create(&entity)
|
||||
}
|
||||
}
|
|
@ -23,13 +23,15 @@ func TestPhotoLabel_TableName(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPhotoLabel_FirstOrCreate(t *testing.T) {
|
||||
r := PhotoLabelFixture1.FirstOrCreate()
|
||||
assert.Equal(t, uint(0xf4240), r.PhotoID)
|
||||
pl := LabelFixtures.PhotoLabel(1000000, "flower", 38, "image")
|
||||
r := pl.FirstOrCreate()
|
||||
assert.Equal(t, uint(1000000), r.PhotoID)
|
||||
}
|
||||
|
||||
func TestPhotoLabel_ClassifyLabel(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
r := PhotoLabelFixture1.ClassifyLabel()
|
||||
pl := LabelFixtures.PhotoLabel(1000000, "flower", 38, "image")
|
||||
r := pl.ClassifyLabel()
|
||||
assert.Equal(t, "Flower", r.Name)
|
||||
assert.Equal(t, 38, r.Uncertainty)
|
||||
assert.Equal(t, "image", r.Source)
|
||||
|
|
|
@ -7,15 +7,15 @@ import (
|
|||
|
||||
func TestPhoto_QualityScore(t *testing.T) {
|
||||
t.Run("PhotoFixture19800101_000002_D640C559", func(t *testing.T) {
|
||||
assert.Equal(t, 4, PhotoFixture19800101_000002_D640C559.QualityScore())
|
||||
assert.Equal(t, 4, PhotoFixtures.Pointer("19800101_000002_D640C559").QualityScore())
|
||||
})
|
||||
t.Run("PhotoFixturePhoto01 - favorite true - taken at before 2008", func(t *testing.T) {
|
||||
assert.Equal(t, 7, PhotoFixturePhoto01.QualityScore())
|
||||
assert.Equal(t, 7, PhotoFixtures.Pointer("Photo01").QualityScore())
|
||||
})
|
||||
t.Run("PhotoFixturePhoto06 - taken at after 2012 - resolution 2", func(t *testing.T) {
|
||||
assert.Equal(t, 4, PhotoFixturePhoto06.QualityScore())
|
||||
assert.Equal(t, 4, PhotoFixtures.Pointer("Photo06").QualityScore())
|
||||
})
|
||||
t.Run("PhotoFixturePhoto07 - score < 3 bit edited", func(t *testing.T) {
|
||||
assert.Equal(t, 3, PhotoFixturePhoto07.QualityScore())
|
||||
assert.Equal(t, 3, PhotoFixtures.Pointer("Photo07").QualityScore())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ func TestPhoto_Save(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("existing photo", func(t *testing.T) {
|
||||
err := PhotoFixture19800101_000002_D640C559.Save()
|
||||
m := PhotoFixtures.Get("19800101_000002_D640C559")
|
||||
err := m.Save()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -100,13 +101,13 @@ func TestPhoto_Save(t *testing.T) {
|
|||
|
||||
func TestPhoto_ClassifyLabels(t *testing.T) {
|
||||
t.Run("new photo", func(t *testing.T) {
|
||||
m := PhotoFixturePhoto01
|
||||
m := PhotoFixtures.Get("Photo01")
|
||||
Db().Set("gorm:auto_preload", true).Model(&m).Related(&m.Labels)
|
||||
labels := m.ClassifyLabels()
|
||||
assert.Empty(t, labels)
|
||||
})
|
||||
t.Run("existing photo", func(t *testing.T) {
|
||||
m := PhotoFixture19800101_000002_D640C559
|
||||
m := PhotoFixtures.Get("19800101_000002_D640C559")
|
||||
Db().Set("gorm:auto_preload", true).Model(&m).Related(&m.Labels)
|
||||
labels := m.ClassifyLabels()
|
||||
assert.LessOrEqual(t, 2, labels.Len())
|
||||
|
|
|
@ -2,9 +2,27 @@ package entity
|
|||
|
||||
import "time"
|
||||
|
||||
var PlaceFixtures = map[string]Place{
|
||||
type PlacesMap map[string]Place
|
||||
|
||||
func (m PlacesMap) Get(name string) Place {
|
||||
if result, ok := m[name]; ok {
|
||||
return result
|
||||
}
|
||||
|
||||
return UnknownPlace
|
||||
}
|
||||
|
||||
func (m PlacesMap) Pointer(name string) *Place {
|
||||
if result, ok := m[name]; ok {
|
||||
return &result
|
||||
}
|
||||
|
||||
return &UnknownPlace
|
||||
}
|
||||
|
||||
var PlaceFixtures = PlacesMap{
|
||||
"teotihuacan": {
|
||||
ID: "1000000",
|
||||
ID: "85d1ea7d382c",
|
||||
LocLabel: "Teotihuacán, Mexico, Mexico",
|
||||
LocCity: "Teotihuacán",
|
||||
LocState: "Mexico",
|
||||
|
@ -12,11 +30,12 @@ var PlaceFixtures = map[string]Place{
|
|||
LocKeywords: "ancient, pyramid",
|
||||
LocNotes: "",
|
||||
LocFavorite: false,
|
||||
PhotoCount: 1,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
"zinkwazi": {
|
||||
ID: "1000001",
|
||||
ID: "1ef744d1e28c",
|
||||
LocLabel: "KwaDukuza, KwaZulu-Natal, South Africa",
|
||||
LocCity: "KwaDukuza",
|
||||
LocState: "KwaZulu-Natal",
|
||||
|
@ -24,14 +43,12 @@ var PlaceFixtures = map[string]Place{
|
|||
LocKeywords: "",
|
||||
LocNotes: "africa",
|
||||
LocFavorite: true,
|
||||
PhotoCount: 2,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
|
||||
var PlaceFixtureTeotihuacan = PlaceFixtures["teotihuacan"]
|
||||
var PlaceFixtureZinkwazi = PlaceFixtures["zinkwazi"]
|
||||
|
||||
// CreatePlaceFixtures inserts known entities into the database for testing.
|
||||
func CreatePlaceFixtures() {
|
||||
for _, entity := range PlaceFixtures {
|
|
@ -14,22 +14,36 @@ func TestCreateUnknownPlace(t *testing.T) {
|
|||
|
||||
func TestFindPlaceByLabel(t *testing.T) {
|
||||
t.Run("find by id", func(t *testing.T) {
|
||||
r := FindPlaceByLabel("1000000", "")
|
||||
r := FindPlaceByLabel("85d1ea7d382c", "")
|
||||
|
||||
if r == nil {
|
||||
t.Fatal("result should not be nil")
|
||||
}
|
||||
|
||||
assert.Equal(t, "mx", r.LocCountry)
|
||||
})
|
||||
t.Run("find by label", func(t *testing.T) {
|
||||
r := FindPlaceByLabel("", "KwaDukuza, KwaZulu-Natal, South Africa")
|
||||
|
||||
if r == nil {
|
||||
t.Fatal("result should not be nil")
|
||||
}
|
||||
|
||||
assert.Equal(t, "za", r.LocCountry)
|
||||
})
|
||||
t.Run("not matching", func(t *testing.T) {
|
||||
r := FindPlaceByLabel("111", "xxx")
|
||||
assert.Nil(t, r)
|
||||
|
||||
if r != nil {
|
||||
t.Fatal("result should be nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPlace_Find(t *testing.T) {
|
||||
t.Run("record exists", func(t *testing.T) {
|
||||
r := PlaceFixtureTeotihuacan.Find()
|
||||
m := PlaceFixtures.Get("teotihuacan")
|
||||
r := m.Find()
|
||||
assert.Nil(t, r)
|
||||
})
|
||||
t.Run("record does not exist", func(t *testing.T) {
|
||||
|
@ -53,6 +67,7 @@ func TestPlace_Find(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPlace_FirstOrCreate(t *testing.T) {
|
||||
r := PlaceFixtureZinkwazi.FirstOrCreate()
|
||||
m := PlaceFixtures.Pointer("zinkwazi")
|
||||
r := m.FirstOrCreate()
|
||||
assert.Equal(t, "KwaDukuza, KwaZulu-Natal, South Africa", r.LocLabel)
|
||||
}
|
||||
|
|
72
internal/query/label.go
Normal file
72
internal/query/label.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
)
|
||||
|
||||
// PhotoLabel returns a photo label entity if exists.
|
||||
func PhotoLabel(photoID, labelID uint) (label entity.PhotoLabel, err error) {
|
||||
if err := Db().Where("photo_id = ? AND label_id = ?", photoID, labelID).Preload("Photo").Preload("Label").First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// LabelBySlug returns a Label based on the slug name.
|
||||
func LabelBySlug(labelSlug string) (label entity.Label, err error) {
|
||||
if err := Db().Where("label_slug = ? OR custom_slug = ?", labelSlug, labelSlug).Preload("Links").First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// LabelByUUID returns a Label based on the label UUID.
|
||||
func LabelByUUID(labelUUID string) (label entity.Label, err error) {
|
||||
if err := Db().Where("label_uuid = ?", labelUUID).Preload("Links").First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// LabelThumbBySlug returns a label preview file based on the slug name.
|
||||
func LabelThumbBySlug(labelSlug string) (file entity.File, err error) {
|
||||
if err := Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN labels ON labels.label_slug = ?", labelSlug).
|
||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||
First(&file).Error; err != nil {
|
||||
return file, err
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// LabelThumbByUUID returns a label preview file based on the label UUID.
|
||||
func LabelThumbByUUID(labelUUID string) (file entity.File, err error) {
|
||||
// Search matching label
|
||||
err = Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN labels ON labels.label_uuid = ?", labelUUID).
|
||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||
First(&file).Error
|
||||
|
||||
if err == nil {
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// If failed, search for category instead
|
||||
err = Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN photos_labels ON photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||
Joins("JOIN categories c ON photos_labels.label_id = c.label_id").
|
||||
Joins("JOIN labels ON c.category_id = labels.id AND labels.label_uuid= ?", labelUUID).
|
||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||
First(&file).Error
|
||||
|
||||
return file, err
|
||||
}
|
|
@ -16,8 +16,8 @@ type LabelResult struct {
|
|||
CustomSlug string
|
||||
LabelName string
|
||||
LabelPriority int
|
||||
LabelCount int
|
||||
LabelFavorite bool
|
||||
LabelDescription string
|
||||
LabelNotes string
|
||||
PhotoCount int
|
||||
}
|
||||
|
|
83
internal/query/label_test.go
Normal file
83
internal/query/label_test.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLabelBySlug(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
label, err := LabelBySlug("flower")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "Flower", label.LabelName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
label, err := LabelBySlug("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
assert.Empty(t, label.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelByUUID(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
label, err := LabelByUUID("lt9k3pw1wowuy3c5")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "COW", label.LabelName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
label, err := LabelByUUID("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
assert.Empty(t, label.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelThumbBySlug(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := LabelThumbBySlug("flower")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := LabelThumbBySlug("cow")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelThumbByUUID(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := LabelThumbByUUID("lt9k3pw1wowuy3c4")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := LabelThumbByUUID("14")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
})
|
||||
}
|
|
@ -12,73 +12,6 @@ import (
|
|||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
// PhotoLabel returns a photo label entity if exists.
|
||||
func PhotoLabel(photoID, labelID uint) (label entity.PhotoLabel, err error) {
|
||||
if err := Db().Where("photo_id = ? AND label_id = ?", photoID, labelID).Preload("Photo").Preload("Label").First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// LabelBySlug returns a Label based on the slug name.
|
||||
func LabelBySlug(labelSlug string) (label entity.Label, err error) {
|
||||
if err := Db().Where("label_slug = ? OR custom_slug = ?", labelSlug, labelSlug).Preload("Links").First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// LabelByUUID returns a Label based on the label UUID.
|
||||
func LabelByUUID(labelUUID string) (label entity.Label, err error) {
|
||||
if err := Db().Where("label_uuid = ?", labelUUID).Preload("Links").First(&label).Error; err != nil {
|
||||
return label, err
|
||||
}
|
||||
|
||||
return label, nil
|
||||
}
|
||||
|
||||
// LabelThumbBySlug returns a label preview file based on the slug name.
|
||||
func LabelThumbBySlug(labelSlug string) (file entity.File, err error) {
|
||||
if err := Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN labels ON labels.label_slug = ?", labelSlug).
|
||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||
First(&file).Error; err != nil {
|
||||
return file, err
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// LabelThumbByUUID returns a label preview file based on the label UUID.
|
||||
func LabelThumbByUUID(labelUUID string) (file entity.File, err error) {
|
||||
// Search matching label
|
||||
err = Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN labels ON labels.label_uuid = ?", labelUUID).
|
||||
Joins("JOIN photos_labels ON photos_labels.label_id = labels.id AND photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||
First(&file).Error
|
||||
|
||||
if err == nil {
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// If failed, search for category instead
|
||||
err = Db().Where("files.file_primary AND files.deleted_at IS NULL").
|
||||
Joins("JOIN photos_labels ON photos_labels.photo_id = files.photo_id AND photos_labels.uncertainty < 100").
|
||||
Joins("JOIN categories c ON photos_labels.label_id = c.label_id").
|
||||
Joins("JOIN labels ON c.category_id = labels.id AND labels.label_uuid= ?", labelUUID).
|
||||
Joins("JOIN photos ON photos.id = files.photo_id AND photos.photo_private = 0 AND photos.deleted_at IS NULL").
|
||||
Order("photos.photo_quality DESC, photos_labels.uncertainty ASC").
|
||||
First(&file).Error
|
||||
|
||||
return file, err
|
||||
}
|
||||
|
||||
// Labels searches labels based on their name.
|
||||
func Labels(f form.LabelSearch) (results []LabelResult, err error) {
|
||||
if err := f.ParseQueryString(); err != nil {
|
||||
|
@ -94,6 +27,7 @@ func Labels(f form.LabelSearch) (results []LabelResult, err error) {
|
|||
s = s.Table("labels").
|
||||
Select(`labels.*`).
|
||||
Where("labels.deleted_at IS NULL").
|
||||
Where("labels.photo_count > 0").
|
||||
Group("labels.id")
|
||||
|
||||
if f.ID != "" {
|
||||
|
|
|
@ -8,82 +8,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLabelBySlug(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
label, err := LabelBySlug("flower")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "Flower", label.LabelName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
label, err := LabelBySlug("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
assert.Empty(t, label.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelByUUID(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
label, err := LabelByUUID("lt9k3pw1wowuy3c5")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "COW", label.LabelName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
label, err := LabelByUUID("111")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
assert.Empty(t, label.ID)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelThumbBySlug(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := LabelThumbBySlug("flower")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := LabelThumbBySlug("cow")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabelThumbByUUID(t *testing.T) {
|
||||
t.Run("files found", func(t *testing.T) {
|
||||
file, err := LabelThumbByUUID("lt9k3pw1wowuy3c4")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, "exampleFileName.jpg", file.FileName)
|
||||
})
|
||||
|
||||
t.Run("no files found", func(t *testing.T) {
|
||||
file, err := LabelThumbByUUID("14")
|
||||
|
||||
assert.Error(t, err, "record not found")
|
||||
t.Log(file)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLabels(t *testing.T) {
|
||||
t.Run("search with query", func(t *testing.T) {
|
||||
query := form.NewLabelSearch("Query:C Count:1005 Order:slug")
|
||||
|
|
|
@ -14,16 +14,19 @@ func UpdatePhotoCounts() error {
|
|||
}
|
||||
|
||||
if err := Db().Table("labels").
|
||||
UpdateColumn("photo_count", gorm.Expr("(SELECT COUNT(*) FROM photos_labels pl "+
|
||||
"JOIN photos ph ON pl.photo_id = ph.id "+
|
||||
"LEFT JOIN categories c ON c.label_id = pl.label_id "+
|
||||
"LEFT JOIN labels lc ON lc.id = c.category_id "+
|
||||
"WHERE pl.label_id = labels.id "+
|
||||
"AND lc.deleted_at IS NULL "+
|
||||
"AND pl.uncertainty < 100 "+
|
||||
"AND ph.photo_quality >= 0 "+
|
||||
"AND ph.photo_private = 0 "+
|
||||
"AND ph.deleted_at IS NULL)")).Error; err != nil {
|
||||
UpdateColumn("photo_count", gorm.Expr(`(SELECT COUNT(DISTINCT ph.id) FROM labels l
|
||||
LEFT JOIN categories c ON c.category_id = l.id
|
||||
LEFT JOIN photos_labels pl ON pl.label_id = l.id
|
||||
LEFT JOIN photos_labels plc ON plc.label_id = c.label_id
|
||||
LEFT JOIN labels lc ON lc.id = plc.label_id
|
||||
LEFT JOIN photos ph ON pl.photo_id = ph.id OR plc.photo_id = ph.id
|
||||
WHERE l.id = labels.id
|
||||
AND lc.deleted_at IS NULL
|
||||
AND (pl.uncertainty < 100 OR pl.uncertainty IS NULL)
|
||||
AND (plc.uncertainty < 100 OR plc.uncertainty IS NULL)
|
||||
AND ph.photo_quality >= 0
|
||||
AND ph.photo_private = 0
|
||||
AND ph.deleted_at IS NULL)`)).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue