Backend: Provide unknown camera & lens as default

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
Michael Mayer 2020-04-25 14:22:47 +02:00
parent 8220f0a443
commit e8e0639d78
15 changed files with 75 additions and 47 deletions

View file

@ -1,4 +1,3 @@
INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (1, 'unknown', 'Unknown', '', '', '', '', '2020-01-06 02:06:29', '2020-01-06 02:07:26', null);
INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (2, 'apple-iphone-se', 'iPhone SE', 'Apple', '', '', '', '2020-01-06 02:06:30', '2020-01-06 02:07:28', null);
INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (3, 'canon-eos-5d', 'EOS 5D', 'Canon', '', '', '', '2020-01-06 02:06:32', '2020-01-06 02:06:32', null);
INSERT INTO cameras (id, camera_slug, camera_model, camera_make, camera_type, camera_description, camera_notes, created_at, updated_at, deleted_at) VALUES (4, 'canon-eos-7d', 'EOS 7D', 'Canon', '', '', '', '2020-01-06 02:06:33', '2020-01-06 02:06:33', null);

View file

@ -355,7 +355,8 @@
</v-btn>
<v-btn color="secondary-dark" depressed dark @click.stop="save(false)"
class="p-photo-dialog-confirm">
<span>Apply</span>
<span v-if="config.settings.library.review && model.PhotoQuality < 3">Approve</span>
<span v-else>Apply</span>
</v-btn>
<v-btn color="secondary-dark" depressed dark @click.stop="save(true)"
class="p-photo-dialog-confirm hidden-xs-only">

View file

@ -167,15 +167,15 @@ func (c *Config) ClientConfig() ClientConfig {
db.Model(&entity.Country{}).
Select("id, country_name").
Order("country_name").
Order("country_slug").
Scan(&countries)
db.Where("deleted_at IS NULL").
Limit(1000).Order("camera_model").
Limit(10000).Order("camera_slug").
Find(&cameras)
db.Where("deleted_at IS NULL").
Limit(1000).Order("lens_model").
Limit(10000).Order("lens_slug").
Find(&lenses)
db.Where("deleted_at IS NULL AND album_favorite = 1").

View file

@ -85,6 +85,8 @@ func (c *Config) MigrateDb() {
entity.CreateUnknownPlace(db)
entity.CreateUnknownCountry(db)
entity.CreateUnknownCamera(db)
entity.CreateUnknownLens(db)
}
// DropTables drops all tables in the currently configured database (be careful!).

View file

@ -24,12 +24,23 @@ type Camera struct {
DeletedAt *time.Time `sql:"index"`
}
var UnknownCamera = Camera{
CameraModel: "Unknown",
CameraMake: "",
CameraSlug: "zz",
}
// CreateUnknownCamera initializes the database with an unknown camera if not exists
func CreateUnknownCamera(db *gorm.DB) {
UnknownCamera.FirstOrCreate(db)
}
// NewCamera creates a camera entity from a model name and a make name.
func NewCamera(modelName string, makeName string) *Camera {
makeName = strings.TrimSpace(makeName)
if modelName == "" {
modelName = "Unknown"
return &UnknownCamera
} else if strings.HasPrefix(modelName, makeName) {
modelName = strings.TrimSpace(modelName[len(makeName):])
}

View file

@ -7,15 +7,10 @@ import (
)
func TestNewCamera(t *testing.T) {
t.Run("model Unknown make Nikon", func(t *testing.T) {
t.Run("unknown camera", func(t *testing.T) {
camera := NewCamera("", "Nikon")
expected := &Camera{
CameraModel: "Unknown",
CameraMake: "Nikon",
CameraSlug: "nikon-unknown",
}
assert.Equal(t, expected, camera)
assert.Equal(t, &UnknownCamera, camera)
})
t.Run("model EOS 6D make Canon", func(t *testing.T) {
camera := NewCamera("EOS 6D", "Canon")
@ -50,12 +45,7 @@ func TestNewCamera(t *testing.T) {
t.Run("model Unknown make Unknown", func(t *testing.T) {
camera := NewCamera("", "")
expected := &Camera{
CameraModel: "Unknown",
CameraMake: "",
CameraSlug: "unknown",
}
assert.Equal(t, expected, camera)
assert.Equal(t, &UnknownCamera, camera)
})
}

View file

@ -26,8 +26,12 @@ type Country struct {
New bool `gorm:"-"`
}
// UnknownCountry is the default country
var UnknownCountry = NewCountry("zz", maps.CountryNames["zz"])
// UnknownCountry is defined here to use it as a default
var UnknownCountry = Country{
ID: "zz",
CountryName: maps.CountryNames["zz"],
CountrySlug: "zz",
}
// CreateUnknownCountry is used to initialize the database with the default country
func CreateUnknownCountry(db *gorm.DB) {
@ -37,7 +41,7 @@ func CreateUnknownCountry(db *gorm.DB) {
// NewCountry creates a new country, with default country code if not provided
func NewCountry(countryCode string, countryName string) *Country {
if countryCode == "" {
countryCode = "zz"
return &UnknownCountry
}
if altName, ok := altCountryNames[countryName]; ok {

View file

@ -24,6 +24,17 @@ type Lens struct {
DeletedAt *time.Time `sql:"index"`
}
var UnknownLens = Lens{
LensModel: "Unknown",
LensMake: "",
LensSlug: "zz",
}
// CreateUnknownLens initializes the database with an unknown lens if not exists
func CreateUnknownLens(db *gorm.DB) {
UnknownLens.FirstOrCreate(db)
}
// TableName returns Lens table identifier "lens"
func (Lens) TableName() string {
return "lenses"
@ -33,13 +44,12 @@ func (Lens) TableName() string {
func NewLens(modelName string, makeName string) *Lens {
modelName = strings.TrimSpace(modelName)
makeName = strings.TrimSpace(makeName)
lensSlug := slug.MakeLang(modelName, "en")
if modelName == "" {
modelName = "Unknown"
return &UnknownLens
}
lensSlug := slug.MakeLang(modelName, "en")
result := &Lens{
LensModel: modelName,
LensMake: makeName,
@ -49,7 +59,7 @@ func NewLens(modelName string, makeName string) *Lens {
return result
}
// FirstOrCreate checks wether the lens already exists in the database
// FirstOrCreate checks if the lens already exists in the database
func (m *Lens) FirstOrCreate(db *gorm.DB) *Lens {
mutex.Db.Lock()
defer mutex.Db.Unlock()

View file

@ -17,7 +17,8 @@ func TestNewLens(t *testing.T) {
lens := NewLens("", "")
assert.Equal(t, "Unknown", lens.LensModel)
assert.Equal(t, "", lens.LensMake)
assert.Equal(t, "unknown", lens.LensSlug)
assert.Equal(t, "zz", lens.LensSlug)
assert.Equal(t, &UnknownLens, lens)
})
}

View file

@ -62,6 +62,7 @@ type Photo struct {
Labels []PhotoLabel
CreatedAt time.Time
UpdatedAt time.Time
EditedAt *time.Time
DeletedAt *time.Time `sql:"index"`
}
@ -100,6 +101,8 @@ func SavePhotoForm(model Photo, form form.Photo, db *gorm.DB, geoApi string) err
log.Warnf("%s (%s)", err.Error(), model.PhotoUUID)
}
edited := time.Now().UTC()
model.EditedAt = &edited
model.PhotoQuality = model.QualityScore()
return db.Unscoped().Save(&model).Error

View file

@ -84,7 +84,7 @@ func (m *Photo) UpdateLocation(db *gorm.DB, geoApi string) (keywords []string, l
} else {
log.Warn(err)
m.Place = UnknownPlace
m.Place = &UnknownPlace
m.PlaceID = UnknownPlace.ID
}

View file

@ -2,6 +2,7 @@ package entity
import (
"strings"
"time"
"github.com/photoprism/photoprism/pkg/txt"
)
@ -12,6 +13,11 @@ var QualityBlacklist = map[string]bool{
"info": true,
}
var (
year2008 = time.Date(2008, 1,1,0,0,0,0, time.UTC)
year2012 = time.Date(2012, 1,1,0,0,0,0, time.UTC)
)
// QualityScore returns a score based on photo properties like size and metadata.
func (m *Photo) QualityScore() (score int) {
if m.PhotoFavorite {
@ -26,7 +32,11 @@ func (m *Photo) QualityScore() (score int) {
score++
}
if m.PhotoResolution >= 2 {
if m.TakenAt.Before(year2008) {
score++
} else if m.TakenAt.Before(year2012) && m.PhotoResolution >= 1 {
score++
} else if m.PhotoResolution >= 2 {
score++
}
@ -49,5 +59,9 @@ func (m *Photo) QualityScore() (score int) {
score++
}
if score < 3 && m.EditedAt != nil {
score = 3
}
return score
}

View file

@ -22,8 +22,14 @@ type Place struct {
New bool `gorm:"-"`
}
// UnknownPlace is the default unknown place
var UnknownPlace = NewPlace("-", "Unknown", "Unknown", "Unknown", "zz")
// UnknownPlace is defined here to use it as a default
var UnknownPlace = Place{
ID: "-",
LocLabel: "Unknown",
LocCity: "Unknown",
LocState: "Unknown",
LocCountry: "zz",
}
// CreateUnknownPlace initializes default place in the database
func CreateUnknownPlace(db *gorm.DB) {
@ -57,19 +63,6 @@ func FindPlaceByLabel(id string, label string, db *gorm.DB) *Place {
return place
}
// NewPlace registers a new place in database
func NewPlace(id, label, city, state, countryCode string) *Place {
result := &Place{
ID: id,
LocLabel: label,
LocCity: city,
LocState: state,
LocCountry: countryCode,
}
return result
}
// Find returns db record of place
func (m *Place) Find(db *gorm.DB) error {
if err := db.First(m, "id = ?", m.ID).Error; err != nil {

View file

@ -232,7 +232,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
} else {
log.Info("index: no latitude and longitude in metadata")
photo.Place = entity.UnknownPlace
photo.Place = &entity.UnknownPlace
photo.PlaceID = entity.UnknownPlace.ID
}
}
@ -263,7 +263,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
}
if photo.Place == nil {
photo.Place = entity.UnknownPlace
photo.Place = &entity.UnknownPlace
photo.PlaceID = entity.UnknownPlace.ID
}

View file

@ -20,7 +20,7 @@ func TestNewCountry(t *testing.T) {
country := entity.NewCountry("", "")
assert.Equal(t, "zz", country.ID)
assert.Equal(t, "Unknown", country.CountryName)
assert.Equal(t, "unknown", country.CountrySlug)
assert.Equal(t, "zz", country.CountrySlug)
})
}
func TestCountry_FirstOrCreate(t *testing.T) {