Skip to content

Commit

Permalink
finished search
Browse files Browse the repository at this point in the history
  • Loading branch information
sofiapoh committed May 25, 2020
1 parent 12a7c22 commit 15e4d57
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 128 deletions.
114 changes: 64 additions & 50 deletions src/panel/pages/request/components/Schema.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RequestContext } from "../../../context";
import { Arrow } from "../../../components";
import { Stack } from "./Stack";
import { Fields } from "./Fields";
import { Search } from "./Search";

type ActiveIds = 1 | 2 | 3;

Expand Down Expand Up @@ -52,59 +53,72 @@ export const Schema = () => {
};

return (
<>
{stack.length > 0 ? (
<Stack stack={stack} setType={setType} setStack={setStack} />
) : (
<Wrapper>
{schemaTypes.Query ? (
<>
<CollapsibleHeader
onClick={() => handleHeaderClick(1)}
aria-expanded={isActiveId(1)}
>
<Arrow data-active={isActiveId(1)} />
<span>Query</span>
</CollapsibleHeader>
{isActiveId(1) && (
<Fields node={schemaTypes?.Query} setType={setType} />
)}
</>
) : null}
{schemaTypes.Mutation ? (
<>
<CollapsibleHeader
onClick={() => handleHeaderClick(2)}
aria-expanded={isActiveId(2)}
>
<Arrow data-active={isActiveId(2)} />
<span>Mutation</span>
</CollapsibleHeader>
{isActiveId(2) && (
<Fields node={schemaTypes?.Mutation} setType={setType} />
)}
</>
) : null}
{schemaTypes.Subscription ? (
<>
<CollapsibleHeader
onClick={() => handleHeaderClick(3)}
aria-expanded={isActiveId(3)}
>
<Arrow data-active={isActiveId(3)} />
<span>Subscription</span>
</CollapsibleHeader>
{isActiveId(3) && (
<Fields node={schemaTypes?.Subscription} setType={setType} />
)}
</>
) : null}
</Wrapper>
)}
</>
<FlexContainer>
<Search typeMap={schemaTypes} setType={setType} />
<Container>
{stack.length > 0 ? (
<Stack stack={stack} setType={setType} setStack={setStack} />
) : (
<Wrapper>
{schemaTypes.Query ? (
<>
<CollapsibleHeader
onClick={() => handleHeaderClick(1)}
aria-expanded={isActiveId(1)}
>
<Arrow data-active={isActiveId(1)} />
<span>Query</span>
</CollapsibleHeader>
{isActiveId(1) && (
<Fields node={schemaTypes?.Query} setType={setType} />
)}
</>
) : null}
{schemaTypes.Mutation ? (
<>
<CollapsibleHeader
onClick={() => handleHeaderClick(2)}
aria-expanded={isActiveId(2)}
>
<Arrow data-active={isActiveId(2)} />
<span>Mutation</span>
</CollapsibleHeader>
{isActiveId(2) && (
<Fields node={schemaTypes?.Mutation} setType={setType} />
)}
</>
) : null}
{schemaTypes.Subscription ? (
<>
<CollapsibleHeader
onClick={() => handleHeaderClick(3)}
aria-expanded={isActiveId(3)}
>
<Arrow data-active={isActiveId(3)} />
<span>Subscription</span>
</CollapsibleHeader>
{isActiveId(3) && (
<Fields node={schemaTypes?.Subscription} setType={setType} />
)}
</>
) : null}
</Wrapper>
)}
</Container>
</FlexContainer>
);
};

const FlexContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;

const Container = styled.div`
position: relative;
`;

const CollapsibleHeader = styled.button`
display: flex;
align-items: center;
Expand Down
201 changes: 123 additions & 78 deletions src/panel/pages/request/components/Search.tsx
Original file line number Diff line number Diff line change
@@ -1,88 +1,163 @@
import React, { FC, useMemo, useCallback } from "react";
import React, {
FC,
useMemo,
useCallback,
ChangeEvent,
useState,
useEffect,
useRef,
} from "react";
import { GraphQLNamedType } from "graphql";
import styled from "styled-components";
import { TypeMap } from "graphql/type/schema";
import { faSearch } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

interface SearchProps {
typeMap: TypeMap;
setType: (type: GraphQLNamedType) => void;
}

export const Search: FC<SearchProps> = (props) => {
const [results, setResults] = useState([]);
const [searchValue, setSearchValue] = useState("");
const typeKeys = useMemo(() => Object.keys(props.typeMap));
export const Search: FC<SearchProps> = ({ typeMap, setType }) => {
const containerRef = useRef<HTMLDivElement>(undefined as any);
const [searchValue, setSearchValue] = useState<string>("");
const [listOpen, setListOpen] = useState<boolean>(false);
let typeKeys = useMemo(() => Object.keys(typeMap), [typeMap]);
const results = useMemo(
() =>
(typeKeys = typeKeys.filter((key) =>
key.toLowerCase().startsWith(searchValue.toLowerCase())
)),
[searchValue]
);

useEffect(() => {
if (searchValue && results.length) {
setListOpen(true);
} else {
setListOpen(false);
}
}, [searchValue, results]);

useEffect(() => {
const onOutsideClick = (e: MouseEvent) => {
if (!containerRef?.current?.contains(e.target as Node)) {
setListOpen(false);
} else if (searchValue && results.length) {
setListOpen(true);
}
};

window.addEventListener("click", onOutsideClick);

return () => {
window.removeEventListener("click", onOutsideClick);
};
}, [searchValue, results]);

const handleOnChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
setSearchValue(e.target.value || "");
},
[setSearchValue]
);

const handleTypeSelect = useCallback(
(type) => {
setType(type);
setListOpen(false);
},
[setListOpen, setType]
);

const handleOnChange = () => {};
return (
<div>
<input value={searchValue} />
<ul>
{results.map((res) => (
<li>{res.name}</li>
))}
</ul>
</div>
<Container ref={containerRef}>
<InputWrapper>
<Icon icon={faSearch} />
<Input
type="search"
value={searchValue}
onChange={handleOnChange}
placeholder="Search for a type in schema"
/>
</InputWrapper>
{listOpen ? (
<List>
{results.map((res, i) => (
<ListItem key={i}>
<TextButton onClick={() => handleTypeSelect(typeMap[res])}>
{typeMap[res].name}
</TextButton>
</ListItem>
))}
</List>
) : null}
</Container>
);
};

const StackHeading = styled.div`
const Container = styled.div`
background-color: ${(p) => p.theme.dark["+5"]};
`;

const Icon = styled(FontAwesomeIcon)`
font-size: 13px;
margin-right: 6px;
color: ${(p) => p.theme.light["-9"]};
`;

const InputWrapper = styled.div`
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
max-width: 250px;
color: ${(p) => p.theme.light["-5"]};
background-color: ${(p) => p.theme.dark["+3"]};
border-top: 1px solid ${(p) => p.theme.dark["+7"]};
border-bottom: 1px solid ${(p) => p.theme.dark["+7"]};
font-size: 13px;
padding: 6px 12px;
&:first-of-type {
background-color: ${(p) => p.theme.dark["+5"]};
border-bottom: none;
&::after {
content: "|";
color: ${(p) => p.theme.grey["-2"]};
}
`;

const StackWrapper = styled.div`
box-sizing: border-box;
position: absolute;
right: 0;
top: 0;
height: 100%;
const Input = styled.input`
background-color: transparent;
border: none;
width: 100%;
display: flex;
flex-direction: column;
background-color: ${(p) => p.theme.dark["+1"]};
color: ${(p) => p.theme.light["-5"]};
`;

export const Box = styled.div`
const List = styled.ul`
position: absolute;
right: 0;
left: 0;
display: flex;
width: 250px;
max-height: 400px;
margin-top: 0;
padding: 12px 6px;
list-style: none;
flex-direction: column;
`;
background-color: ${(p) => p.theme.dark["+2"]};
border: 1px solid ${(p) => p.theme.dark["+4"]};
const TypeKind = styled.code`
color: ${(p) => p.theme.yellow["+3"]};
margin-right: 6px;
&[data-kind="interface"] {
color: ${(p) => p.theme.red["+3"]};
}
&[data-kind="enum"] {
color: ${(p) => p.theme.purple["+3"]};
}
z-index: 2;
overflow: auto;
`;

&[data-kind="union"] {
color: ${(p) => p.theme.blue["+3"]};
}
const ListItem = styled.li`
padding: 6px;
&[data-kind="scalar"] {
color: ${(p) => p.theme.orange["+3"]};
&:hover {
background-color: ${(p) => p.theme.dark["+3"]};
}
`;

const TextButton = styled.button`
display: inline-block;
width: 100%;
background: transparent;
outline: none;
border: none;
Expand All @@ -97,33 +172,3 @@ const TextButton = styled.button`
text-decoration: underline;
}
`;

const BackButton = styled(TextButton)`
width: max-content;
color: ${(p) => p.theme.light["-9"]};
font-size: 12px;
border-radius: 3px;
margin-right: 6px;
padding: 4px 6px;
&:last-child {
margin-right: 0;
}
&:hover {
background-color: ${(p) => p.theme.grey["-9"]};
text-decoration: none;
}
`;

const Title = styled.span`
color: ${(p) => p.theme.light["-9"]};
display: inline-block;
padding: 4px 6px;
`;

const Description = styled.p`
font-size: 13px;
color: ${(p) => p.theme.light["-9"]};
margin: 12px;
`;

0 comments on commit 15e4d57

Please sign in to comment.