parent
4891377d35
commit
12cb89eca5
16 changed files with 126 additions and 105 deletions
|
@ -88,6 +88,21 @@
|
|||
<td>{{ model.CameraSerial }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="model.Stack < 1">
|
||||
<td>
|
||||
<translate>Stackable</translate>
|
||||
</td>
|
||||
<td>
|
||||
<v-switch
|
||||
@change="save"
|
||||
hide-details
|
||||
:true-value="0"
|
||||
:false-value="-1"
|
||||
v-model="model.Stack"
|
||||
:label="model.Stack ? $gettext('Yes') : $gettext('No')"
|
||||
></v-switch>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate>Favorite</translate>
|
||||
|
@ -114,19 +129,6 @@
|
|||
></v-switch>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate>Unstacked</translate>
|
||||
</td>
|
||||
<td>
|
||||
<v-switch
|
||||
@change="save"
|
||||
hide-details
|
||||
v-model="model.Single"
|
||||
:label="model.Single ? $gettext('Yes') : $gettext('No')"
|
||||
></v-switch>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate>Scan</translate>
|
||||
|
|
|
@ -57,6 +57,7 @@ export class Photo extends RestModel {
|
|||
DocumentID: "",
|
||||
Type: TypeImage,
|
||||
TypeSrc: "",
|
||||
Stack: 0,
|
||||
Favorite: false,
|
||||
Private: false,
|
||||
Scan: false,
|
||||
|
|
|
@ -50,7 +50,7 @@ func StartIndexing(router *gin.RouterGroup) {
|
|||
Rescan: f.Rescan,
|
||||
Convert: conf.Settings().Index.Convert && conf.SidecarWritable(),
|
||||
Path: filepath.Clean(f.Path),
|
||||
Single: false,
|
||||
Stack: true,
|
||||
}
|
||||
|
||||
if len(indOpt.Path) > 1 {
|
||||
|
|
|
@ -114,7 +114,7 @@ func PhotoUnstack(router *gin.RouterGroup) {
|
|||
files = related.Files
|
||||
}
|
||||
|
||||
newPhoto := entity.NewPhoto(true)
|
||||
newPhoto := entity.NewPhoto(false)
|
||||
newPhoto.PhotoPath = unstackFile.RootRelPath()
|
||||
newPhoto.PhotoName = unstackFile.BasePrefix(false)
|
||||
|
||||
|
@ -175,7 +175,7 @@ func PhotoUnstack(router *gin.RouterGroup) {
|
|||
}
|
||||
|
||||
// Re-index existing photo stack.
|
||||
if res := ind.FileName(photoprism.FileName(stackPrimary.FileRoot, stackPrimary.FileName), photoprism.IndexOptionsAll()); res.Failed() {
|
||||
if res := ind.FileName(photoprism.FileName(stackPrimary.FileRoot, stackPrimary.FileName), photoprism.IndexOptionsSingle()); res.Failed() {
|
||||
log.Errorf("photo: %s (unstack %s)", res.Err, txt.Quote(baseName))
|
||||
AbortSaveFailed(c)
|
||||
return
|
||||
|
|
|
@ -63,7 +63,7 @@ func indexAction(ctx *cli.Context) error {
|
|||
Path: subPath,
|
||||
Rescan: ctx.Bool("all"),
|
||||
Convert: conf.Settings().Index.Convert && conf.SidecarWritable(),
|
||||
Single: false,
|
||||
Stack: true,
|
||||
}
|
||||
|
||||
indexed := ind.Start(indOpt)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package entity
|
||||
|
||||
const (
|
||||
// Sort orders.
|
||||
// Sort orders:
|
||||
SortOrderAdded = "added"
|
||||
SortOrderNewest = "newest"
|
||||
SortOrderOldest = "oldest"
|
||||
|
@ -10,13 +10,13 @@ const (
|
|||
SortOrderRelevance = "relevance"
|
||||
SortOrderEdited = "edited"
|
||||
|
||||
// Unknown values.
|
||||
// Unknown values:
|
||||
YearUnknown = -1
|
||||
MonthUnknown = -1
|
||||
DayUnknown = -1
|
||||
TitleUnknown = "Unknown"
|
||||
|
||||
// Content types.
|
||||
// Content types:
|
||||
TypeDefault = ""
|
||||
TypeImage = "image"
|
||||
TypeLive = "live"
|
||||
|
@ -24,7 +24,7 @@ const (
|
|||
TypeRaw = "raw"
|
||||
TypeText = "text"
|
||||
|
||||
// Root directories.
|
||||
// Root directories:
|
||||
RootUnknown = ""
|
||||
RootOriginals = "/"
|
||||
RootExamples = "examples"
|
||||
|
@ -32,14 +32,19 @@ const (
|
|||
RootImport = "import"
|
||||
RootPath = "/"
|
||||
|
||||
// Panorama projections.
|
||||
// Panorama projections:
|
||||
ProjectionDefault = ""
|
||||
ProjectionEquirectangular = "equirectangular"
|
||||
ProjectionCubestrip = "cubestrip"
|
||||
ProjectionCylindrical = "cylindrical"
|
||||
|
||||
// Event names.
|
||||
// Event names:
|
||||
Updated = "updated"
|
||||
Created = "created"
|
||||
Deleted = "deleted"
|
||||
|
||||
// Photo stacks:
|
||||
IsStacked int8 = 1
|
||||
IsStackable int8 = 0
|
||||
IsUnstacked int8 = -1
|
||||
)
|
||||
|
|
|
@ -97,7 +97,7 @@ func TestDetails_NoCopyright(t *testing.T) {
|
|||
|
||||
func TestNewDetails(t *testing.T) {
|
||||
t.Run("add to photo", func(t *testing.T) {
|
||||
p := NewPhoto(false)
|
||||
p := NewPhoto(true)
|
||||
|
||||
assert.Equal(t, TitleUnknown, p.PhotoTitle)
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ type Photo struct {
|
|||
PhotoPath string `gorm:"type:VARBINARY(500);index:idx_photos_path_name;" json:"Path" yaml:"-"`
|
||||
PhotoName string `gorm:"type:VARBINARY(255);index:idx_photos_path_name;" json:"Name" yaml:"-"`
|
||||
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||
PhotoStack int8 `json:"Stack" yaml:"Stack"`
|
||||
PhotoFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||
PhotoSingle bool `json:"Single" yaml:"Single,omitempty"`
|
||||
PhotoPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
||||
PhotoScan bool `json:"Scan" yaml:"Scan,omitempty"`
|
||||
PhotoPanorama bool `json:"Panorama" yaml:"Panorama,omitempty"`
|
||||
|
@ -102,11 +102,10 @@ type Photo struct {
|
|||
}
|
||||
|
||||
// NewPhoto creates a photo entity.
|
||||
func NewPhoto(single bool) Photo {
|
||||
return Photo{
|
||||
func NewPhoto(stackable bool) Photo {
|
||||
m := Photo{
|
||||
PhotoTitle: TitleUnknown,
|
||||
PhotoType: TypeImage,
|
||||
PhotoSingle: single,
|
||||
PhotoCountry: UnknownCountry.ID,
|
||||
CameraID: UnknownCamera.ID,
|
||||
LensID: UnknownLens.ID,
|
||||
|
@ -117,6 +116,14 @@ func NewPhoto(single bool) Photo {
|
|||
Cell: &UnknownLocation,
|
||||
Place: &UnknownPlace,
|
||||
}
|
||||
|
||||
if stackable {
|
||||
m.PhotoStack = IsStackable
|
||||
} else {
|
||||
m.PhotoStack = IsUnstacked
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// SavePhotoForm saves a model in the database using form data.
|
||||
|
|
|
@ -18,15 +18,15 @@ func (m *Photo) ResolvePrimary() error {
|
|||
|
||||
// Identical returns identical photos that can be merged.
|
||||
func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err error) {
|
||||
if m.PhotoSingle || m.PhotoName == "" {
|
||||
if m.PhotoStack == IsUnstacked || m.PhotoName == "" {
|
||||
return identical, nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case includeMeta && includeUuid && m.HasLocation() && m.HasLatLng() && m.TakenSrc == SrcMeta && rnd.IsUUID(m.UUID):
|
||||
if err := Db().
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND photo_single = 0 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
"OR (uuid = ? AND photo_single = 0)"+
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
"OR (uuid = ? AND photo_stack > -1)"+
|
||||
"OR (photo_path = ? AND photo_name = ?)",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.UUID, m.PhotoPath, m.PhotoName).
|
||||
Order("id ASC").Find(&identical).Error; err != nil {
|
||||
|
@ -34,7 +34,7 @@ func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err
|
|||
}
|
||||
case includeMeta && m.HasLocation() && m.HasLatLng() && m.TakenSrc == SrcMeta:
|
||||
if err := Db().
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND photo_single = 0 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
"OR (photo_path = ? AND photo_name = ?)",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.PhotoPath, m.PhotoName).
|
||||
Order("id ASC").Find(&identical).Error; err != nil {
|
||||
|
@ -42,7 +42,7 @@ func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err
|
|||
}
|
||||
case includeUuid && rnd.IsUUID(m.UUID):
|
||||
if err := Db().
|
||||
Where("(uuid = ? AND photo_single = 0) OR (photo_path = ? AND photo_name = ?)",
|
||||
Where("(uuid = ? AND photo_stack > -1) OR (photo_path = ? AND photo_name = ?)",
|
||||
m.UUID, m.PhotoPath, m.PhotoName).
|
||||
Order("id ASC").Find(&identical).Error; err != nil {
|
||||
return identical, err
|
||||
|
|
|
@ -33,9 +33,9 @@ type Photo struct {
|
|||
PhotoDescription string `json:"Description"`
|
||||
DescriptionSrc string `json:"DescriptionSrc"`
|
||||
Details Details `json:"Details"`
|
||||
PhotoStack int8 `json:"Stack"`
|
||||
PhotoFavorite bool `json:"Favorite"`
|
||||
PhotoPrivate bool `json:"Private"`
|
||||
PhotoSingle bool `json:"Single"`
|
||||
PhotoScan bool `json:"Scan"`
|
||||
PhotoPanorama bool `json:"Panorama"`
|
||||
PhotoAltitude int `json:"Altitude"`
|
||||
|
|
|
@ -6,60 +6,61 @@ import (
|
|||
|
||||
// PhotoSearch represents search form fields for "/api/v1/photos".
|
||||
type PhotoSearch struct {
|
||||
Query string `form:"q"`
|
||||
Filter string `form:"filter"`
|
||||
ID string `form:"id"`
|
||||
Type string `form:"type"`
|
||||
Path string `form:"path"`
|
||||
Folder string `form:"folder"` // Alias for Path
|
||||
Name string `form:"name"`
|
||||
Filename string `form:"filename"`
|
||||
Original string `form:"original"`
|
||||
Title string `form:"title"`
|
||||
Hash string `form:"hash"`
|
||||
Primary bool `form:"primary"`
|
||||
Single bool `form:"single"`
|
||||
Video bool `form:"video"`
|
||||
Photo bool `form:"photo"`
|
||||
Scan bool `form:"scan"`
|
||||
Panorama bool `form:"panorama"`
|
||||
Error bool `form:"error"`
|
||||
Hidden bool `form:"hidden"`
|
||||
Archived bool `form:"archived"`
|
||||
Public bool `form:"public"`
|
||||
Private bool `form:"private"`
|
||||
Favorite bool `form:"favorite"`
|
||||
Unsorted bool `form:"unsorted"`
|
||||
Stack bool `form:"stack"`
|
||||
Lat float32 `form:"lat"`
|
||||
Lng float32 `form:"lng"`
|
||||
Dist uint `form:"dist"`
|
||||
Fmin float32 `form:"fmin"`
|
||||
Fmax float32 `form:"fmax"`
|
||||
Chroma uint8 `form:"chroma"`
|
||||
Diff uint32 `form:"diff"`
|
||||
Mono bool `form:"mono"`
|
||||
Portrait bool `form:"portrait"`
|
||||
Geo bool `form:"geo"`
|
||||
Album string `form:"album"`
|
||||
Label string `form:"label"`
|
||||
Category string `form:"category"` // Moments
|
||||
Country string `form:"country"` // Moments
|
||||
State string `form:"state"` // Moments
|
||||
Year int `form:"year"` // Moments
|
||||
Month int `form:"month"` // Moments
|
||||
Day int `form:"day"` // Moments
|
||||
Color string `form:"color"`
|
||||
Quality int `form:"quality"`
|
||||
Review bool `form:"review"`
|
||||
Camera int `form:"camera"`
|
||||
Lens int `form:"lens"`
|
||||
Before time.Time `form:"before" time_format:"2006-01-02"`
|
||||
After time.Time `form:"after" time_format:"2006-01-02"`
|
||||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Merged bool `form:"merged" serialize:"-"`
|
||||
Query string `form:"q"`
|
||||
Filter string `form:"filter"`
|
||||
ID string `form:"id"`
|
||||
Type string `form:"type"`
|
||||
Path string `form:"path"`
|
||||
Folder string `form:"folder"` // Alias for Path
|
||||
Name string `form:"name"`
|
||||
Filename string `form:"filename"`
|
||||
Original string `form:"original"`
|
||||
Title string `form:"title"`
|
||||
Hash string `form:"hash"`
|
||||
Primary bool `form:"primary"`
|
||||
Stack bool `form:"stack"`
|
||||
Unstacked bool `form:"unstacked"`
|
||||
Stackable bool `form:"stackable"`
|
||||
Video bool `form:"video"`
|
||||
Photo bool `form:"photo"`
|
||||
Scan bool `form:"scan"`
|
||||
Panorama bool `form:"panorama"`
|
||||
Error bool `form:"error"`
|
||||
Hidden bool `form:"hidden"`
|
||||
Archived bool `form:"archived"`
|
||||
Public bool `form:"public"`
|
||||
Private bool `form:"private"`
|
||||
Favorite bool `form:"favorite"`
|
||||
Unsorted bool `form:"unsorted"`
|
||||
Lat float32 `form:"lat"`
|
||||
Lng float32 `form:"lng"`
|
||||
Dist uint `form:"dist"`
|
||||
Fmin float32 `form:"fmin"`
|
||||
Fmax float32 `form:"fmax"`
|
||||
Chroma uint8 `form:"chroma"`
|
||||
Diff uint32 `form:"diff"`
|
||||
Mono bool `form:"mono"`
|
||||
Portrait bool `form:"portrait"`
|
||||
Geo bool `form:"geo"`
|
||||
Album string `form:"album"`
|
||||
Label string `form:"label"`
|
||||
Category string `form:"category"` // Moments
|
||||
Country string `form:"country"` // Moments
|
||||
State string `form:"state"` // Moments
|
||||
Year int `form:"year"` // Moments
|
||||
Month int `form:"month"` // Moments
|
||||
Day int `form:"day"` // Moments
|
||||
Color string `form:"color"`
|
||||
Quality int `form:"quality"`
|
||||
Review bool `form:"review"`
|
||||
Camera int `form:"camera"`
|
||||
Lens int `form:"lens"`
|
||||
Before time.Time `form:"before" time_format:"2006-01-02"`
|
||||
After time.Time `form:"after" time_format:"2006-01-02"`
|
||||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Merged bool `form:"merged" serialize:"-"`
|
||||
}
|
||||
|
||||
func (f *PhotoSearch) GetQuery() string {
|
||||
|
|
|
@ -19,7 +19,7 @@ func TestNewPhoto(t *testing.T) {
|
|||
PhotoFavorite: false,
|
||||
PhotoPrivate: false,
|
||||
PhotoType: "image",
|
||||
PhotoSingle: false,
|
||||
PhotoStack: int8(1),
|
||||
PhotoLat: 9.9999,
|
||||
PhotoLng: 8.8888,
|
||||
PhotoAltitude: 2,
|
||||
|
@ -50,7 +50,7 @@ func TestNewPhoto(t *testing.T) {
|
|||
assert.Equal(t, false, r.PhotoFavorite)
|
||||
assert.Equal(t, false, r.PhotoPrivate)
|
||||
assert.Equal(t, "image", r.PhotoType)
|
||||
assert.Equal(t, false, r.PhotoSingle)
|
||||
assert.Equal(t, int8(1), r.PhotoStack)
|
||||
assert.Equal(t, float32(9.9999), r.PhotoLat)
|
||||
assert.Equal(t, float32(8.8888), r.PhotoLng)
|
||||
assert.Equal(t, 2, r.PhotoAltitude)
|
||||
|
|
|
@ -89,10 +89,10 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
|
||||
file, primaryFile := entity.File{}, entity.File{}
|
||||
|
||||
photo := entity.NewPhoto(o.Single)
|
||||
photo := entity.NewPhoto(o.Stack)
|
||||
metaData := meta.NewData()
|
||||
labels := classify.Labels{}
|
||||
stripSequence := Config().Settings().StackSequences() && !o.Single
|
||||
stripSequence := Config().Settings().StackSequences() && o.Stack
|
||||
|
||||
fileRoot, fileBase, filePath, fileName := m.PathNameInfo(stripSequence)
|
||||
fullBase := m.BasePrefix(false)
|
||||
|
@ -173,14 +173,14 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
|
||||
// Look for existing photo if file wasn't indexed yet...
|
||||
if !fileExists {
|
||||
if photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ?", filePath, fullBase); photoQuery.Error == nil || fileBase == fullBase || o.Single {
|
||||
if photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ?", filePath, fullBase); photoQuery.Error == nil || fileBase == fullBase || !o.Stack {
|
||||
// Skip next query.
|
||||
} else if photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ? AND photo_single = 0", filePath, fileBase); photoQuery.Error == nil {
|
||||
} else if photoQuery = entity.UnscopedDb().First(&photo, "photo_path = ? AND photo_name = ? AND photo_stack > -1", filePath, fileBase); photoQuery.Error == nil {
|
||||
fileStacked = true
|
||||
}
|
||||
|
||||
// Stack file based on matching location and time metadata?
|
||||
if !o.Single && photoQuery.Error != nil && Config().Settings().StackMeta() && m.MetaData().HasTimeAndPlace() {
|
||||
if o.Stack && photoQuery.Error != nil && Config().Settings().StackMeta() && m.MetaData().HasTimeAndPlace() {
|
||||
metaData = m.MetaData()
|
||||
photoQuery = entity.UnscopedDb().First(&photo, "photo_lat = ? AND photo_lng = ? AND taken_at = ? AND taken_src = 'meta' AND camera_serial = ?", metaData.Lat, metaData.Lng, metaData.TakenAt, metaData.CameraSerial)
|
||||
|
||||
|
@ -190,7 +190,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
}
|
||||
|
||||
// Stack file based on the same unique ID?
|
||||
if !o.Single && photoQuery.Error != nil && Config().Settings().StackUUID() && m.MetaData().HasDocumentID() {
|
||||
if o.Stack && photoQuery.Error != nil && Config().Settings().StackUUID() && m.MetaData().HasDocumentID() {
|
||||
photoQuery = entity.UnscopedDb().First(&photo, "uuid <> '' AND uuid = ?", m.MetaData().DocumentID)
|
||||
|
||||
if photoQuery.Error == nil {
|
||||
|
@ -229,7 +229,10 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
// Try to recover photo metadata from backup if not exists.
|
||||
if !photoExists {
|
||||
photo.PhotoQuality = -1
|
||||
photo.PhotoSingle = o.Single
|
||||
|
||||
if o.Stack {
|
||||
photo.PhotoStack = entity.IsStackable
|
||||
}
|
||||
|
||||
if yamlName := fs.FormatYaml.FindFirst(m.FileName(), []string{Config().SidecarPath(), fs.HiddenPath}, Config().OriginalsPath(), stripSequence); yamlName != "" {
|
||||
if err := photo.LoadFromYaml(yamlName); err != nil {
|
||||
|
@ -250,7 +253,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
|
||||
photo.PhotoPath = filePath
|
||||
|
||||
if o.Single || photo.PhotoSingle || !stripSequence {
|
||||
if !o.Stack || !stripSequence || photo.PhotoStack == entity.IsUnstacked {
|
||||
photo.PhotoName = fullBase
|
||||
} else {
|
||||
photo.PhotoName = fileBase
|
||||
|
@ -823,7 +826,7 @@ func (ind *Index) MediaFile(m *MediaFile, o IndexOptions, originalName string) (
|
|||
log.Errorf("index: %s in %s (set download id)", err, logName)
|
||||
}
|
||||
|
||||
if o.Single || photo.PhotoSingle {
|
||||
if !o.Stack || photo.PhotoStack == entity.IsUnstacked {
|
||||
// Do nothing.
|
||||
} else if original, merged, err := photo.Merge(Config().Settings().StackMeta(), Config().Settings().StackUUID()); err != nil {
|
||||
log.Errorf("index: %s in %s (merge)", err.Error(), logName)
|
||||
|
|
|
@ -4,7 +4,7 @@ type IndexOptions struct {
|
|||
Path string
|
||||
Rescan bool
|
||||
Convert bool
|
||||
Single bool
|
||||
Stack bool
|
||||
}
|
||||
|
||||
func (o *IndexOptions) SkipUnchanged() bool {
|
||||
|
@ -17,7 +17,7 @@ func IndexOptionsAll() IndexOptions {
|
|||
Path: "/",
|
||||
Rescan: true,
|
||||
Convert: true,
|
||||
Single: false,
|
||||
Stack: true,
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -29,7 +29,7 @@ func IndexOptionsSingle() IndexOptions {
|
|||
Path: "/",
|
||||
Rescan: true,
|
||||
Convert: true,
|
||||
Single: true,
|
||||
Stack: false,
|
||||
}
|
||||
|
||||
return result
|
||||
|
|
|
@ -31,8 +31,8 @@ type PhotoResult struct {
|
|||
PhotoMonth int `json:"Month"`
|
||||
PhotoDay int `json:"Day"`
|
||||
PhotoCountry string `json:"Country"`
|
||||
PhotoStack int8 `json:"Stack"`
|
||||
PhotoFavorite bool `json:"Favorite"`
|
||||
PhotoSingle bool `json:"Single"`
|
||||
PhotoPrivate bool `json:"Private"`
|
||||
PhotoIso int `json:"Iso"`
|
||||
PhotoFocalLength int `json:"FocalLength"`
|
||||
|
|
|
@ -201,8 +201,10 @@ func PhotoSearch(f form.PhotoSearch) (results PhotoResults, count int, err error
|
|||
s = s.Where("photos.photo_panorama = 1")
|
||||
}
|
||||
|
||||
if f.Single {
|
||||
s = s.Where("photos.photo_single = 1")
|
||||
if f.Stackable {
|
||||
s = s.Where("photos.photo_stack > -1")
|
||||
} else if f.Unstacked {
|
||||
s = s.Where("photos.photo_stack = -1")
|
||||
}
|
||||
|
||||
if f.Country != "" {
|
||||
|
|
Loading…
Reference in a new issue