mirror of
https://github.com/photoprism/photoprism.git
synced 2026-01-23 02:24:24 +00:00
Search: Add "reverse" query param to sort results in reverse order #683
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
66cd55461f
commit
88126e3e48
22 changed files with 212 additions and 68 deletions
|
|
@ -262,10 +262,13 @@ export default {
|
|||
|
||||
return "cards";
|
||||
},
|
||||
getSortOrder() {
|
||||
sortOrder() {
|
||||
const query = this.$route.query;
|
||||
return query["order"] ? query["order"] : this.model?.Order;
|
||||
},
|
||||
sortReverse() {
|
||||
return !!this.$route?.query["reverse"] && this.$route.query["reverse"] === "true";
|
||||
},
|
||||
openDate(index) {
|
||||
if (!this.canEdit) {
|
||||
return this.openPhoto(index);
|
||||
|
|
@ -325,7 +328,7 @@ export default {
|
|||
|
||||
if (showMerged) {
|
||||
this.$lightbox.openModels(Thumb.fromFiles([selected]), 0, this.model);
|
||||
} else if (this.getSortOrder() === "random") {
|
||||
} else if (this.sortOrder() === "random") {
|
||||
this.$lightbox.openModels(Thumb.fromPhotos(this.results), index, this.model);
|
||||
} else {
|
||||
this.$lightbox.openView(this, index);
|
||||
|
|
@ -353,7 +356,8 @@ export default {
|
|||
offset: offset,
|
||||
s: this.uid,
|
||||
merged: true,
|
||||
order: this.getSortOrder(),
|
||||
order: this.sortOrder(),
|
||||
reverse: this.sortReverse(),
|
||||
};
|
||||
|
||||
Object.assign(params, this.lastFilter);
|
||||
|
|
@ -474,7 +478,8 @@ export default {
|
|||
offset: this.offset,
|
||||
s: this.uid,
|
||||
merged: true,
|
||||
order: this.getSortOrder(),
|
||||
order: this.sortOrder(),
|
||||
reverse: this.sortReverse(),
|
||||
};
|
||||
|
||||
Object.assign(params, this.filter);
|
||||
|
|
|
|||
|
|
@ -396,10 +396,11 @@ export default {
|
|||
const query = this.$route.query;
|
||||
const routeName = this.$route.name;
|
||||
const order = this.sortOrder();
|
||||
const reverse = this.sortReverse();
|
||||
const q = query["q"] ? query["q"] : "";
|
||||
const category = query["category"] ? query["category"] : "";
|
||||
const year = query["year"] ? parseInt(query["year"]) : "";
|
||||
const filter = { q, category, order, year };
|
||||
const filter = { q, category, order, reverse, year };
|
||||
const settings = {};
|
||||
const features = this.$config.getSettings().features;
|
||||
|
||||
|
|
@ -503,6 +504,7 @@ export default {
|
|||
this.filter.category = query["category"] ? query["category"] : "";
|
||||
this.filter.year = query["year"] ? parseInt(query["year"]) : "";
|
||||
this.filter.order = this.sortOrder();
|
||||
this.filter.reverse = this.sortReverse();
|
||||
|
||||
this.search();
|
||||
},
|
||||
|
|
@ -627,6 +629,9 @@ export default {
|
|||
|
||||
return this.defaultOrder;
|
||||
},
|
||||
sortReverse() {
|
||||
return !!this.$route?.query["reverse"] && this.$route.query["reverse"] === "true";
|
||||
},
|
||||
searchCount() {
|
||||
const offset = parseInt(window.localStorage.getItem("albums.offset"));
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ export default {
|
|||
const label = query["label"] ? query["label"] : "";
|
||||
const latlng = query["latlng"] ? query["latlng"] : "";
|
||||
const view = this.getViewType();
|
||||
const order = this.getSortOrder();
|
||||
const order = this.sortOrder();
|
||||
const filter = {
|
||||
country: country,
|
||||
camera: camera,
|
||||
|
|
@ -128,6 +128,7 @@ export default {
|
|||
month: month,
|
||||
color: color,
|
||||
order: order,
|
||||
reverse: this.sortReverse(),
|
||||
q: q,
|
||||
};
|
||||
|
||||
|
|
@ -217,7 +218,8 @@ export default {
|
|||
this.filter.color = query["color"] ? query["color"] : "";
|
||||
this.filter.label = query["label"] ? query["label"] : "";
|
||||
this.filter.latlng = query["latlng"] ? query["latlng"] : "";
|
||||
this.filter.order = this.getSortOrder();
|
||||
this.filter.order = this.sortOrder();
|
||||
this.filter.reverse = this.sortReverse();
|
||||
|
||||
this.settings.view = this.getViewType();
|
||||
|
||||
|
|
@ -354,7 +356,7 @@ export default {
|
|||
|
||||
return "";
|
||||
},
|
||||
getSortOrder() {
|
||||
sortOrder() {
|
||||
if (this.embedded) {
|
||||
return "newest";
|
||||
}
|
||||
|
|
@ -396,6 +398,9 @@ export default {
|
|||
|
||||
return defaultOrder;
|
||||
},
|
||||
sortReverse() {
|
||||
return !!this.$route?.query["reverse"] && this.$route.query["reverse"] === "true";
|
||||
},
|
||||
openDate(index) {
|
||||
const photo = this.results[index];
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ func AlbumCoverByUID(uid string, public bool) (file entity.File, err error) {
|
|||
// Automatically hide empty months.
|
||||
switch a.AlbumType {
|
||||
case entity.AlbumMonth, entity.AlbumState:
|
||||
if err := a.Delete(); err != nil {
|
||||
if err = a.Delete(); err != nil {
|
||||
log.Errorf("%s: %s (hide)", a.AlbumType, err)
|
||||
} else {
|
||||
log.Infof("%s: %s hidden", a.AlbumType, clean.Log(a.AlbumTitle))
|
||||
|
|
|
|||
|
|
@ -78,57 +78,57 @@ func UserAlbums(frm form.SearchAlbums, sess *entity.Session) (results AlbumResul
|
|||
// Set sort order.
|
||||
switch frm.Order {
|
||||
case sortby.Count:
|
||||
s = s.Order("photo_count DESC, albums.album_title, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("photo_count DESC, albums.album_title, albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Moment, sortby.Newest:
|
||||
if frm.Type == entity.AlbumManual || frm.Type == entity.AlbumState {
|
||||
s = s.Order("albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_uid DESC", frm.Reverse))
|
||||
} else if frm.Type == entity.AlbumMoment {
|
||||
s = s.Order("has_year, albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("has_year, albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC", frm.Reverse))
|
||||
} else {
|
||||
s = s.Order("albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC", frm.Reverse))
|
||||
}
|
||||
case sortby.Oldest:
|
||||
if frm.Type == entity.AlbumManual || frm.Type == entity.AlbumState {
|
||||
s = s.Order("albums.album_uid ASC")
|
||||
s = s.Order(OrderExpr("albums.album_uid ASC", frm.Reverse))
|
||||
} else if frm.Type == entity.AlbumMoment {
|
||||
s = s.Order("has_year, albums.album_year ASC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid ASC")
|
||||
s = s.Order(OrderExpr("has_year, albums.album_year ASC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid ASC", frm.Reverse))
|
||||
} else {
|
||||
s = s.Order("albums.album_year ASC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid ASC")
|
||||
s = s.Order(OrderExpr("albums.album_year ASC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid ASC", frm.Reverse))
|
||||
}
|
||||
case sortby.Added:
|
||||
s = s.Order("albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Edited:
|
||||
s = s.Order("albums.updated_at DESC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.updated_at DESC, albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Place:
|
||||
s = s.Order("no_location, albums.album_location, has_year, albums.album_year DESC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("no_location, albums.album_location, has_year, albums.album_year DESC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Path:
|
||||
s = s.Order("albums.album_path, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_path, albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Category:
|
||||
s = s.Order("albums.album_category, albums.album_title, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_category, albums.album_title, albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Slug:
|
||||
s = s.Order("albums.album_slug ASC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_slug ASC, albums.album_uid DESC", frm.Reverse))
|
||||
case sortby.Favorites:
|
||||
if frm.Type == entity.AlbumFolder {
|
||||
s = s.Order("albums.album_favorite DESC, albums.album_path ASC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_favorite DESC, albums.album_path ASC, albums.album_uid DESC", frm.Reverse))
|
||||
} else if frm.Type == entity.AlbumMonth {
|
||||
s = s.Order("albums.album_favorite DESC, albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_favorite DESC, albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC", frm.Reverse))
|
||||
} else {
|
||||
s = s.Order("albums.album_favorite DESC, albums.album_title ASC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_favorite DESC, albums.album_title ASC, albums.album_uid DESC", frm.Reverse))
|
||||
}
|
||||
case sortby.Name:
|
||||
if frm.Type == entity.AlbumFolder {
|
||||
s = s.Order("albums.album_path ASC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_path ASC, albums.album_uid DESC", frm.Reverse))
|
||||
} else {
|
||||
s = s.Order("albums.album_title ASC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_title ASC, albums.album_uid DESC", frm.Reverse))
|
||||
}
|
||||
case sortby.NameReverse:
|
||||
if frm.Type == entity.AlbumFolder {
|
||||
s = s.Order("albums.album_path DESC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_path DESC, albums.album_uid DESC", frm.Reverse))
|
||||
} else {
|
||||
s = s.Order("albums.album_title DESC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_title DESC, albums.album_uid DESC", frm.Reverse))
|
||||
}
|
||||
default:
|
||||
s = s.Order("albums.album_favorite DESC, albums.album_title ASC, albums.album_uid DESC")
|
||||
s = s.Order(OrderExpr("albums.album_favorite DESC, albums.album_title ASC, albums.album_uid DESC", frm.Reverse))
|
||||
}
|
||||
|
||||
// Find specific UIDs only?
|
||||
|
|
|
|||
|
|
@ -62,13 +62,13 @@ func Faces(frm form.SearchFaces) (results FaceResults, err error) {
|
|||
// Set sort order.
|
||||
switch frm.Order {
|
||||
case "subject":
|
||||
s = s.Order(fmt.Sprintf("%s.subj_uid", facesTable))
|
||||
s = s.Order(OrderExpr(fmt.Sprintf("%s.subj_uid ASC", facesTable), frm.Reverse))
|
||||
case "added":
|
||||
s = s.Order(fmt.Sprintf("%s.created_at DESC", facesTable))
|
||||
s = s.Order(OrderExpr(fmt.Sprintf("%s.created_at DESC", facesTable), frm.Reverse))
|
||||
case "samples":
|
||||
s = s.Order(fmt.Sprintf("%s.samples DESC, %s.id", facesTable, facesTable))
|
||||
s = s.Order(OrderExpr(fmt.Sprintf("%s.samples DESC, %s.id", facesTable, facesTable), frm.Reverse))
|
||||
default:
|
||||
s = s.Order(fmt.Sprintf("%s.samples DESC, %s.id", facesTable, facesTable))
|
||||
s = s.Order(OrderExpr(fmt.Sprintf("%s.samples DESC, %s.id", facesTable, facesTable), frm.Reverse))
|
||||
}
|
||||
|
||||
// Find specific IDs?
|
||||
|
|
|
|||
10
internal/entity/search/order.go
Normal file
10
internal/entity/search/order.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"github.com/photoprism/photoprism/internal/entity/sortby"
|
||||
)
|
||||
|
||||
// OrderExpr replaces "ASC" with "DESC" and "DESC" with "ASC" in the specified query order string if reverse is true.
|
||||
func OrderExpr(s string, reverse bool) string {
|
||||
return sortby.OrderExpr(s, reverse)
|
||||
}
|
||||
24
internal/entity/search/order_test.go
Normal file
24
internal/entity/search/order_test.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOrderExpr(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
assert.Equal(t, "", OrderExpr("", false))
|
||||
assert.Equal(t, "photos.edited_at", OrderExpr("photos.edited_at", false))
|
||||
assert.Equal(t, "photos.edited_at ASC", OrderExpr("photos.edited_at ASC", false))
|
||||
assert.Equal(t, "photos.edited_at DESC, files.media_id", OrderExpr("photos.edited_at DESC, files.media_id", false))
|
||||
assert.Equal(t, "photos.edited_at DESC, files.media_id ASC", OrderExpr("photos.edited_at DESC, files.media_id ASC", false))
|
||||
})
|
||||
t.Run("Reverse", func(t *testing.T) {
|
||||
assert.Equal(t, "", OrderExpr("", true))
|
||||
assert.Equal(t, "photos.edited_at", OrderExpr("photos.edited_at", true))
|
||||
assert.Equal(t, "photos.edited_at DESC", OrderExpr("photos.edited_at ASC", true))
|
||||
assert.Equal(t, "photos.edited_at ASC, files.media_id", OrderExpr("photos.edited_at DESC, files.media_id", true))
|
||||
assert.Equal(t, "photos.edited_at ASC, files.media_id DESC", OrderExpr("photos.edited_at DESC, files.media_id ASC", true))
|
||||
})
|
||||
}
|
||||
|
|
@ -180,36 +180,36 @@ func searchPhotos(frm form.SearchPhotos, sess *entity.Session, resultCols string
|
|||
// Set sort order.
|
||||
switch frm.Order {
|
||||
case sortby.Edited:
|
||||
s = s.Where("photos.edited_at IS NOT NULL").Order("photos.edited_at DESC, files.media_id")
|
||||
s = s.Where("photos.edited_at IS NOT NULL").Order(OrderExpr("photos.edited_at DESC, files.media_id", frm.Reverse))
|
||||
case sortby.Updated, sortby.UpdatedAt:
|
||||
s = s.Where("photos.updated_at > photos.created_at").Order("photos.updated_at DESC, files.media_id")
|
||||
s = s.Where("photos.updated_at > photos.created_at").Order(OrderExpr("photos.updated_at DESC, files.media_id", frm.Reverse))
|
||||
case sortby.Archived:
|
||||
s = s.Order("photos.deleted_at DESC, files.media_id")
|
||||
s = s.Order(OrderExpr("photos.deleted_at DESC, files.media_id", frm.Reverse))
|
||||
case sortby.Relevance:
|
||||
if frm.Label != "" {
|
||||
s = s.Order("photos.photo_quality DESC, photos_labels.uncertainty ASC, files.time_index")
|
||||
s = s.Order(OrderExpr("photos.photo_quality DESC, photos_labels.uncertainty ASC, files.time_index", frm.Reverse))
|
||||
} else {
|
||||
s = s.Order("photos.photo_quality DESC, files.time_index")
|
||||
s = s.Order(OrderExpr("photos.photo_quality DESC, files.time_index", frm.Reverse))
|
||||
}
|
||||
case sortby.Duration:
|
||||
s = s.Order("photos.photo_duration DESC, files.time_index")
|
||||
s = s.Order(OrderExpr("photos.photo_duration DESC, files.time_index", frm.Reverse))
|
||||
case sortby.Size:
|
||||
s = s.Order("files.file_size DESC, files.time_index")
|
||||
s = s.Order(OrderExpr("files.file_size DESC, files.time_index", frm.Reverse))
|
||||
case sortby.Newest:
|
||||
s = s.Order("files.time_index")
|
||||
s = s.Order(OrderExpr("files.time_index", frm.Reverse))
|
||||
case sortby.Oldest:
|
||||
s = s.Order("files.photo_taken_at, files.media_id")
|
||||
s = s.Order(OrderExpr("files.photo_taken_at ASC, files.media_id", frm.Reverse))
|
||||
case sortby.Similar:
|
||||
s = s.Where("files.file_diff > 0")
|
||||
s = s.Order("photos.photo_color, photos.cell_id, files.file_diff, files.photo_id, files.time_index")
|
||||
s = s.Order(OrderExpr("photos.photo_color ASC, photos.cell_id ASC, files.file_diff, files.photo_id, files.time_index", frm.Reverse))
|
||||
case sortby.Name:
|
||||
s = s.Order("photos.photo_path, photos.photo_name, files.time_index")
|
||||
s = s.Order(OrderExpr("photos.photo_path ASC, photos.photo_name ASC, files.time_index", frm.Reverse))
|
||||
case sortby.Title:
|
||||
s = s.Order("photos.photo_title, photos.photo_name, files.time_index")
|
||||
s = s.Order(OrderExpr("photos.photo_title ASC, photos.photo_name ASC, files.time_index", frm.Reverse))
|
||||
case sortby.Random:
|
||||
s = s.Order(sortby.RandomExpr(s.Dialect()))
|
||||
case sortby.Default, sortby.Imported, sortby.Added:
|
||||
s = s.Order("files.media_id")
|
||||
s = s.Order(OrderExpr("files.media_id", frm.Reverse))
|
||||
default:
|
||||
return PhotoResults{}, 0, ErrBadSortOrder
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,17 +57,19 @@ func Sessions(frm form.SearchSessions) (result entity.Sessions, err error) {
|
|||
// Sort results?
|
||||
switch order {
|
||||
case sortby.LastActive:
|
||||
stmt = stmt.Order("last_active DESC, user_name, client_name, id")
|
||||
stmt = stmt.Order(OrderExpr("last_active DESC, user_name, client_name, id", frm.Reverse))
|
||||
case sortby.SessExpires:
|
||||
stmt = stmt.Order("sess_expires DESC, user_name, client_name, id")
|
||||
stmt = stmt.Order(OrderExpr("sess_expires DESC, user_name, client_name, id", frm.Reverse))
|
||||
case sortby.ClientName:
|
||||
stmt = stmt.Where("client_name <> '' AND client_name IS NOT NULL").Order("client_name, created_at, id")
|
||||
stmt = stmt.
|
||||
Where("client_name <> '' AND client_name IS NOT NULL").
|
||||
Order(OrderExpr("client_name, created_at, id", frm.Reverse))
|
||||
case sortby.Login, sortby.LoginAt:
|
||||
stmt = stmt.Order("login_at DESC, user_name, client_name, id")
|
||||
stmt = stmt.Order(OrderExpr("login_at DESC, user_name, client_name, id", frm.Reverse))
|
||||
case sortby.Created, sortby.CreatedAt:
|
||||
stmt = stmt.Order("created_at ASC, user_name, client_name, id")
|
||||
stmt = stmt.Order(OrderExpr("created_at ASC, user_name, client_name, id", frm.Reverse))
|
||||
case sortby.Updated, sortby.UpdatedAt:
|
||||
stmt = stmt.Order("updated_at DESC, user_name, client_name, id")
|
||||
stmt = stmt.Order(OrderExpr("updated_at DESC, user_name, client_name, id", frm.Reverse))
|
||||
default:
|
||||
return result, fmt.Errorf("invalid sort order %s", order)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@ func Subjects(frm form.SearchSubjects) (results SubjectResults, err error) {
|
|||
// Set sort order.
|
||||
switch frm.Order {
|
||||
case "name":
|
||||
s = s.Order("subj_name")
|
||||
s = s.Order(OrderExpr("subj_name ASC", frm.Reverse))
|
||||
case "count":
|
||||
s = s.Order("file_count DESC")
|
||||
s = s.Order(OrderExpr("file_count DESC", frm.Reverse))
|
||||
case "added":
|
||||
s = s.Order(fmt.Sprintf("%s.created_at DESC", subjTable))
|
||||
s = s.Order(OrderExpr(fmt.Sprintf("%s.created_at DESC", subjTable), frm.Reverse))
|
||||
case "relevance":
|
||||
s = s.Order("subj_favorite DESC, photo_count DESC")
|
||||
s = s.Order(OrderExpr("subj_favorite DESC, photo_count DESC", frm.Reverse))
|
||||
default:
|
||||
s = s.Order("subj_favorite DESC, subj_name")
|
||||
s = s.Order(OrderExpr("subj_favorite DESC, subj_name ASC", frm.Reverse))
|
||||
}
|
||||
|
||||
if frm.UID != "" {
|
||||
|
|
|
|||
|
|
@ -60,21 +60,21 @@ func Users(frm form.SearchUsers) (result entity.Users, err error) {
|
|||
|
||||
switch sortOrder {
|
||||
case sortby.Name:
|
||||
sortOrder = "user_name, id"
|
||||
sortOrder = OrderExpr("user_name ASC, id ASC", frm.Reverse)
|
||||
case sortby.DisplayName:
|
||||
sortOrder = "display_name, id"
|
||||
sortOrder = OrderExpr("display_name ASC, id ASC", frm.Reverse)
|
||||
case sortby.Login, sortby.LoginAt:
|
||||
sortOrder = "login_at DESC, id"
|
||||
sortOrder = OrderExpr("login_at DESC, id ASC", frm.Reverse)
|
||||
case sortby.Created, sortby.CreatedAt:
|
||||
sortOrder = "created_at ASC, id"
|
||||
sortOrder = OrderExpr("created_at ASC, id ASC", frm.Reverse)
|
||||
case sortby.Updated, sortby.UpdatedAt:
|
||||
sortOrder = "updated_at DESC, id"
|
||||
sortOrder = OrderExpr("updated_at DESC, id ASC", frm.Reverse)
|
||||
case sortby.Deleted, sortby.DeletedAt:
|
||||
sortOrder = "deleted_at DESC, created_at DESC, id"
|
||||
sortOrder = OrderExpr("deleted_at DESC, created_at DESC, id ASC", frm.Reverse)
|
||||
case sortby.Email:
|
||||
sortOrder = "user_email, id"
|
||||
sortOrder = OrderExpr("user_email ASC, id ASC", frm.Reverse)
|
||||
default:
|
||||
sortOrder = "user_name, id"
|
||||
sortOrder = OrderExpr("user_name ASC, id ASC", frm.Reverse)
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
|
|
|
|||
44
internal/entity/sortby/order.go
Normal file
44
internal/entity/sortby/order.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package sortby
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Sort direction strings.
|
||||
const (
|
||||
DirAsc = "ASC"
|
||||
DirDesc = "DESC"
|
||||
)
|
||||
|
||||
// OrderReplacer replaces "ASC" with "DESC" and "DESC" with "ASC"
|
||||
var OrderReplacer = strings.NewReplacer(DirAsc, DirDesc, DirDesc, DirAsc)
|
||||
|
||||
// OrderExpr replaces "ASC" with "DESC" and "DESC" with "ASC" in the specified query order string if reverse is true.
|
||||
func OrderExpr(s string, reverse bool) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
} else if reverse {
|
||||
return OrderReplacer.Replace(s)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// OrderAsc returns the expression used for sorting in ascending order.
|
||||
func OrderAsc(reverse bool) string {
|
||||
if reverse {
|
||||
return DirDesc
|
||||
}
|
||||
|
||||
return DirAsc
|
||||
|
||||
}
|
||||
|
||||
// OrderDesc returns the expression used for sorting in descending order.
|
||||
func OrderDesc(reverse bool) string {
|
||||
if reverse {
|
||||
return DirAsc
|
||||
}
|
||||
|
||||
return DirDesc
|
||||
}
|
||||
42
internal/entity/sortby/order_test.go
Normal file
42
internal/entity/sortby/order_test.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package sortby
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOrderExpr(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
assert.Equal(t, "", OrderExpr("", false))
|
||||
assert.Equal(t, "photos.edited_at", OrderExpr("photos.edited_at", false))
|
||||
assert.Equal(t, "photos.edited_at ASC", OrderExpr("photos.edited_at ASC", false))
|
||||
assert.Equal(t, "photos.edited_at DESC, files.media_id", OrderExpr("photos.edited_at DESC, files.media_id", false))
|
||||
assert.Equal(t, "photos.edited_at DESC, files.media_id ASC", OrderExpr("photos.edited_at DESC, files.media_id ASC", false))
|
||||
})
|
||||
t.Run("Reverse", func(t *testing.T) {
|
||||
assert.Equal(t, "", OrderExpr("", true))
|
||||
assert.Equal(t, "photos.edited_at", OrderExpr("photos.edited_at", true))
|
||||
assert.Equal(t, "photos.edited_at DESC", OrderExpr("photos.edited_at ASC", true))
|
||||
assert.Equal(t, "photos.edited_at ASC, files.media_id", OrderExpr("photos.edited_at DESC, files.media_id", true))
|
||||
assert.Equal(t, "photos.edited_at ASC, files.media_id DESC", OrderExpr("photos.edited_at DESC, files.media_id ASC", true))
|
||||
})
|
||||
}
|
||||
|
||||
func TestOrderAsc(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
assert.Equal(t, DirAsc, OrderAsc(false))
|
||||
})
|
||||
t.Run("Reverse", func(t *testing.T) {
|
||||
assert.Equal(t, DirDesc, OrderAsc(true))
|
||||
})
|
||||
}
|
||||
|
||||
func TestOrderDesc(t *testing.T) {
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
assert.Equal(t, DirDesc, OrderDesc(false))
|
||||
})
|
||||
t.Run("Reverse", func(t *testing.T) {
|
||||
assert.Equal(t, DirAsc, OrderDesc(true))
|
||||
})
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ type SearchAlbums struct {
|
|||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Reverse bool `form:"reverse" serialize:"-"`
|
||||
}
|
||||
|
||||
func (f *SearchAlbums) GetQuery() string {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type SearchFaces struct {
|
|||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Reverse bool `form:"reverse" serialize:"-"`
|
||||
}
|
||||
|
||||
func (f *SearchFaces) GetQuery() string {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type SearchLabels struct {
|
|||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Reverse bool `form:"reverse" serialize:"-"`
|
||||
}
|
||||
|
||||
func (f *SearchLabels) GetQuery() string {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ type SearchPhotos struct {
|
|||
Count int `form:"count" binding:"required" serialize:"-"` // Result FILE limit
|
||||
Offset int `form:"offset" serialize:"-"` // Result FILE offset
|
||||
Order string `form:"order" serialize:"-"` // Sort order
|
||||
Reverse bool `form:"reverse" serialize:"-"` // Merge FILES in response
|
||||
Merged bool `form:"merged" serialize:"-"` // Merge FILES in response
|
||||
Details bool `form:"-" serialize:"-"` // Include additional information from details table
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ type SearchSessions struct {
|
|||
UID string `form:"uid"`
|
||||
Provider string `form:"provider"`
|
||||
Method string `form:"method"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Reverse bool `form:"reverse" serialize:"-"`
|
||||
}
|
||||
|
||||
// AuthProviders returns the normalized authentication provider types.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type SearchSubjects struct {
|
|||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Reverse bool `form:"reverse" serialize:"-"`
|
||||
}
|
||||
|
||||
func (f *SearchSubjects) GetQuery() string {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ type SearchUsers struct {
|
|||
Email string `form:"email"`
|
||||
All bool `form:"all"`
|
||||
Deleted bool `form:"deleted"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Count int `form:"count" binding:"required" serialize:"-"`
|
||||
Offset int `form:"offset" serialize:"-"`
|
||||
Order string `form:"order" serialize:"-"`
|
||||
Reverse bool `form:"reverse" serialize:"-"`
|
||||
}
|
||||
|
||||
func (f *SearchUsers) GetQuery() string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue