mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Fix age filtering regression (#778)
* Show filter control in loading/error * Add performer age unit tests * Fix addWhere regression
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
@@ -207,6 +208,46 @@ func TestPerformerDestroyPerformerImage(t *testing.T) {
|
|||||||
assert.Nil(t, storedImage)
|
assert.Nil(t, storedImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPerformerQueryAge(t *testing.T) {
|
||||||
|
const age = 19
|
||||||
|
ageCriterion := models.IntCriterionInput{
|
||||||
|
Value: age,
|
||||||
|
Modifier: models.CriterionModifierEquals,
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyPerformerAge(t, ageCriterion)
|
||||||
|
|
||||||
|
ageCriterion.Modifier = models.CriterionModifierNotEquals
|
||||||
|
verifyPerformerAge(t, ageCriterion)
|
||||||
|
|
||||||
|
ageCriterion.Modifier = models.CriterionModifierGreaterThan
|
||||||
|
verifyPerformerAge(t, ageCriterion)
|
||||||
|
|
||||||
|
ageCriterion.Modifier = models.CriterionModifierLessThan
|
||||||
|
verifyPerformerAge(t, ageCriterion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyPerformerAge(t *testing.T, ageCriterion models.IntCriterionInput) {
|
||||||
|
qb := models.NewPerformerQueryBuilder()
|
||||||
|
performerFilter := models.PerformerFilterType{
|
||||||
|
Age: &ageCriterion,
|
||||||
|
}
|
||||||
|
|
||||||
|
performers, _ := qb.Query(&performerFilter, nil)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
for _, performer := range performers {
|
||||||
|
bd := performer.Birthdate.String
|
||||||
|
d, _ := time.Parse("2006-01-02", bd)
|
||||||
|
age := now.Year() - d.Year()
|
||||||
|
if now.YearDay() < d.YearDay() {
|
||||||
|
age = age - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyInt(t, age, ageCriterion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Update
|
// TODO Update
|
||||||
// TODO Destroy
|
// TODO Destroy
|
||||||
// TODO Find
|
// TODO Find
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ func verifyScenesOCounter(t *testing.T, oCounterCriterion models.IntCriterionInp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func verifyInt(t *testing.T, value int, criterion models.IntCriterionInput) {
|
func verifyInt(t *testing.T, value int, criterion models.IntCriterionInput) {
|
||||||
|
t.Helper()
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
if criterion.Modifier == models.CriterionModifierEquals {
|
if criterion.Modifier == models.CriterionModifierEquals {
|
||||||
assert.Equal(criterion.Value, value)
|
assert.Equal(criterion.Value, value)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func (qb queryBuilder) executeFind() ([]int, int) {
|
|||||||
func (qb *queryBuilder) addWhere(clauses ...string) {
|
func (qb *queryBuilder) addWhere(clauses ...string) {
|
||||||
for _, clause := range clauses {
|
for _, clause := range clauses {
|
||||||
if len(clause) > 0 {
|
if len(clause) > 0 {
|
||||||
qb.whereClauses = append(qb.whereClauses, clauses...)
|
qb.whereClauses = append(qb.whereClauses, clause)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
||||||
@@ -370,6 +371,13 @@ func getPerformerBoolValue(index int) bool {
|
|||||||
return index == 1
|
return index == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getPerformerBirthdate(index int) string {
|
||||||
|
const minAge = 18
|
||||||
|
birthdate := time.Now()
|
||||||
|
birthdate = birthdate.AddDate(-minAge-index, -1, -1)
|
||||||
|
return birthdate.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
|
||||||
//createPerformers creates n performers with plain Name and o performers with camel cased NaMe included
|
//createPerformers creates n performers with plain Name and o performers with camel cased NaMe included
|
||||||
func createPerformers(tx *sqlx.Tx, n int, o int) error {
|
func createPerformers(tx *sqlx.Tx, n int, o int) error {
|
||||||
pqb := models.NewPerformerQueryBuilder()
|
pqb := models.NewPerformerQueryBuilder()
|
||||||
@@ -391,6 +399,10 @@ func createPerformers(tx *sqlx.Tx, n int, o int) error {
|
|||||||
Name: sql.NullString{String: getPerformerStringValue(index, name), Valid: true},
|
Name: sql.NullString{String: getPerformerStringValue(index, name), Valid: true},
|
||||||
Checksum: getPerformerStringValue(i, checksumField),
|
Checksum: getPerformerStringValue(i, checksumField),
|
||||||
Favorite: sql.NullBool{Bool: getPerformerBoolValue(i), Valid: true},
|
Favorite: sql.NullBool{Bool: getPerformerBoolValue(i), Valid: true},
|
||||||
|
Birthdate: models.SQLiteDate{
|
||||||
|
String: getPerformerBirthdate(i),
|
||||||
|
Valid: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := pqb.Create(performer, tx)
|
created, err := pqb.Create(performer, tx)
|
||||||
|
|||||||
@@ -333,38 +333,13 @@ const RenderList = <
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
let content;
|
function maybeRenderContent() {
|
||||||
if (result.loading) {
|
if (result.loading || result.error) {
|
||||||
content = <LoadingIndicator />;
|
return;
|
||||||
} else if (result.error) {
|
}
|
||||||
content = <h1>{result.error.message}</h1>;
|
|
||||||
} else {
|
return (
|
||||||
content = (
|
<>
|
||||||
<div>
|
|
||||||
<ListFilter
|
|
||||||
onFilterUpdate={updateQueryParams}
|
|
||||||
onSelectAll={selectable ? onSelectAll : undefined}
|
|
||||||
onSelectNone={selectable ? onSelectNone : undefined}
|
|
||||||
zoomIndex={zoomable ? zoomIndex : undefined}
|
|
||||||
onChangeZoom={zoomable ? onChangeZoom : undefined}
|
|
||||||
otherOperations={operations}
|
|
||||||
itemsSelected={selectedIds.size > 0}
|
|
||||||
onEdit={renderEditDialog ? onEdit : undefined}
|
|
||||||
onDelete={renderDeleteDialog ? onDelete : undefined}
|
|
||||||
filter={filter}
|
|
||||||
/>
|
|
||||||
{isEditDialogOpen &&
|
|
||||||
renderEditDialog &&
|
|
||||||
renderEditDialog(
|
|
||||||
getSelectedData(getData(result), selectedIds),
|
|
||||||
(applied) => onEditDialogClosed(applied)
|
|
||||||
)}
|
|
||||||
{isDeleteDialogOpen &&
|
|
||||||
renderDeleteDialog &&
|
|
||||||
renderDeleteDialog(
|
|
||||||
getSelectedData(getData(result), selectedIds),
|
|
||||||
(deleted) => onDeleteDialogClosed(deleted)
|
|
||||||
)}
|
|
||||||
{renderPagination()}
|
{renderPagination()}
|
||||||
{renderContent(result, filter, selectedIds, zoomIndex)}
|
{renderContent(result, filter, selectedIds, zoomIndex)}
|
||||||
<PaginationIndex
|
<PaginationIndex
|
||||||
@@ -373,10 +348,42 @@ const RenderList = <
|
|||||||
totalItems={totalCount}
|
totalItems={totalCount}
|
||||||
/>
|
/>
|
||||||
{renderPagination()}
|
{renderPagination()}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const content = (
|
||||||
|
<div>
|
||||||
|
<ListFilter
|
||||||
|
onFilterUpdate={updateQueryParams}
|
||||||
|
onSelectAll={selectable ? onSelectAll : undefined}
|
||||||
|
onSelectNone={selectable ? onSelectNone : undefined}
|
||||||
|
zoomIndex={zoomable ? zoomIndex : undefined}
|
||||||
|
onChangeZoom={zoomable ? onChangeZoom : undefined}
|
||||||
|
otherOperations={operations}
|
||||||
|
itemsSelected={selectedIds.size > 0}
|
||||||
|
onEdit={renderEditDialog ? onEdit : undefined}
|
||||||
|
onDelete={renderDeleteDialog ? onDelete : undefined}
|
||||||
|
filter={filter}
|
||||||
|
/>
|
||||||
|
{isEditDialogOpen &&
|
||||||
|
renderEditDialog &&
|
||||||
|
renderEditDialog(
|
||||||
|
getSelectedData(getData(result), selectedIds),
|
||||||
|
(applied) => onEditDialogClosed(applied)
|
||||||
|
)}
|
||||||
|
{isDeleteDialogOpen &&
|
||||||
|
renderDeleteDialog &&
|
||||||
|
renderDeleteDialog(
|
||||||
|
getSelectedData(getData(result), selectedIds),
|
||||||
|
(deleted) => onDeleteDialogClosed(deleted)
|
||||||
|
)}
|
||||||
|
{result.loading ? <LoadingIndicator /> : undefined}
|
||||||
|
{result.error ? <h1>{result.error.message}</h1> : undefined}
|
||||||
|
{maybeRenderContent()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return { contentTemplate: content, onSelectChange };
|
return { contentTemplate: content, onSelectChange };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user