Skip to content

Commit d073741

Browse files
committed
collection.MoveFilesIntoAnotherCollection: autocomplete collection name
1 parent 7f5258e commit d073741

5 files changed

Lines changed: 76 additions & 2 deletions

File tree

frontend/component/autocompletes.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { SearchBox } from 'component/autocomplete';
22
import { CustomFieldInputFactory } from 'f61ui/commandtypes';
33
import {
4+
searchCollections,
45
searchIgdb,
56
searchReplicationPolicies,
67
searchTmdbMovies,
@@ -9,6 +10,29 @@ import {
910
} from 'generated/stoserver/stoservertypes_endpoints';
1011
import * as React from 'react';
1112

13+
export const collectionAutocomplete: CustomFieldInputFactory<string> = (
14+
field,
15+
_,
16+
update,
17+
autoFocus,
18+
) => {
19+
return (
20+
<SearchBox
21+
allowEmptySearch={false}
22+
autoFocus={autoFocus}
23+
placeholder={field.Placeholder}
24+
searchTerm={field.DefaultValueString}
25+
dataSource={searchCollections}
26+
onSelect={(item) => {
27+
update(item.key);
28+
}}
29+
itemToAutocompleteItem={(item) => {
30+
return { label: item.Name, key: item.ID };
31+
}}
32+
/>
33+
);
34+
};
35+
1236
export const replicationPolicyAutocomplete: CustomFieldInputFactory<string> = (
1337
field,
1438
_,

frontend/pages/CollectionPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AssetImg } from 'component/assetimg';
2-
import { tmdbMovieAutocomplete } from 'component/autocompletes';
2+
import { collectionAutocomplete, tmdbMovieAutocomplete } from 'component/autocompletes';
33
import { collectionDropdown } from 'component/collectiondropdown';
44
import { filetypeForFile, iconForFiletype } from 'component/filetypes';
55
import { FileUploadArea } from 'component/fileupload';
@@ -492,6 +492,9 @@ export default class CollectionPage extends React.Component<
492492
command={CollectionMoveFilesIntoAnotherCollection(
493493
coll.Id,
494494
this.state.selectedFileHashes,
495+
{
496+
Destination: collectionAutocomplete,
497+
},
495498
)}
496499
/>
497500
</span>

pkg/stoserver/restapi.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,45 @@ func (h *handlers) Search(rctx *httpauth.RequestContext, w http.ResponseWriter,
15341534
return &results
15351535
}
15361536

1537+
func (h *handlers) SearchCollections(rctx *httpauth.RequestContext, w http.ResponseWriter, r *http.Request) *[]stoservertypes.CollectionSearchResult {
1538+
//nolint:unparam // false positive for this pattern
1539+
withErr := func(err error) *[]stoservertypes.CollectionSearchResult {
1540+
http.Error(w, err.Error(), http.StatusInternalServerError)
1541+
return nil
1542+
}
1543+
1544+
queryLowercased := strings.ToLower(r.URL.Query().Get("q"))
1545+
1546+
results := []stoservertypes.CollectionSearchResult{}
1547+
1548+
if queryLowercased == "" {
1549+
return &results
1550+
}
1551+
1552+
tx, err := h.db.Begin(false)
1553+
if err != nil {
1554+
return withErr(err)
1555+
}
1556+
defer func() { ignoreError(tx.Rollback()) }()
1557+
1558+
if err := stodb.CollectionRepository.Each(func(record any) error {
1559+
coll := record.(*stotypes.Collection)
1560+
1561+
if queryMatches := strings.Contains(strings.ToLower(coll.Name), queryLowercased); queryMatches {
1562+
results = append(results, stoservertypes.CollectionSearchResult{
1563+
ID: coll.ID,
1564+
Name: coll.Name,
1565+
})
1566+
}
1567+
1568+
return nil
1569+
}, tx); err != nil {
1570+
return withErr(err)
1571+
}
1572+
1573+
return &results
1574+
}
1575+
15371576
func (h *handlers) whichInitialVolumeToWriteCollectionBlobsTo(collectionID string) (int, error) {
15381577
var volumeID int
15391578
return volumeID, h.db.View(func(tx *bbolt.Tx) error {

pkg/stoserver/stoservertypes/commands.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@
481481
"fields": [
482482
{ "key": "Source", "hideIfDefaultValue": true },
483483
{ "key": "Files", "type": "StringList", "hideIfDefaultValue": true },
484-
{ "key": "Destination", "placeholder": "lwwEC91fGeU", "help": "Collection ID" }
484+
{ "key": "Destination", "title": "Destination collection", "placeholder": "(search)", "type": "custom/string" }
485485
]
486486
},
487487
{

pkg/stoserver/stoservertypes/types.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
{ "chain": "public", "method": "GET", "path": "/api_v2/config/{id}", "produces": {"_": "ConfigValue"}, "name": "getConfig" },
3333
{ "chain": "public", "method": "GET", "path": "/api_v2/logs", "produces": {"_": "list", "of": {"_": "string"}}, "name": "getLogs" },
3434
{ "chain": "public", "method": "GET", "path": "/api_v2/search?q={query}", "produces": {"_": "list", "of": {"_": "SearchResult"}}, "name": "search" },
35+
{ "chain": "public", "method": "GET", "path": "/api_v2/search_collections?q={query}", "produces": {"_": "list", "of": {"_": "CollectionSearchResult"}}, "name": "searchCollections" },
3536
{ "chain": "public", "method": "GET", "path": "/api_v2/external/tmdb/movies?q={query}", "produces": {"_": "list", "of": {"_": "TmdbSearchResult"}}, "name": "searchTmdbMovies" },
3637
{ "chain": "public", "method": "GET", "path": "/api_v2/external/tmdb/tv?q={query}", "produces": {"_": "list", "of": {"_": "TmdbSearchResult"}}, "name": "searchTmdbTv" },
3738
{ "chain": "public", "method": "GET", "path": "/api_v2/external/tmdb/credits?collection={collection}", "produces": {"_": "list", "of": {"_": "TmdbCredit"}}, "name": "tmdbCredits" },
@@ -465,6 +466,13 @@
465466
"Collection": {"_": "CollectionSubset", "nullable": true}
466467
}}
467468
},
469+
{
470+
"name": "CollectionSearchResult",
471+
"type": {"_": "object", "fields": {
472+
"ID": {"_": "string"},
473+
"Name": {"_": "string"}
474+
}}
475+
},
468476
{
469477
"name": "GeneratedIds",
470478
"type": {"_": "object", "fields": {

0 commit comments

Comments
 (0)