Overhaul look and feel of folder select (#527)

This commit is contained in:
InfiniteTF
2020-05-09 05:08:00 +02:00
committed by GitHub
parent e9c68897d7
commit 328db57d6c
8 changed files with 111 additions and 24 deletions

View File

@@ -4,6 +4,10 @@ query Configuration {
} }
} }
query Directories($path: String) { query Directory($path: String) {
directories(path: $path) directory(path: $path) {
path
parent
directories
}
} }

View File

@@ -73,7 +73,7 @@ type Query {
"""Returns the current, complete configuration""" """Returns the current, complete configuration"""
configuration: ConfigResult! configuration: ConfigResult!
"""Returns an array of paths for the given path""" """Returns an array of paths for the given path"""
directories(path: String): [String!]! directory(path: String): Directory!
# Metadata # Metadata

View File

@@ -117,3 +117,10 @@ type ConfigResult {
general: ConfigGeneralResult! general: ConfigGeneralResult!
interface: ConfigInterfaceResult! interface: ConfigInterfaceResult!
} }
"""Directory structure of a path"""
type Directory {
path: String!
parent: String
directories: [String!]!
}

View File

@@ -12,12 +12,18 @@ func (r *queryResolver) Configuration(ctx context.Context) (*models.ConfigResult
return makeConfigResult(), nil 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 = "" var dirPath = ""
if path != nil { if path != nil {
dirPath = *path 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 { func makeConfigResult() *models.ConfigResult {

View File

@@ -96,15 +96,6 @@ func EmptyDir(path string) error {
// ListDir will return the contents of a given directory path as a string slice // ListDir will return the contents of a given directory path as a string slice
func ListDir(path string) []string { func ListDir(path string) []string {
if path == "" {
path = GetHomeDirectory()
}
absolutePath, err := filepath.Abs(path)
if err == nil {
path = absolutePath
}
files, err := ioutil.ReadDir(path) files, err := ioutil.ReadDir(path)
if err != nil { if err != nil {
path = filepath.Dir(path) path = filepath.Dir(path)
@@ -133,3 +124,25 @@ func GetHomeDirectory() string {
} }
return currentUser.HomeDir 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
}
}

View File

@@ -1,7 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { FormattedMessage } from "react-intl";
import { Button, InputGroup, Form, Modal } from "react-bootstrap"; import { Button, InputGroup, Form, Modal } from "react-bootstrap";
import { LoadingIndicator } from "src/components/Shared"; import { LoadingIndicator } from "src/components/Shared";
import { useDirectories } from "src/core/StashService"; import { useDirectory } from "src/core/StashService";
interface IProps { interface IProps {
directories: string[]; directories: string[];
@@ -12,13 +13,18 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
const [currentDirectory, setCurrentDirectory] = useState<string>(""); const [currentDirectory, setCurrentDirectory] = useState<string>("");
const [isDisplayingDialog, setIsDisplayingDialog] = useState<boolean>(false); const [isDisplayingDialog, setIsDisplayingDialog] = useState<boolean>(false);
const [selectedDirectories, setSelectedDirectories] = useState<string[]>([]); const [selectedDirectories, setSelectedDirectories] = useState<string[]>([]);
const { data, error, loading } = useDirectories(currentDirectory); const { data, error, loading } = useDirectory(currentDirectory);
useEffect(() => { useEffect(() => {
setSelectedDirectories(props.directories); setSelectedDirectories(props.directories);
}, [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() { function onSelectDirectory() {
selectedDirectories.push(currentDirectory); selectedDirectories.push(currentDirectory);
@@ -36,6 +42,19 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
props.onDirectoriesChanged(newSelectedDirectories); props.onDirectoriesChanged(newSelectedDirectories);
} }
const topDirectory = data?.directory?.parent ? (
<li className="folder-list-parent folder-list-item">
<Button
variant="link"
onClick={() =>
data.directory.parent && setCurrentDirectory(data.directory.parent)
}
>
<FormattedMessage defaultMessage="Up a directory" id="up-dir" />
</Button>
</li>
) : null;
function renderDialog() { function renderDialog() {
return ( return (
<Modal <Modal
@@ -52,11 +71,11 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setCurrentDirectory(e.currentTarget.value) setCurrentDirectory(e.currentTarget.value)
} }
defaultValue={currentDirectory} value={currentDirectory}
spellCheck={false} spellCheck={false}
/> />
<InputGroup.Append> <InputGroup.Append>
{!data || !data.directories || loading ? ( {!data || !data.directory || loading ? (
<LoadingIndicator inline /> <LoadingIndicator inline />
) : ( ) : (
"" ""
@@ -64,12 +83,12 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
</InputGroup.Append> </InputGroup.Append>
</InputGroup> </InputGroup>
<ul className="folder-list"> <ul className="folder-list">
{topDirectory}
{selectableDirectories.map((path) => { {selectableDirectories.map((path) => {
return ( return (
<li key={path} className="folder-item"> <li key={path} className="folder-list-item">
<Button <Button
variant="link" variant="link"
key={path}
onClick={() => setCurrentDirectory(path)} onClick={() => setCurrentDirectory(path)}
> >
{path} {path}

View File

@@ -75,3 +75,41 @@
min-width: 0; min-width: 0;
position: relative; position: relative;
} }
.folder-list {
list-style-type: none;
margin: 0;
padding-top: 1rem;
&-item {
white-space: nowrap;
.btn-link {
border: none;
color: black;
font-weight: 400;
padding: 0;
}
&:last-child::before {
content: "└ \1F4C1";
}
&::before {
content: "├ \1F4C1";
display: inline-block;
padding-right: 1rem;
transform: scale(1.5);
}
}
&-parent {
&::before {
visibility: hidden;
}
.btn-link {
font-weight: 500;
}
}
}

View File

@@ -173,8 +173,8 @@ export const useLatestVersion = () =>
}); });
export const useConfiguration = () => GQL.useConfigurationQuery(); export const useConfiguration = () => GQL.useConfigurationQuery();
export const useDirectories = (path?: string) => export const useDirectory = (path?: string) =>
GQL.useDirectoriesQuery({ variables: { path } }); GQL.useDirectoryQuery({ variables: { path } });
export const performerMutationImpactedQueries = [ export const performerMutationImpactedQueries = [
"findPerformers", "findPerformers",