diff --git a/src/components/InputPanel/InputItem.tsx b/src/components/InputPanel/InputItem.tsx new file mode 100644 index 0000000..d22262e --- /dev/null +++ b/src/components/InputPanel/InputItem.tsx @@ -0,0 +1,20 @@ +import React, { PropsWithChildren, useCallback } from 'react'; +import styles from '../../css/RMLMappingEditor.module.scss'; + +interface InputItemProps extends PropsWithChildren { + onClick: (index: number) => void; + index: number; +} + +function InputItem({ onClick, index, children }: InputItemProps) { + const handleClick = useCallback(() => { + onClick(index); + }, [index, onClick]); + return ( +
+ {children} +
+ ); +} + +export default InputItem; diff --git a/src/components/InputPanel/ViewButton.tsx b/src/components/InputPanel/ViewButton.tsx new file mode 100644 index 0000000..3341be0 --- /dev/null +++ b/src/components/InputPanel/ViewButton.tsx @@ -0,0 +1,28 @@ +import React, { PropsWithChildren, useCallback } from 'react'; +import { ViewType } from '../../util/TypeUtil'; +import styles from '../../css/RMLMappingEditor.module.scss'; + +interface ViewButtonProps extends PropsWithChildren { + name: ViewType; + onClick: (name: ViewType) => void; + isSelected: boolean; +} + +function ViewButton({ name, onClick, isSelected, children }: ViewButtonProps) { + const handleClick = useCallback(() => { + onClick(name); + }, [onClick, name]); + + return ( + + ); +} + +export default ViewButton; diff --git a/src/components/InputPanel.tsx b/src/components/InputPanel/index.tsx similarity index 56% rename from src/components/InputPanel.tsx rename to src/components/InputPanel/index.tsx index bcb89a2..5b87f97 100644 --- a/src/components/InputPanel.tsx +++ b/src/components/InputPanel/index.tsx @@ -1,22 +1,47 @@ -import { useCallback, useContext, useEffect, useMemo, useState } from "react"; -import InputContext from "../contexts/InputContext"; -import styles from "../css/RMLMappingEditor.module.scss"; -import CodeEditor from "./CodeEditor"; -import { ReactComponent as PlusIcon } from "../images/plus.svg"; -import { ReactComponent as DownArrow } from "../images/down-arrow.svg"; -import { INPUT_TYPES } from '../util/Constants'; +import React, { + useCallback, + useContext, + useEffect, + useMemo, + useState, +} from 'react'; +import InputContext from '../../contexts/InputContext'; +import styles from '../../css/RMLMappingEditor.module.scss'; +import CodeEditor from '../CodeEditor'; +import { ReactComponent as PlusIcon } from '../../images/plus.svg'; +import { ReactComponent as DownArrow } from '../../images/down-arrow.svg'; +import ViewButton from './ViewButton'; +import { ViewType } from '../../util/TypeUtil'; +import InputItem from './InputItem'; +import { INPUT_TYPES } from '../../util/Constants'; -const views = { - inputs: "Input Files", - // functions: 'Functions', +const views: Record = { + [ViewType.INPUTS]: 'Input Files', + [ViewType.FUNCTIONS]: 'Functions', }; +// type ViewType = keyof typeof views; + +const functionList = [ + { + name: 'Capitalize', + function: (str: string) => str.toUpperCase(), + }, + { + name: 'Lower case', + function: (str: string) => str.toLowerCase(), + }, + { + name: 'Concatenate', + function: (strList: string[], delimiter: '-') => strList.join(delimiter), + }, +]; export interface InputPanelProps { addNewInput: () => void; } function InputPanel({ addNewInput }: InputPanelProps) { - const [view, setView] = useState(views.inputs); + const [view, setView] = useState(ViewType.INPUTS); const { inputFiles, setInputFiles } = useContext(InputContext); const [selectedInputFileIndex, setSelectedInputFileIndex] = useState(); @@ -33,17 +58,17 @@ function InputPanel({ addNewInput }: InputPanelProps) { const inputType = useMemo(() => { if (selectedInputFile) { - if (selectedInputFile.name.endsWith(".json")) { + if (selectedInputFile.name.endsWith('.json')) { return INPUT_TYPES.json; - } else if (selectedInputFile.name.endsWith(".xml")) { + } else if (selectedInputFile.name.endsWith('.xml')) { return INPUT_TYPES.xml; - } else if (selectedInputFile.name.endsWith(".csv")) { + } else if (selectedInputFile.name.endsWith('.csv')) { return INPUT_TYPES.csv; } } }, [selectedInputFile]); - const changeToInputView = useCallback(() => setView(views.inputs), [setView]); + const changeView = useCallback((view: ViewType) => setView(view), [setView]); const updateSelectedInputFile = useCallback( (input: string) => { @@ -78,14 +103,17 @@ function InputPanel({ addNewInput }: InputPanelProps) { return (
- + {/* */} + {Object.keys(views).map((viewType) => ( + + {views[viewType as ViewType]} + + ))}
*/}
- {!selectedInputFile && ( -
+ + {!selectedInputFile && view === 'inputs' && ( +
{inputFiles.map((inputFile, index) => { return ( -
{inputFile.name} -
+ ); })}
)} + {view === 'functions' && ( +
+
Sample function list
+ {functionList.map((fn) => ( +
+ {fn.name} +
+ ))} +
+ )} {selectedInputFile && ( <>
@@ -127,7 +166,7 @@ function InputPanel({ addNewInput }: InputPanelProps) { diff --git a/src/css/RMLMappingEditor.module.scss b/src/css/RMLMappingEditor.module.scss index a1c34f5..8add04f 100644 --- a/src/css/RMLMappingEditor.module.scss +++ b/src/css/RMLMappingEditor.module.scss @@ -97,7 +97,6 @@ justify-content: center; } - .header { composes: centered; padding: 0 10px; @@ -284,13 +283,13 @@ overflow: auto; } -.inputFilesList { +.inputItemsList { composes: stretch; overflow: auto; padding: 8px; } -.inputFile { +.inputItem { cursor: pointer; padding: 7px 10px; border-radius: 5px; @@ -302,11 +301,11 @@ color: var(--secondary-text-color); } -.inputFile:hover { +.inputItem:hover { background-color: var(--explorer-item-hover-color); } -.inputFile.Selected { +.inputItem.Selected { background-color: var(--explorer-item-selected-color); color: var(--primary-text-color); } @@ -410,6 +409,10 @@ } } +.functionsListHeader { + color: var(--button-selected-text-color); + padding: 8px 12px; +} .collapsePanelButtonLeft { margin-right: 10px; } diff --git a/src/util/TypeUtil.ts b/src/util/TypeUtil.ts index de57f40..f72126f 100644 --- a/src/util/TypeUtil.ts +++ b/src/util/TypeUtil.ts @@ -16,6 +16,10 @@ export type ValueOf = T[keyof T]; export type ClickEvent = React.MouseEvent; +export enum ViewType { + INPUTS = 'inputs', + FUNCTIONS = 'functions', +} export type PanelType = ValueOf; -export type InputType = ValueOf; \ No newline at end of file +export type InputType = ValueOf;