Skip to content

Commit ba13553

Browse files
committed
collection.MoveFilesIntoAnotherCollection: autocomplete collection name
1 parent 705621b commit ba13553

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';
@@ -497,6 +497,9 @@ export default class CollectionPage extends React.Component<
497497
command={CollectionMoveFilesIntoAnotherCollection(
498498
coll.Id,
499499
this.state.selectedFileHashes,
500+
{
501+
Destination: collectionAutocomplete,
502+
},
500503
)}
501504
/>
502505
</span>

pkg/stoserver/restapi.go

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

1552+
func (h *handlers) SearchCollections(rctx *httpauth.RequestContext, w http.ResponseWriter, r *http.Request) *[]stoservertypes.CollectionSearchResult {
1553+
//nolint:unparam // false positive for this pattern
1554+
withErr := func(err error) *[]stoservertypes.CollectionSearchResult {
1555+
http.Error(w, err.Error(), http.StatusInternalServerError)
1556+
return nil
1557+
}
1558+
1559+
queryLowercased := strings.ToLower(r.URL.Query().Get("q"))
1560+
1561+
results := []stoservertypes.CollectionSearchResult{}
1562+
1563+
if queryLowercased == "" {
1564+
return &results
1565+
}
1566+
1567+
tx, err := h.db.Begin(false)
1568+
if err != nil {
1569+
return withErr(err)
1570+
}
1571+
defer func() { ignoreError(tx.Rollback()) }()
1572+
1573+
if err := stodb.CollectionRepository.Each(func(record any) error {
1574+
coll := record.(*stotypes.Collection)
1575+
1576+
if queryMatches := strings.Contains(strings.ToLower(coll.Name), queryLowercased); queryMatches {
1577+
results = append(results, stoservertypes.CollectionSearchResult{
1578+
ID: coll.ID,
1579+
Name: coll.Name,
1580+
})
1581+
}
1582+
1583+
return nil
1584+
}, tx); err != nil {
1585+
return withErr(err)
1586+
}
1587+
1588+
return &results
1589+
}
1590+
15521591
func (h *handlers) whichInitialVolumeToWriteCollectionBlobsTo(collectionID string) (int, error) {
15531592
var volumeID int
15541593
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" },
@@ -466,6 +467,13 @@
466467
"Collection": {"_": "CollectionSubset", "nullable": true}
467468
}}
468469
},
470+
{
471+
"name": "CollectionSearchResult",
472+
"type": {"_": "object", "fields": {
473+
"ID": {"_": "string"},
474+
"Name": {"_": "string"}
475+
}}
476+
},
469477
{
470478
"name": "GeneratedIds",
471479
"type": {"_": "object", "fields": {

0 commit comments

Comments
 (0)