mirror of https://github.com/stashapp/stash.git
Maintain saved filters in full export/import (#5465)
* Remove ellipsis from full export button
This commit is contained in:
parent
41d1b45fb9
commit
a18c538c1f
|
@ -42,3 +42,7 @@ func (jp *jsonUtils) saveGallery(fn string, gallery *jsonschema.Gallery) error {
|
||||||
func (jp *jsonUtils) saveFile(fn string, file jsonschema.DirEntry) error {
|
func (jp *jsonUtils) saveFile(fn string, file jsonschema.DirEntry) error {
|
||||||
return jsonschema.SaveFileFile(filepath.Join(jp.json.Files, fn), file)
|
return jsonschema.SaveFileFile(filepath.Join(jp.json.Files, fn), file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (jp *jsonUtils) saveSavedFilter(fn string, savedFilter *jsonschema.SavedFilter) error {
|
||||||
|
return jsonschema.SaveSavedFilterFile(filepath.Join(jp.json.SavedFilters, fn), savedFilter)
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/stashapp/stash/pkg/models/jsonschema"
|
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||||
"github.com/stashapp/stash/pkg/models/paths"
|
"github.com/stashapp/stash/pkg/models/paths"
|
||||||
"github.com/stashapp/stash/pkg/performer"
|
"github.com/stashapp/stash/pkg/performer"
|
||||||
|
"github.com/stashapp/stash/pkg/savedfilter"
|
||||||
"github.com/stashapp/stash/pkg/scene"
|
"github.com/stashapp/stash/pkg/scene"
|
||||||
"github.com/stashapp/stash/pkg/sliceutil"
|
"github.com/stashapp/stash/pkg/sliceutil"
|
||||||
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
|
||||||
|
@ -176,6 +177,7 @@ func (t *ExportTask) Start(ctx context.Context, wg *sync.WaitGroup) {
|
||||||
t.ExportPerformers(ctx, workerCount)
|
t.ExportPerformers(ctx, workerCount)
|
||||||
t.ExportStudios(ctx, workerCount)
|
t.ExportStudios(ctx, workerCount)
|
||||||
t.ExportTags(ctx, workerCount)
|
t.ExportTags(ctx, workerCount)
|
||||||
|
t.ExportSavedFilters(ctx, workerCount)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -1186,3 +1188,62 @@ func (t *ExportTask) exportGroup(ctx context.Context, wg *sync.WaitGroup, jobCha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ExportTask) ExportSavedFilters(ctx context.Context, workers int) {
|
||||||
|
// don't export saved filters unless we're doing a full export
|
||||||
|
if !t.full {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
reader := t.repository.SavedFilter
|
||||||
|
var filters []*models.SavedFilter
|
||||||
|
var err error
|
||||||
|
filters, err = reader.All(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("[saved filters] failed to fetch saved filters: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("[saved filters] exporting")
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
|
jobCh := make(chan *models.SavedFilter, workers*2) // make a buffered channel to feed workers
|
||||||
|
|
||||||
|
for w := 0; w < workers; w++ { // create export Saved Filter workers
|
||||||
|
wg.Add(1)
|
||||||
|
go t.exportSavedFilter(ctx, &wg, jobCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, savedFilter := range filters {
|
||||||
|
index := i + 1
|
||||||
|
logger.Progressf("[saved filters] %d of %d", index, len(filters))
|
||||||
|
|
||||||
|
jobCh <- savedFilter // feed workers
|
||||||
|
}
|
||||||
|
|
||||||
|
close(jobCh)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
logger.Infof("[saved filters] export complete in %s. %d workers used.", time.Since(startTime), workers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ExportTask) exportSavedFilter(ctx context.Context, wg *sync.WaitGroup, jobChan <-chan *models.SavedFilter) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for thisFilter := range jobChan {
|
||||||
|
newJSON, err := savedfilter.ToJSON(ctx, thisFilter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("[saved filter] <%s> error getting saved filter JSON: %v", thisFilter.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn := newJSON.Filename()
|
||||||
|
|
||||||
|
if err := t.json.saveSavedFilter(fn, newJSON); err != nil {
|
||||||
|
logger.Errorf("[saved filter] <%s> failed to save json: %v", fn, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/stashapp/stash/pkg/models/jsonschema"
|
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||||
"github.com/stashapp/stash/pkg/models/paths"
|
"github.com/stashapp/stash/pkg/models/paths"
|
||||||
"github.com/stashapp/stash/pkg/performer"
|
"github.com/stashapp/stash/pkg/performer"
|
||||||
|
"github.com/stashapp/stash/pkg/savedfilter"
|
||||||
"github.com/stashapp/stash/pkg/scene"
|
"github.com/stashapp/stash/pkg/scene"
|
||||||
"github.com/stashapp/stash/pkg/studio"
|
"github.com/stashapp/stash/pkg/studio"
|
||||||
"github.com/stashapp/stash/pkg/tag"
|
"github.com/stashapp/stash/pkg/tag"
|
||||||
|
@ -124,6 +125,7 @@ func (t *ImportTask) Start(ctx context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.ImportSavedFilters(ctx)
|
||||||
t.ImportTags(ctx)
|
t.ImportTags(ctx)
|
||||||
t.ImportPerformers(ctx)
|
t.ImportPerformers(ctx)
|
||||||
t.ImportStudios(ctx)
|
t.ImportStudios(ctx)
|
||||||
|
@ -779,3 +781,53 @@ func (t *ImportTask) ImportImages(ctx context.Context) {
|
||||||
|
|
||||||
logger.Info("[images] import complete")
|
logger.Info("[images] import complete")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ImportTask) ImportSavedFilters(ctx context.Context) {
|
||||||
|
logger.Info("[saved filters] importing")
|
||||||
|
|
||||||
|
path := t.json.json.SavedFilters
|
||||||
|
files, err := os.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
logger.Errorf("[saved filters] failed to read saved filters directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r := t.repository
|
||||||
|
|
||||||
|
for i, fi := range files {
|
||||||
|
index := i + 1
|
||||||
|
savedFilterJSON, err := jsonschema.LoadSavedFilterFile(filepath.Join(path, fi.Name()))
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("[saved filters] failed to read json: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Progressf("[saved filters] %d of %d", index, len(files))
|
||||||
|
|
||||||
|
if err := r.WithTxn(ctx, func(ctx context.Context) error {
|
||||||
|
return t.importSavedFilter(ctx, savedFilterJSON)
|
||||||
|
}); err != nil {
|
||||||
|
logger.Errorf("[saved filters] <%s> failed to import: %v", fi.Name(), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("[saved filters] import complete")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ImportTask) importSavedFilter(ctx context.Context, savedFilterJSON *jsonschema.SavedFilter) error {
|
||||||
|
importer := &savedfilter.Importer{
|
||||||
|
ReaderWriter: t.repository.SavedFilter,
|
||||||
|
Input: *savedFilterJSON,
|
||||||
|
MissingRefBehaviour: t.MissingRefBehaviour,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := performImport(ctx, importer, t.DuplicateBehaviour); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package jsonschema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadFile[T any](filePath string) (*T, error) {
|
||||||
|
var ret T
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
jsonParser := json.NewDecoder(file)
|
||||||
|
err = jsonParser.Decode(&ret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveFile[T any](filePath string, obj *T) error {
|
||||||
|
if obj == nil {
|
||||||
|
return fmt.Errorf("object must not be nil")
|
||||||
|
}
|
||||||
|
return marshalToFile(filePath, obj)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package jsonschema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stashapp/stash/pkg/fsutil"
|
||||||
|
"github.com/stashapp/stash/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SavedFilter struct {
|
||||||
|
Mode models.FilterMode `db:"mode" json:"mode"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
FindFilter *models.FindFilterType `json:"find_filter"`
|
||||||
|
ObjectFilter map[string]interface{} `json:"object_filter"`
|
||||||
|
UIOptions map[string]interface{} `json:"ui_options"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SavedFilter) Filename() string {
|
||||||
|
ret := fsutil.SanitiseBasename(s.Name + "_" + s.Mode.String())
|
||||||
|
return ret + ".json"
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSavedFilterFile(filePath string) (*SavedFilter, error) {
|
||||||
|
return loadFile[SavedFilter](filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SaveSavedFilterFile(filePath string, image *SavedFilter) error {
|
||||||
|
return saveFile[SavedFilter](filePath, image)
|
||||||
|
}
|
|
@ -12,14 +12,15 @@ type JSONPaths struct {
|
||||||
|
|
||||||
ScrapedFile string
|
ScrapedFile string
|
||||||
|
|
||||||
Performers string
|
Performers string
|
||||||
Scenes string
|
Scenes string
|
||||||
Images string
|
Images string
|
||||||
Galleries string
|
Galleries string
|
||||||
Studios string
|
Studios string
|
||||||
Tags string
|
Tags string
|
||||||
Groups string
|
Groups string
|
||||||
Files string
|
Files string
|
||||||
|
SavedFilters string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newJSONPaths(baseDir string) *JSONPaths {
|
func newJSONPaths(baseDir string) *JSONPaths {
|
||||||
|
@ -34,6 +35,7 @@ func newJSONPaths(baseDir string) *JSONPaths {
|
||||||
jp.Groups = filepath.Join(baseDir, "movies")
|
jp.Groups = filepath.Join(baseDir, "movies")
|
||||||
jp.Tags = filepath.Join(baseDir, "tags")
|
jp.Tags = filepath.Join(baseDir, "tags")
|
||||||
jp.Files = filepath.Join(baseDir, "files")
|
jp.Files = filepath.Join(baseDir, "files")
|
||||||
|
jp.SavedFilters = filepath.Join(baseDir, "saved_filters")
|
||||||
return &jp
|
return &jp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +54,7 @@ func EmptyJSONDirs(baseDir string) {
|
||||||
_ = fsutil.EmptyDir(jsonPaths.Groups)
|
_ = fsutil.EmptyDir(jsonPaths.Groups)
|
||||||
_ = fsutil.EmptyDir(jsonPaths.Tags)
|
_ = fsutil.EmptyDir(jsonPaths.Tags)
|
||||||
_ = fsutil.EmptyDir(jsonPaths.Files)
|
_ = fsutil.EmptyDir(jsonPaths.Files)
|
||||||
|
_ = fsutil.EmptyDir(jsonPaths.SavedFilters)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnsureJSONDirs(baseDir string) {
|
func EnsureJSONDirs(baseDir string) {
|
||||||
|
@ -83,4 +86,7 @@ func EnsureJSONDirs(baseDir string) {
|
||||||
if err := fsutil.EnsureDir(jsonPaths.Files); err != nil {
|
if err := fsutil.EnsureDir(jsonPaths.Files); err != nil {
|
||||||
logger.Warnf("couldn't create directories for Files: %v", err)
|
logger.Warnf("couldn't create directories for Files: %v", err)
|
||||||
}
|
}
|
||||||
|
if err := fsutil.EnsureDir(jsonPaths.SavedFilters); err != nil {
|
||||||
|
logger.Warnf("couldn't create directories for Saved Filters: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package savedfilter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/models"
|
||||||
|
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToJSON converts a SavedFilter object into its JSON equivalent.
|
||||||
|
func ToJSON(ctx context.Context, filter *models.SavedFilter) (*jsonschema.SavedFilter, error) {
|
||||||
|
return &jsonschema.SavedFilter{
|
||||||
|
Name: filter.Name,
|
||||||
|
Mode: filter.Mode,
|
||||||
|
FindFilter: filter.FindFilter,
|
||||||
|
ObjectFilter: filter.ObjectFilter,
|
||||||
|
UIOptions: filter.UIOptions,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package savedfilter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stashapp/stash/pkg/models"
|
||||||
|
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||||
|
"github.com/stashapp/stash/pkg/models/mocks"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
savedFilterID = 1
|
||||||
|
noImageID = 2
|
||||||
|
errImageID = 3
|
||||||
|
errAliasID = 4
|
||||||
|
withParentsID = 5
|
||||||
|
errParentsID = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
filterName = "testFilter"
|
||||||
|
mode = models.FilterModeGalleries
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
findFilter = models.FindFilterType{}
|
||||||
|
objectFilter = make(map[string]interface{})
|
||||||
|
uiOptions = make(map[string]interface{})
|
||||||
|
)
|
||||||
|
|
||||||
|
func createSavedFilter(id int) models.SavedFilter {
|
||||||
|
return models.SavedFilter{
|
||||||
|
ID: id,
|
||||||
|
Name: filterName,
|
||||||
|
Mode: mode,
|
||||||
|
FindFilter: &findFilter,
|
||||||
|
ObjectFilter: objectFilter,
|
||||||
|
UIOptions: uiOptions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createJSONSavedFilter() *jsonschema.SavedFilter {
|
||||||
|
return &jsonschema.SavedFilter{
|
||||||
|
Name: filterName,
|
||||||
|
Mode: mode,
|
||||||
|
FindFilter: &findFilter,
|
||||||
|
ObjectFilter: objectFilter,
|
||||||
|
UIOptions: uiOptions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type testScenario struct {
|
||||||
|
savedFilter models.SavedFilter
|
||||||
|
expected *jsonschema.SavedFilter
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var scenarios []testScenario
|
||||||
|
|
||||||
|
func initTestTable() {
|
||||||
|
scenarios = []testScenario{
|
||||||
|
{
|
||||||
|
createSavedFilter(savedFilterID),
|
||||||
|
createJSONSavedFilter(),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToJSON(t *testing.T) {
|
||||||
|
initTestTable()
|
||||||
|
|
||||||
|
db := mocks.NewDatabase()
|
||||||
|
|
||||||
|
for i, s := range scenarios {
|
||||||
|
savedFilter := s.savedFilter
|
||||||
|
json, err := ToJSON(testCtx, &savedFilter)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case !s.err && err != nil:
|
||||||
|
t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
||||||
|
case s.err && err == nil:
|
||||||
|
t.Errorf("[%d] expected error not returned", i)
|
||||||
|
default:
|
||||||
|
assert.Equal(t, s.expected, json, "[%d]", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db.AssertExpectations(t)
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package savedfilter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/models"
|
||||||
|
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ImporterReaderWriter interface {
|
||||||
|
models.SavedFilterWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
type Importer struct {
|
||||||
|
ReaderWriter ImporterReaderWriter
|
||||||
|
Input jsonschema.SavedFilter
|
||||||
|
MissingRefBehaviour models.ImportMissingRefEnum
|
||||||
|
|
||||||
|
savedFilter models.SavedFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) PreImport(ctx context.Context) error {
|
||||||
|
i.savedFilter = models.SavedFilter{
|
||||||
|
Name: i.Input.Name,
|
||||||
|
Mode: i.Input.Mode,
|
||||||
|
FindFilter: i.Input.FindFilter,
|
||||||
|
ObjectFilter: i.Input.ObjectFilter,
|
||||||
|
UIOptions: i.Input.UIOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) PostImport(ctx context.Context, id int) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) Name() string {
|
||||||
|
return i.Input.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) FindExistingID(ctx context.Context) (*int, error) {
|
||||||
|
// for now, assume this is only imported in full, so we don't support updating existing filters
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) Create(ctx context.Context) (*int, error) {
|
||||||
|
err := i.ReaderWriter.Create(ctx, &i.savedFilter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating saved filter: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := i.savedFilter.ID
|
||||||
|
return &id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) Update(ctx context.Context, id int) error {
|
||||||
|
return fmt.Errorf("updating existing saved filters is not supported")
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
package savedfilter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stashapp/stash/pkg/models"
|
||||||
|
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||||
|
"github.com/stashapp/stash/pkg/models/mocks"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
savedFilterNameErr = "savedFilterNameErr"
|
||||||
|
existingSavedFilterName = "existingSavedFilterName"
|
||||||
|
|
||||||
|
existingFilterID = 100
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCtx = context.Background()
|
||||||
|
|
||||||
|
func TestImporterName(t *testing.T) {
|
||||||
|
i := Importer{
|
||||||
|
Input: jsonschema.SavedFilter{
|
||||||
|
Name: filterName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, filterName, i.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImporterPreImport(t *testing.T) {
|
||||||
|
i := Importer{
|
||||||
|
Input: jsonschema.SavedFilter{
|
||||||
|
Name: filterName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := i.PreImport(testCtx)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImporterPostImport(t *testing.T) {
|
||||||
|
db := mocks.NewDatabase()
|
||||||
|
|
||||||
|
i := Importer{
|
||||||
|
ReaderWriter: db.SavedFilter,
|
||||||
|
Input: jsonschema.SavedFilter{},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := i.PostImport(testCtx, savedFilterID)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
db.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImporterFindExistingID(t *testing.T) {
|
||||||
|
db := mocks.NewDatabase()
|
||||||
|
|
||||||
|
i := Importer{
|
||||||
|
ReaderWriter: db.SavedFilter,
|
||||||
|
Input: jsonschema.SavedFilter{
|
||||||
|
Name: filterName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := i.FindExistingID(testCtx)
|
||||||
|
assert.Nil(t, id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
db := mocks.NewDatabase()
|
||||||
|
|
||||||
|
savedFilter := models.SavedFilter{
|
||||||
|
Name: filterName,
|
||||||
|
}
|
||||||
|
|
||||||
|
savedFilterErr := models.SavedFilter{
|
||||||
|
Name: savedFilterNameErr,
|
||||||
|
}
|
||||||
|
|
||||||
|
i := Importer{
|
||||||
|
ReaderWriter: db.SavedFilter,
|
||||||
|
savedFilter: savedFilter,
|
||||||
|
}
|
||||||
|
|
||||||
|
errCreate := errors.New("Create error")
|
||||||
|
db.SavedFilter.On("Create", testCtx, &savedFilter).Run(func(args mock.Arguments) {
|
||||||
|
t := args.Get(1).(*models.SavedFilter)
|
||||||
|
t.ID = savedFilterID
|
||||||
|
}).Return(nil).Once()
|
||||||
|
db.SavedFilter.On("Create", testCtx, &savedFilterErr).Return(errCreate).Once()
|
||||||
|
|
||||||
|
id, err := i.Create(testCtx)
|
||||||
|
assert.Equal(t, savedFilterID, *id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
i.savedFilter = savedFilterErr
|
||||||
|
id, err = i.Create(testCtx)
|
||||||
|
assert.Nil(t, id)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
db.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
db := mocks.NewDatabase()
|
||||||
|
|
||||||
|
savedFilterErr := models.SavedFilter{
|
||||||
|
Name: savedFilterNameErr,
|
||||||
|
}
|
||||||
|
|
||||||
|
i := Importer{
|
||||||
|
ReaderWriter: db.SavedFilter,
|
||||||
|
savedFilter: savedFilterErr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is not currently supported
|
||||||
|
err := i.Update(testCtx, existingFilterID)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
|
@ -520,7 +520,7 @@ export const DataManagementTasks: React.FC<IDataManagementTasks> = ({
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={() => onExport()}
|
onClick={() => onExport()}
|
||||||
>
|
>
|
||||||
<FormattedMessage id="actions.full_export" />…
|
<FormattedMessage id="actions.full_export" />
|
||||||
</Button>
|
</Button>
|
||||||
</Setting>
|
</Setting>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue