People: Improve face thumbnails on overview page #22
This commit is contained in:
parent
885b2b0e00
commit
8492efebcf
15 changed files with 131 additions and 56 deletions
|
@ -38,8 +38,8 @@ export class Subject extends RestModel {
|
|||
getDefaults() {
|
||||
return {
|
||||
UID: "",
|
||||
Thumb: "",
|
||||
ThumbSrc: "",
|
||||
MarkerUID: "",
|
||||
MarkerSrc: "",
|
||||
Type: "",
|
||||
Src: "",
|
||||
Slug: "",
|
||||
|
@ -51,6 +51,8 @@ export class Subject extends RestModel {
|
|||
Private: false,
|
||||
Excluded: false,
|
||||
FileCount: 0,
|
||||
FileHash: "",
|
||||
CropArea: "",
|
||||
Metadata: {},
|
||||
CreatedAt: "",
|
||||
UpdatedAt: "",
|
||||
|
@ -82,11 +84,21 @@ export class Subject extends RestModel {
|
|||
}
|
||||
|
||||
thumbnailUrl(size) {
|
||||
if (this.Thumb) {
|
||||
return `${config.contentUri}/t/${this.Thumb}/${config.previewToken()}/${size}`;
|
||||
} else {
|
||||
if (!this.FileHash) {
|
||||
return `${config.contentUri}/svg/portrait`;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
size = "tile_160";
|
||||
}
|
||||
|
||||
if (this.CropArea && (size === "tile_160" || size === "tile_320")) {
|
||||
return `${config.contentUri}/t/${this.FileHash}/${config.previewToken()}/${size}/${
|
||||
this.CropArea
|
||||
}`;
|
||||
} else {
|
||||
return `${config.contentUri}/t/${this.FileHash}/${config.previewToken()}/${size}`;
|
||||
}
|
||||
}
|
||||
|
||||
getDateString() {
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
>
|
||||
<div class="card-background accent lighten-3"></div>
|
||||
<v-img
|
||||
:src="model.thumbnailUrl('tile_500')"
|
||||
:src="model.thumbnailUrl('tile_320')"
|
||||
:alt="model.Name"
|
||||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
|
@ -509,8 +509,6 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log("onUpdate", ev, data);
|
||||
|
||||
const type = ev.split('.')[1];
|
||||
|
||||
switch (type) {
|
||||
|
|
|
@ -263,6 +263,7 @@ export default [
|
|||
path: "/people",
|
||||
component: Subjects,
|
||||
meta: { title: $gettext("People"), auth: true },
|
||||
props: { staticFilter: { files: 1, type: "person" } },
|
||||
},
|
||||
{
|
||||
name: "library",
|
||||
|
|
|
@ -89,15 +89,25 @@ func UpdateMarker(router *gin.RouterGroup) {
|
|||
}
|
||||
|
||||
// Save marker.
|
||||
if err := marker.SaveForm(markerForm); err != nil {
|
||||
if changed, err := marker.SaveForm(markerForm); err != nil {
|
||||
log.Errorf("photo: %s (save marker form)", err)
|
||||
AbortSaveFailed(c)
|
||||
return
|
||||
} else if marker.SubjUID != "" && marker.SubjSrc == entity.SrcManual && marker.FaceID != "" {
|
||||
if res, err := service.Faces().Optimize(); err != nil {
|
||||
log.Errorf("faces: %s (optimize)", err)
|
||||
} else if res.Merged > 0 {
|
||||
log.Infof("faces: %d clusters merged", res.Merged)
|
||||
} else if changed {
|
||||
if marker.FaceID != "" && marker.SubjUID != "" && marker.SubjSrc == entity.SrcManual {
|
||||
if res, err := service.Faces().Optimize(); err != nil {
|
||||
log.Errorf("faces: %s (optimize)", err)
|
||||
} else if res.Merged > 0 {
|
||||
log.Infof("faces: %d clusters merged", res.Merged)
|
||||
}
|
||||
}
|
||||
|
||||
if err := query.UpdateSubjectPreviews(); err != nil {
|
||||
log.Errorf("faces: %s (update previews)", err)
|
||||
}
|
||||
|
||||
if err := entity.UpdateSubjectFileCounts(); err != nil {
|
||||
log.Errorf("faces: %s (update counts)", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,6 +148,10 @@ func ClearMarkerSubject(router *gin.RouterGroup) {
|
|||
log.Errorf("faces: %s (clear subject)", err)
|
||||
AbortSaveFailed(c)
|
||||
return
|
||||
} else if err := query.UpdateSubjectPreviews(); err != nil {
|
||||
log.Errorf("faces: %s (update previews)", err)
|
||||
} else if err := entity.UpdateSubjectFileCounts(); err != nil {
|
||||
log.Errorf("faces: %s (update counts)", err)
|
||||
}
|
||||
|
||||
// Update photo metadata.
|
||||
|
|
|
@ -48,6 +48,7 @@ type Marker struct {
|
|||
Y float32 `gorm:"type:FLOAT;" json:"Y" yaml:"Y,omitempty"`
|
||||
W float32 `gorm:"type:FLOAT;" json:"W" yaml:"W,omitempty"`
|
||||
H float32 `gorm:"type:FLOAT;" json:"H" yaml:"H,omitempty"`
|
||||
Q int `json:"Q" yaml:"Q,omitempty"`
|
||||
Size int `gorm:"default:-1" json:"Size" yaml:"Size,omitempty"`
|
||||
Score int `gorm:"type:SMALLINT" json:"Score" yaml:"Score,omitempty"`
|
||||
MatchedAt *time.Time `sql:"index" json:"MatchedAt" yaml:"MatchedAt,omitempty"`
|
||||
|
@ -93,6 +94,7 @@ func NewFaceMarker(f face.Face, file File, subjUID string) *Marker {
|
|||
m := NewMarker(file, f.CropArea(), subjUID, SrcImage, MarkerFace)
|
||||
|
||||
m.Size = f.Size()
|
||||
m.Q = int(float32(math.Log(float64(f.Score))) * float32(m.Size) * m.W)
|
||||
m.Score = f.Score
|
||||
m.MarkerReview = f.Score < 30
|
||||
m.FaceDist = -1
|
||||
|
@ -113,9 +115,7 @@ func (m *Marker) Update(attr string, value interface{}) error {
|
|||
}
|
||||
|
||||
// SaveForm updates the entity using form data and stores it in the database.
|
||||
func (m *Marker) SaveForm(f form.Marker) error {
|
||||
changed := false
|
||||
|
||||
func (m *Marker) SaveForm(f form.Marker) (changed bool, err error) {
|
||||
if m.MarkerInvalid != f.MarkerInvalid {
|
||||
m.MarkerInvalid = f.MarkerInvalid
|
||||
changed = true
|
||||
|
@ -126,22 +126,22 @@ func (m *Marker) SaveForm(f form.Marker) error {
|
|||
changed = true
|
||||
}
|
||||
|
||||
if f.SubjSrc == SrcManual && strings.TrimSpace(f.MarkerName) != "" {
|
||||
if f.SubjSrc == SrcManual && strings.TrimSpace(f.MarkerName) != "" && f.MarkerName != m.MarkerName {
|
||||
m.SubjSrc = SrcManual
|
||||
m.MarkerName = txt.Title(txt.Clip(f.MarkerName, txt.ClipDefault))
|
||||
|
||||
if err := m.SyncSubject(true); err != nil {
|
||||
return err
|
||||
return changed, err
|
||||
}
|
||||
|
||||
changed = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
return m.Save()
|
||||
return changed, m.Save()
|
||||
}
|
||||
|
||||
return nil
|
||||
return changed, nil
|
||||
}
|
||||
|
||||
// HasFace tests if the marker already has the best matching face.
|
||||
|
@ -551,8 +551,9 @@ func UpdateOrCreateMarker(m *Marker) (*Marker, error) {
|
|||
"Y": m.Y,
|
||||
"W": m.W,
|
||||
"H": m.H,
|
||||
"Score": m.Score,
|
||||
"Q": m.Q,
|
||||
"Size": m.Size,
|
||||
"Score": m.Score,
|
||||
"LandmarksJSON": m.LandmarksJSON,
|
||||
"EmbeddingsJSON": m.EmbeddingsJSON,
|
||||
})
|
||||
|
|
|
@ -33,6 +33,7 @@ func (m *Marker) MarshalJSON() ([]byte, error) {
|
|||
Y float32
|
||||
W float32 `json:",omitempty"`
|
||||
H float32 `json:",omitempty"`
|
||||
Q int `json:",omitempty"`
|
||||
Size int `json:",omitempty"`
|
||||
Score int `json:",omitempty"`
|
||||
CreatedAt time.Time
|
||||
|
@ -53,6 +54,7 @@ func (m *Marker) MarshalJSON() ([]byte, error) {
|
|||
Y: m.Y,
|
||||
W: m.W,
|
||||
H: m.H,
|
||||
Q: m.Q,
|
||||
Size: m.Size,
|
||||
Score: m.Score,
|
||||
CreatedAt: m.CreatedAt,
|
||||
|
|
|
@ -49,12 +49,13 @@ func TestMarker_SaveForm(t *testing.T) {
|
|||
|
||||
f := form.Marker{SubjSrc: SrcManual, MarkerName: "Jane Doe", MarkerInvalid: false}
|
||||
|
||||
err := m.SaveForm(f)
|
||||
changed, err := m.SaveForm(f)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.True(t, changed)
|
||||
assert.NotEmpty(t, m.SubjUID)
|
||||
|
||||
if s := m.Subject(); s != nil {
|
||||
|
@ -72,8 +73,10 @@ func TestMarker_SaveForm(t *testing.T) {
|
|||
|
||||
if m := FindMarker("mt9k3pw1wowuy777"); m == nil {
|
||||
t.Fatal("result is nil")
|
||||
} else if err := m.SaveForm(f3); err != nil {
|
||||
} else if changed, err := m.SaveForm(f3); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
assert.True(t, changed)
|
||||
}
|
||||
|
||||
if m := FindMarker("mt9k3pw1wowuy666"); m != nil {
|
||||
|
|
|
@ -43,8 +43,8 @@ func LabelCounts() LabelPhotoCounts {
|
|||
return result
|
||||
}
|
||||
|
||||
// UpdatePhotoCounts updates static photos counts and visibilities.
|
||||
func UpdatePhotoCounts() (err error) {
|
||||
// UpdatePlacesPhotoCounts updates the places photo counts.
|
||||
func UpdatePlacesPhotoCounts() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
// Update places.
|
||||
|
@ -57,9 +57,14 @@ func UpdatePhotoCounts() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("places: updating photo counts completed in %s", time.Since(start))
|
||||
log.Debugf("counts: updated places [%s]", time.Since(start))
|
||||
|
||||
start = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSubjectFileCounts updates the subject file counts.
|
||||
func UpdateSubjectFileCounts() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
// Update subjects.
|
||||
if err = Db().Table(Subject{}.TableName()).
|
||||
|
@ -72,11 +77,15 @@ func UpdatePhotoCounts() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("subjects: updating file counts completed in %s", time.Since(start))
|
||||
log.Debugf("counts: updated subjects [%s]", time.Since(start))
|
||||
|
||||
start = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateLabelPhotoCounts updates the label photo counts.
|
||||
func UpdateLabelPhotoCounts() (err error) {
|
||||
start := time.Now()
|
||||
|
||||
// Update labels.
|
||||
if IsDialect(MySQL) {
|
||||
if err = Db().
|
||||
Table("labels").
|
||||
|
@ -129,7 +138,24 @@ func UpdatePhotoCounts() (err error) {
|
|||
return fmt.Errorf("unknown sql dialect %s", DbDialect())
|
||||
}
|
||||
|
||||
log.Debugf("labels: updating photo counts completed in %s", time.Since(start))
|
||||
log.Debugf("counts: updated labels [%s]", time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdatePhotoCounts updates static photos counts and visibilities.
|
||||
func UpdatePhotoCounts() (err error) {
|
||||
if err = UpdatePlacesPhotoCounts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = UpdateSubjectFileCounts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = UpdateLabelPhotoCounts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* TODO: Slow with many photos due to missing index.
|
||||
start = time.Now()
|
||||
|
@ -151,7 +177,7 @@ func UpdatePhotoCounts() (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
log.Debugf("calendar: updating visibility completed in %s", time.Since(start))
|
||||
log.Debugf("calendar: updating visibility completed [%s]", time.Since(start))
|
||||
*/
|
||||
|
||||
return nil
|
||||
|
|
|
@ -21,8 +21,8 @@ type Subjects []Subject
|
|||
// Subject represents a named photo subject, typically a person.
|
||||
type Subject struct {
|
||||
SubjUID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"UID" yaml:"UID"`
|
||||
Thumb string `gorm:"type:VARBINARY(128);index;default:''" json:"Thumb,omitempty" yaml:"Thumb,omitempty"`
|
||||
ThumbSrc string `gorm:"type:VARBINARY(8);default:''" json:"ThumbSrc,omitempty" yaml:"ThumbSrc,omitempty"`
|
||||
MarkerUID string `gorm:"type:VARBINARY(42);index" json:"MarkerUID" yaml:"MarkerUID,omitempty"`
|
||||
MarkerSrc string `gorm:"type:VARBINARY(8);default:''" json:"MarkerSrc,omitempty" yaml:"MarkerSrc,omitempty"`
|
||||
SubjType string `gorm:"type:VARBINARY(8);default:''" json:"Type,omitempty" yaml:"Type,omitempty"`
|
||||
SubjSrc string `gorm:"type:VARBINARY(8);default:''" json:"Src,omitempty" yaml:"Src,omitempty"`
|
||||
SubjSlug string `gorm:"type:VARBINARY(255);index;default:''" json:"Slug" yaml:"-"`
|
||||
|
|
|
@ -19,7 +19,6 @@ type Person struct {
|
|||
SubjName string `json:"Name"`
|
||||
SubjAlias string `json:"Alias"`
|
||||
SubjFavorite bool `json:"Favorite"`
|
||||
Thumb string `json:"Thumb"`
|
||||
}
|
||||
|
||||
// NewPerson returns a new entity.
|
||||
|
@ -29,7 +28,6 @@ func NewPerson(subj Subject) *Person {
|
|||
SubjName: subj.SubjName,
|
||||
SubjAlias: subj.SubjAlias,
|
||||
SubjFavorite: subj.SubjFavorite,
|
||||
Thumb: subj.Thumb,
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -42,12 +40,10 @@ func (m *Person) MarshalJSON() ([]byte, error) {
|
|||
Name string
|
||||
Keywords []string `json:",omitempty"`
|
||||
Favorite bool `json:",omitempty"`
|
||||
Thumb string `json:",omitempty"`
|
||||
}{
|
||||
UID: m.SubjUID,
|
||||
Name: m.SubjName,
|
||||
Keywords: txt.NameKeywords(m.SubjName, m.SubjAlias),
|
||||
Favorite: m.SubjFavorite,
|
||||
Thumb: m.Thumb,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ func TestNewPerson(t *testing.T) {
|
|||
SubjName: "William Henry Gates III",
|
||||
SubjAlias: "Windows Guru",
|
||||
SubjFavorite: true,
|
||||
Thumb: "622c7287967f2800e873fbc55f0328973056ce1d",
|
||||
}
|
||||
|
||||
m := NewPerson(subj)
|
||||
|
@ -22,7 +21,6 @@ func TestNewPerson(t *testing.T) {
|
|||
assert.Equal(t, "William Henry Gates III", m.SubjName)
|
||||
assert.Equal(t, "Windows Guru", m.SubjAlias)
|
||||
assert.Equal(t, true, m.SubjFavorite)
|
||||
assert.Equal(t, "622c7287967f2800e873fbc55f0328973056ce1d", m.Thumb)
|
||||
|
||||
if j, err := m.MarshalJSON(); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -31,7 +29,7 @@ func TestNewPerson(t *testing.T) {
|
|||
|
||||
expected := "{\"UID\":\"jqytw12v8jjeu3e6\",\"Name\":\"William Henry Gates III\"," +
|
||||
"\"Keywords\":[\"william\",\"henry\",\"gates\",\"iii\",\"windows\",\"guru\"]," +
|
||||
"\"Favorite\":true,\"Thumb\":\"622c7287967f2800e873fbc55f0328973056ce1d\"}"
|
||||
"\"Favorite\":true}"
|
||||
|
||||
assert.Equal(t, expected, s)
|
||||
t.Logf("person json: %s", s)
|
||||
|
|
|
@ -10,6 +10,7 @@ type SubjectSearch struct {
|
|||
Favorite bool `form:"favorite"`
|
||||
Private bool `form:"private"`
|
||||
Excluded bool `form:"excluded"`
|
||||
Files int `form:"files"`
|
||||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
|
|
|
@ -21,7 +21,7 @@ func UpdateAlbumDefaultPreviews() (err error) {
|
|||
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))
|
||||
log.Debugf("previews: updated albums [%s]", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ func UpdateAlbumFolderPreviews() (err error) {
|
|||
) WHERE thumb_src = '' AND album_type = 'folder' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
|
||||
log.Debugf("folders: updating previews completed in %s", time.Since(start))
|
||||
log.Debugf("previews: updated folders [%s]", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ func UpdateAlbumMonthPreviews() (err error) {
|
|||
return nil
|
||||
}
|
||||
*/
|
||||
log.Debugf("calendar: updating previews completed in %s", time.Since(start))
|
||||
log.Debugf("previews: updated calendar [%s]", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func UpdateLabelPreviews() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("labels: updating previews completed in %s", time.Since(start))
|
||||
log.Debugf("previews: updated labels [%s]", time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ func UpdateCategoryPreviews() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debugf("categories: updating previews completed in %s", time.Since(start))
|
||||
log.Debugf("previews: updated categories [%s]", time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -170,16 +170,28 @@ func UpdateSubjectPreviews() (err error) {
|
|||
Error */
|
||||
|
||||
err = Db().Table(entity.Subject{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr("(SELECT m.file_hash FROM "+
|
||||
UpdateColumn("marker_uid", gorm.Expr("(SELECT m.marker_uid FROM "+
|
||||
fmt.Sprintf(
|
||||
"%s m WHERE m.subj_uid = %s.subj_uid AND m.subj_src = 'manual' ",
|
||||
entity.Marker{}.TableName(),
|
||||
entity.Subject{}.TableName())+
|
||||
` AND m.file_hash <> '' ORDER BY m.size DESC LIMIT 1)
|
||||
WHERE thumb_src='' AND deleted_at IS NULL`)).
|
||||
` AND m.file_hash <> '' ORDER BY m.q DESC LIMIT 1)
|
||||
WHERE marker_src = '' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
|
||||
log.Debugf("subjects: updating previews completed in %s", time.Since(start))
|
||||
/** err = Db().Table(entity.Subject{}.TableName()).
|
||||
UpdateColumn("thumb", gorm.Expr("(SELECT m.file_hash FROM "+
|
||||
fmt.Sprintf(
|
||||
"%s m WHERE m.subj_uid = %s.subj_uid AND m.subj_src = 'manual' ",
|
||||
entity.Marker{}.TableName(),
|
||||
entity.Subject{}.TableName())+
|
||||
` AND m.file_hash <> '' ORDER BY m.w DESC LIMIT 1)
|
||||
WHERE thumb_src = '' AND deleted_at IS NULL`)).
|
||||
Error
|
||||
|
||||
*/
|
||||
|
||||
log.Debugf("previews: updated subjects [%s]", time.Since(start))
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import (
|
|||
// SubjectResult represents a subject search result.
|
||||
type SubjectResult struct {
|
||||
SubjUID string `json:"UID"`
|
||||
MarkerUID string `json:"MarkerUID"`
|
||||
MarkerSrc string `json:"MarkerSrc,omitempty"`
|
||||
SubjType string `json:"Type"`
|
||||
SubjSlug string `json:"Slug"`
|
||||
SubjName string `json:"Name"`
|
||||
|
@ -22,7 +24,8 @@ type SubjectResult struct {
|
|||
SubjPrivate bool `json:"Private"`
|
||||
SubjExcluded bool `json:"Excluded"`
|
||||
FileCount int `json:"FileCount"`
|
||||
Thumb string `json:"Thumb"`
|
||||
FileHash string `json:"FileHash"`
|
||||
CropArea string `json:"CropArea"`
|
||||
}
|
||||
|
||||
// SubjectResults represents subject search results.
|
||||
|
@ -38,7 +41,10 @@ func SubjectSearch(f form.SubjectSearch) (results SubjectResults, err error) {
|
|||
|
||||
// Base query.
|
||||
s := UnscopedDb().Table(entity.Subject{}.TableName()).
|
||||
Select("subj_uid, subj_slug, subj_name, subj_alias, subj_type, thumb, subj_favorite, subj_private, subj_excluded, file_count")
|
||||
Select(fmt.Sprintf("%s.*, m.file_hash, m.crop_area", entity.Subject{}.TableName()))
|
||||
|
||||
// Join markers table for face thumbs.
|
||||
s = s.Joins(fmt.Sprintf("LEFT JOIN %s m ON m.marker_uid = %s.marker_uid", entity.Marker{}.TableName(), entity.Subject{}.TableName()))
|
||||
|
||||
// Limit result count.
|
||||
if f.Count > 0 && f.Count <= MaxResults {
|
||||
|
@ -54,7 +60,7 @@ func SubjectSearch(f form.SubjectSearch) (results SubjectResults, err error) {
|
|||
case "count":
|
||||
s = s.Order("file_count DESC")
|
||||
case "added":
|
||||
s = s.Order("created_at DESC")
|
||||
s = s.Order(fmt.Sprintf("%s.created_at DESC", entity.Subject{}.TableName()))
|
||||
case "relevance":
|
||||
s = s.Order("subj_favorite DESC, subj_name")
|
||||
default:
|
||||
|
@ -62,7 +68,7 @@ func SubjectSearch(f form.SubjectSearch) (results SubjectResults, err error) {
|
|||
}
|
||||
|
||||
if f.ID != "" {
|
||||
s = s.Where("subj_uid IN (?)", strings.Split(f.ID, Or))
|
||||
s = s.Where(fmt.Sprintf("%s.subj_uid IN (?)", entity.Subject{}.TableName()), strings.Split(f.ID, Or))
|
||||
|
||||
if result := s.Scan(&results); result.Error != nil {
|
||||
return results, result.Error
|
||||
|
@ -77,6 +83,10 @@ func SubjectSearch(f form.SubjectSearch) (results SubjectResults, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if f.Files > 0 {
|
||||
s = s.Where("file_count >= ?", f.Files)
|
||||
}
|
||||
|
||||
if f.Type != "" {
|
||||
s = s.Where("subj_type IN (?)", strings.Split(f.Type, Or))
|
||||
}
|
||||
|
@ -94,7 +104,7 @@ func SubjectSearch(f form.SubjectSearch) (results SubjectResults, err error) {
|
|||
}
|
||||
|
||||
// Omit deleted rows.
|
||||
s = s.Where("deleted_at IS NULL")
|
||||
s = s.Where(fmt.Sprintf("%s.deleted_at IS NULL", entity.Subject{}.TableName()))
|
||||
|
||||
if result := s.Scan(&results); result.Error != nil {
|
||||
return results, result.Error
|
||||
|
|
|
@ -14,6 +14,7 @@ func TestSubjectSearch(t *testing.T) {
|
|||
t.Run("FindAll", func(t *testing.T) {
|
||||
results, err := SubjectSearch(form.SubjectSearch{Type: entity.SubjPerson})
|
||||
assert.NoError(t, err)
|
||||
// t.Logf("Subjects: %#v", results)
|
||||
assert.LessOrEqual(t, 3, len(results))
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue