mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Accept random seed from UI for random sorting (#328)
This commit is contained in:
@@ -93,6 +93,8 @@ func getSort(sort string, direction string, tableName string) string {
|
|||||||
direction = "ASC"
|
direction = "ASC"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const randomSeedPrefix = "random_"
|
||||||
|
|
||||||
if strings.Contains(sort, "_count") {
|
if strings.Contains(sort, "_count") {
|
||||||
var relationTableName = strings.Split(sort, "_")[0] // TODO: pluralize?
|
var relationTableName = strings.Split(sort, "_")[0] // TODO: pluralize?
|
||||||
colName := getColumn(relationTableName, "id")
|
colName := getColumn(relationTableName, "id")
|
||||||
@@ -100,12 +102,18 @@ func getSort(sort string, direction string, tableName string) string {
|
|||||||
} else if strings.Compare(sort, "filesize") == 0 {
|
} else if strings.Compare(sort, "filesize") == 0 {
|
||||||
colName := getColumn(tableName, "size")
|
colName := getColumn(tableName, "size")
|
||||||
return " ORDER BY cast(" + colName + " as integer) " + direction
|
return " ORDER BY cast(" + colName + " as integer) " + direction
|
||||||
|
} else if strings.HasPrefix(sort, randomSeedPrefix) {
|
||||||
|
// seed as a parameter from the UI
|
||||||
|
// turn the provided seed into a float
|
||||||
|
seedStr := "0." + sort[len(randomSeedPrefix):]
|
||||||
|
seed, err := strconv.ParseFloat(seedStr, 32)
|
||||||
|
if err != nil {
|
||||||
|
// fallback to default seed
|
||||||
|
seed = randomSortFloat
|
||||||
|
}
|
||||||
|
return getRandomSort(tableName, direction, seed)
|
||||||
} else if strings.Compare(sort, "random") == 0 {
|
} else if strings.Compare(sort, "random") == 0 {
|
||||||
// https://stackoverflow.com/a/24511461
|
return getRandomSort(tableName, direction, randomSortFloat)
|
||||||
// TODO seed as a parameter from the UI
|
|
||||||
colName := getColumn(tableName, "id")
|
|
||||||
randomSortString := strconv.FormatFloat(randomSortFloat, 'f', 16, 32)
|
|
||||||
return " ORDER BY " + "(substr(" + colName + " * " + randomSortString + ", length(" + colName + ") + 2))" + " " + direction
|
|
||||||
} else {
|
} else {
|
||||||
colName := getColumn(tableName, sort)
|
colName := getColumn(tableName, sort)
|
||||||
var additional string
|
var additional string
|
||||||
@@ -122,6 +130,13 @@ func getSort(sort string, direction string, tableName string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRandomSort(tableName string, direction string, seed float64) string {
|
||||||
|
// https://stackoverflow.com/a/24511461
|
||||||
|
colName := getColumn(tableName, "id")
|
||||||
|
randomSortString := strconv.FormatFloat(seed, 'f', 16, 32)
|
||||||
|
return " ORDER BY " + "(substr(" + colName + " * " + randomSortString + ", length(" + colName + ") + 2))" + " " + direction
|
||||||
|
}
|
||||||
|
|
||||||
func getSearch(columns []string, q string) string {
|
func getSearch(columns []string, q string) string {
|
||||||
// TODO - susceptible to SQL injection
|
// TODO - susceptible to SQL injection
|
||||||
var likeClauses []string
|
var likeClauses []string
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export class ListFilterModel {
|
|||||||
public criterionOptions: ICriterionOption[] = [];
|
public criterionOptions: ICriterionOption[] = [];
|
||||||
public criteria: Array<Criterion<any, any>> = [];
|
public criteria: Array<Criterion<any, any>> = [];
|
||||||
public totalCount: number = 0;
|
public totalCount: number = 0;
|
||||||
|
public randomSeed: number = -1;
|
||||||
|
|
||||||
private static createCriterionOption(criterion: CriterionType) {
|
private static createCriterionOption(criterion: CriterionType) {
|
||||||
return new CriterionOption(Criterion.getLabel(criterion), criterion);
|
return new CriterionOption(Criterion.getLabel(criterion), criterion);
|
||||||
@@ -153,6 +154,19 @@ export class ListFilterModel {
|
|||||||
const params = rawParms as IQueryParameters;
|
const params = rawParms as IQueryParameters;
|
||||||
if (params.sortby !== undefined) {
|
if (params.sortby !== undefined) {
|
||||||
this.sortBy = params.sortby;
|
this.sortBy = params.sortby;
|
||||||
|
|
||||||
|
// parse the random seed if provided
|
||||||
|
const randomPrefix = "random_";
|
||||||
|
if (this.sortBy && this.sortBy.startsWith(randomPrefix)) {
|
||||||
|
let seedStr = this.sortBy.substring(randomPrefix.length);
|
||||||
|
|
||||||
|
this.sortBy = "random";
|
||||||
|
try {
|
||||||
|
this.randomSeed = Number.parseInt(seedStr);
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (params.sortdir === "asc" || params.sortdir === "desc") {
|
if (params.sortdir === "asc" || params.sortdir === "desc") {
|
||||||
this.sortDirection = params.sortdir;
|
this.sortDirection = params.sortdir;
|
||||||
@@ -187,6 +201,28 @@ export class ListFilterModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setRandomSeed() {
|
||||||
|
if (this.sortBy == "random") {
|
||||||
|
// #321 - set the random seed if it is not set
|
||||||
|
if (this.randomSeed == -1) {
|
||||||
|
// generate 8-digit seed
|
||||||
|
this.randomSeed = Math.floor(Math.random() * Math.pow(10, 8));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.randomSeed = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSortBy(): string | undefined {
|
||||||
|
this.setRandomSeed();
|
||||||
|
|
||||||
|
if (this.sortBy == "random") {
|
||||||
|
return this.sortBy + "_" + this.randomSeed.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sortBy;
|
||||||
|
}
|
||||||
|
|
||||||
public makeQueryParameters(): string {
|
public makeQueryParameters(): string {
|
||||||
const encodedCriteria: string[] = [];
|
const encodedCriteria: string[] = [];
|
||||||
this.criteria.forEach((criterion) => {
|
this.criteria.forEach((criterion) => {
|
||||||
@@ -198,8 +234,9 @@ export class ListFilterModel {
|
|||||||
encodedCriteria.push(jsonCriterion);
|
encodedCriteria.push(jsonCriterion);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
sortby: this.sortBy,
|
sortby: this.getSortBy(),
|
||||||
sortdir: this.sortDirection,
|
sortdir: this.sortDirection,
|
||||||
disp: this.displayMode,
|
disp: this.displayMode,
|
||||||
q: this.searchTerm,
|
q: this.searchTerm,
|
||||||
@@ -216,7 +253,7 @@ export class ListFilterModel {
|
|||||||
q: this.searchTerm,
|
q: this.searchTerm,
|
||||||
page: this.currentPage,
|
page: this.currentPage,
|
||||||
per_page: this.itemsPerPage,
|
per_page: this.itemsPerPage,
|
||||||
sort: this.sortBy,
|
sort: this.getSortBy(),
|
||||||
direction: this.sortDirection === "asc" ? SortDirectionEnum.Asc : SortDirectionEnum.Desc,
|
direction: this.sortDirection === "asc" ? SortDirectionEnum.Asc : SortDirectionEnum.Desc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user