Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add toggles to Input Panel #19

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/components/InputPanel/InputItem.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className={styles.inputItem} onClick={handleClick}>
{children}
</div>
);
}

export default InputItem;
28 changes: 28 additions & 0 deletions src/components/InputPanel/ViewButton.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<button
className={`${styles.headerButton} ${
isSelected ? styles.headerButtonSelected : ''
}`}
onClick={handleClick}
>
{children}
</button>
);
}

export default ViewButton;
Original file line number Diff line number Diff line change
@@ -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, string> = {
[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>(ViewType.INPUTS);
const { inputFiles, setInputFiles } = useContext(InputContext);
const [selectedInputFileIndex, setSelectedInputFileIndex] =
useState<number>();
Expand All @@ -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) => {
Expand Down Expand Up @@ -78,14 +103,17 @@ function InputPanel({ addNewInput }: InputPanelProps) {
return (
<div className={styles.inputPanel}>
<div className={styles.panelHeader}>
<button
onClick={changeToInputView}
className={`${styles.headerButton} ${
view === views.inputs ? styles.headerButtonSelected : ""
}`}
>
Input Files
</button>
{/* <button onClick={changeToInputView} className={`${styles.headerButton} ${view === views.inputs ? styles.headerButtonSelected : ''}`}>Input Files</button> */}
{Object.keys(views).map((viewType) => (
<ViewButton
key={viewType}
name={viewType as ViewType}
onClick={changeView}
isSelected={view === viewType}
>
{views[viewType as ViewType]}
</ViewButton>
))}
<div className={styles.stretch}></div>
<button
onClick={addNewInput}
Expand All @@ -96,21 +124,32 @@ function InputPanel({ addNewInput }: InputPanelProps) {
{/* <button onClick={changeToJSONInput} className={`${styles.headerButton} ${inputType === INPUT_TYPES.json ? styles.headerButtonSelected : ''}`}>JSON</button>
<button onClick={changeToXMLInput} className={`${styles.headerButton} ${inputType === INPUT_TYPES.xml ? styles.headerButtonSelected : ''}`}>XML</button> */}
</div>
{!selectedInputFile && (
<div className={styles.inputFilesList}>

{!selectedInputFile && view === 'inputs' && (
<div className={styles.inputItemsList}>
{inputFiles.map((inputFile, index) => {
return (
<div
<InputItem
key={index}
className={styles.inputFile}
onClick={setSelectedInputFileIndex.bind(null, index)}
index={index}
onClick={setSelectedInputFileIndex}
>
{inputFile.name}
</div>
</InputItem>
);
})}
</div>
)}
{view === 'functions' && (
<div className={styles.inputItemsList}>
<div className={styles.functionsListHeader}>Sample function list</div>
{functionList.map((fn) => (
<div className={styles.inputItem} key={fn.name}>
{fn.name}
</div>
))}
</div>
)}
{selectedInputFile && (
<>
<div className={styles.panelHeader}>
Expand All @@ -127,7 +166,7 @@ function InputPanel({ addNewInput }: InputPanelProps) {
<CodeEditor
key={selectedInputFileIndex}
mode={inputType}
code={selectedInputFile.contents ?? ""}
code={selectedInputFile.contents ?? ''}
onChange={updateSelectedInputFile}
classes={styles.mappingEditorCodeView}
/>
Expand Down
13 changes: 8 additions & 5 deletions src/css/RMLMappingEditor.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
justify-content: center;
}


.header {
composes: centered;
padding: 0 10px;
Expand Down Expand Up @@ -284,13 +283,13 @@
overflow: auto;
}

.inputFilesList {
.inputItemsList {
composes: stretch;
overflow: auto;
padding: 8px;
}

.inputFile {
.inputItem {
cursor: pointer;
padding: 7px 10px;
border-radius: 5px;
Expand All @@ -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);
}
Expand Down Expand Up @@ -410,6 +409,10 @@
}
}

.functionsListHeader {
color: var(--button-selected-text-color);
padding: 8px 12px;
}
.collapsePanelButtonLeft {
margin-right: 10px;
}
Expand Down
6 changes: 5 additions & 1 deletion src/util/TypeUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export type ValueOf<T> = T[keyof T];

export type ClickEvent = React.MouseEvent<HTMLButtonElement>;

export enum ViewType {
INPUTS = 'inputs',
FUNCTIONS = 'functions',
}
export type PanelType = ValueOf<typeof PANELS>;

export type InputType = ValueOf<typeof INPUT_TYPES>;
export type InputType = ValueOf<typeof INPUT_TYPES>;