diff --git a/graphql/documents/queries/settings/config.graphql b/graphql/documents/queries/settings/config.graphql index f92b14b7a..4ee9d4ec6 100644 --- a/graphql/documents/queries/settings/config.graphql +++ b/graphql/documents/queries/settings/config.graphql @@ -4,6 +4,10 @@ query Configuration { } } -query Directories($path: String) { - directories(path: $path) -} \ No newline at end of file +query Directory($path: String) { + directory(path: $path) { + path + parent + directories + } +} diff --git a/graphql/schema/schema.graphql b/graphql/schema/schema.graphql index 9b6f14094..3a57a551e 100644 --- a/graphql/schema/schema.graphql +++ b/graphql/schema/schema.graphql @@ -73,7 +73,7 @@ type Query { """Returns the current, complete configuration""" configuration: ConfigResult! """Returns an array of paths for the given path""" - directories(path: String): [String!]! + directory(path: String): Directory! # Metadata diff --git a/graphql/schema/types/config.graphql b/graphql/schema/types/config.graphql index 240caf2e3..ff759a74a 100644 --- a/graphql/schema/types/config.graphql +++ b/graphql/schema/types/config.graphql @@ -117,3 +117,10 @@ type ConfigResult { general: ConfigGeneralResult! interface: ConfigInterfaceResult! } + +"""Directory structure of a path""" +type Directory { + path: String! + parent: String + directories: [String!]! +} diff --git a/pkg/api/resolver_query_configuration.go b/pkg/api/resolver_query_configuration.go index ab5235d46..25708a5ca 100644 --- a/pkg/api/resolver_query_configuration.go +++ b/pkg/api/resolver_query_configuration.go @@ -12,12 +12,18 @@ func (r *queryResolver) Configuration(ctx context.Context) (*models.ConfigResult return makeConfigResult(), nil } -func (r *queryResolver) Directories(ctx context.Context, path *string) ([]string, error) { +func (r *queryResolver) Directory(ctx context.Context, path *string) (*models.Directory, error) { var dirPath = "" if path != nil { dirPath = *path } - return utils.ListDir(dirPath), nil + currentDir := utils.GetDir(dirPath) + + return &models.Directory{ + Path: currentDir, + Parent: utils.GetParent(currentDir), + Directories: utils.ListDir(currentDir), + }, nil } func makeConfigResult() *models.ConfigResult { diff --git a/pkg/utils/file.go b/pkg/utils/file.go index e029c3073..753958292 100644 --- a/pkg/utils/file.go +++ b/pkg/utils/file.go @@ -96,15 +96,6 @@ func EmptyDir(path string) error { // ListDir will return the contents of a given directory path as a string slice func ListDir(path string) []string { - if path == "" { - path = GetHomeDirectory() - } - - absolutePath, err := filepath.Abs(path) - if err == nil { - path = absolutePath - } - files, err := ioutil.ReadDir(path) if err != nil { path = filepath.Dir(path) @@ -133,3 +124,25 @@ func GetHomeDirectory() string { } return currentUser.HomeDir } + +func GetDir(path string) string { + if path == "" { + path = GetHomeDirectory() + } + + absolutePath, err := filepath.Abs(path) + if err == nil { + path = absolutePath + } + return absolutePath +} + +func GetParent(path string) *string { + isRoot := path[len(path)-1:] == "/" + if isRoot { + return nil + } else { + parentPath := filepath.Clean(path + "/..") + return &parentPath + } +} diff --git a/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx b/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx index ceb6cc4b4..9f5c4286b 100644 --- a/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx +++ b/ui/v2.5/src/components/Shared/FolderSelect/FolderSelect.tsx @@ -1,7 +1,8 @@ import React, { useEffect, useState } from "react"; +import { FormattedMessage } from "react-intl"; import { Button, InputGroup, Form, Modal } from "react-bootstrap"; import { LoadingIndicator } from "src/components/Shared"; -import { useDirectories } from "src/core/StashService"; +import { useDirectory } from "src/core/StashService"; interface IProps { directories: string[]; @@ -12,13 +13,18 @@ export const FolderSelect: React.FC = (props: IProps) => { const [currentDirectory, setCurrentDirectory] = useState(""); const [isDisplayingDialog, setIsDisplayingDialog] = useState(false); const [selectedDirectories, setSelectedDirectories] = useState([]); - const { data, error, loading } = useDirectories(currentDirectory); + const { data, error, loading } = useDirectory(currentDirectory); useEffect(() => { setSelectedDirectories(props.directories); }, [props.directories]); - const selectableDirectories: string[] = data?.directories ?? []; + useEffect(() => { + if (currentDirectory === "" && data?.directory.path) + setCurrentDirectory(data.directory.path); + }, [currentDirectory, data]); + + const selectableDirectories: string[] = data?.directory.directories ?? []; function onSelectDirectory() { selectedDirectories.push(currentDirectory); @@ -36,6 +42,19 @@ export const FolderSelect: React.FC = (props: IProps) => { props.onDirectoriesChanged(newSelectedDirectories); } + const topDirectory = data?.directory?.parent ? ( +
  • + +
  • + ) : null; + function renderDialog() { return ( = (props: IProps) => { onChange={(e: React.ChangeEvent) => setCurrentDirectory(e.currentTarget.value) } - defaultValue={currentDirectory} + value={currentDirectory} spellCheck={false} /> - {!data || !data.directories || loading ? ( + {!data || !data.directory || loading ? ( ) : ( "" @@ -64,12 +83,12 @@ export const FolderSelect: React.FC = (props: IProps) => {
      + {topDirectory} {selectableDirectories.map((path) => { return ( -
    • +