Skip to content

Commit

Permalink
Add data types here
Browse files Browse the repository at this point in the history
  • Loading branch information
quirinpa committed Jan 28, 2025
1 parent ccae965 commit 712c019
Show file tree
Hide file tree
Showing 36 changed files with 4,963 additions and 117 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
"material-icons": "^0.1.0",
"notistack": "^1.0.10",
"prop-types": "^15.7.2",
"react-ace": "^13.0.0",
"react-beautiful-dnd": "^13.1.1",
"react-color": "^2.19.3",
"react-table": "^7.8.0",
"react-virtualized": "^9.22.3",
"react-virtualized-tree": "^3.4.1",
"react-virtuoso": "^4.6.3",
Expand All @@ -74,6 +78,7 @@
"@material-ui/lab": "^4.0.0-alpha.61",
"@material-ui/pickers": "^3.3.10",
"@material-ui/styles": "^4.11.5",
"@mov-ai/mov-fe-lib-code-editor": "1.1.4-1",
"@mov-ai/mov-fe-lib-core": "^1.2.3-1",
"@storybook/addon-actions": "^6.4.19",
"@storybook/addon-controls": "^6.4.19",
Expand Down
578 changes: 461 additions & 117 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions src/Components/ConfigurationSelector.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useState, useRef } from "react";
import PropTypes from "prop-types";
import { IconButton, InputAdornment, TextField } from "@material-ui/core";
import { SCOPES } from "../Utils/Constants";
import SelectScopeModal from "./Modal/SelectScopeModal";
import CodeIcon from "@material-ui/icons/Code";

function formatValue(value) {
return value.split("/").pop();
}

const ConfigurationSelector = (props) => {
// Props
const { rowProps = {} } = props;
// State Hooks
const [openModal, setOpenModal] = useState(false);
const [selected, setSelected] = useState(rowProps.rowData?.value);
// Refs
const inputTextRef = useRef();

/**
* On Configuration selected
* @param {string} selectedConfiguration
*/
const onSubmit = (selectedConfiguration) => {
const formatted = formatValue(selectedConfiguration);
rowProps.onChange(formatted);
setSelected(formatted);
setOpenModal(false);
// Set cursor position
globalThis.setImmediate(() => {
if (!inputTextRef.current) return;
const inputText = inputTextRef.current.querySelector("input");
inputText.focus();
const endPosition = inputText.value.length;
inputText.setSelectionRange(endPosition, endPosition);
});
};

//========================================================================================
/* *
* Render *
* */
//========================================================================================

return (
<TextField
style={{ width: "100%" }}
value={selected || ""}
data-testid="selector-text-input"
onChange={(evt) => {
setSelected(evt.target.value);
rowProps.onChange(evt.target.value);
}}
InputProps={{
ref: inputTextRef,
endAdornment: (
<InputAdornment position="end">
<IconButton
data-testid="open-selector-btn"
aria-label="Select configuration"
onClick={() => setOpenModal(true)}
disabled={props.rowProps.disabled}
onMouseDown={(evt) => evt.preventDefault()}
>
<CodeIcon></CodeIcon>
</IconButton>
<SelectScopeModal
open={openModal}
onCancel={() => setOpenModal(false)}
onSubmit={onSubmit}
scopeList={[SCOPES.CONFIGURATION]}
selected={selected}
allowArchive={false}
></SelectScopeModal>
</InputAdornment>
),
}}
/>
);
};

ConfigurationSelector.propTypes = {
rowProps: {
disabled: PropTypes.bool,
onChange: PropTypes.func,
rowData: PropTypes.shape({
value: PropTypes.string,
}),
},
};

export default ConfigurationSelector;
88 changes: 88 additions & 0 deletions src/Components/ConfigurationSelector/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useRef } from "react";
import { IconButton, InputAdornment, TextField } from "@material-ui/core";
import { SelectScopeModal } from "@mov-ai/mov-fe-lib-react";
import { Document } from "@mov-ai/mov-fe-lib-core";
import CodeIcon from "@material-ui/icons/Code";
import PropTypes from "prop-types";

const ConfigurationSelector = (props) => {
const [openModal, setOpenModal] = React.useState(false);
const [selected, setSelected] = React.useState(null);
const inputTextRef = useRef();
const rowProps = props.rowProps;
const rowData = props.rowProps?.rowData;

const formatConfigurationValue = (configuration) => {
const document = Document.parsePath(configuration, SCOPES.Configuration);
// Temporary validation if document is from archive
// TO BE REMOVED AFTER STANDARDIZATION OF PARSING PROCESS
if (document.workspace !== "global") {
props.interface.alert(
"Please note that only configurations from 'global' workspace are accepted at the moment.",
props.interface.ALERTS.warning,
);
}
// Return formatted config name
return document.name;
};

return (
<TextField
style={{ width: "100%" }}
value={rowData?.value || ""}
data-testid="selector-text-input"
onChange={(evt) => rowProps?.onChange(evt.target.value)}
InputProps={{
ref: inputTextRef,
endAdornment: (
<InputAdornment position="end">
<IconButton
data-testid="open-selector-btn"
aria-label="Select configuration"
onClick={() => setOpenModal(true)}
disabled={props.rowProps.disabled}
onMouseDown={(evt) => evt.preventDefault()}
>
<CodeIcon></CodeIcon>
</IconButton>
<SelectScopeModal
open={openModal}
onCancel={() => setOpenModal(false)}
onSubmit={(selectedConfiguration) => {
const formatted = formatConfigurationValue(
selectedConfiguration,
);
rowProps.onChange(formatted);
setSelected(selectedConfiguration);
setOpenModal(false);
// Set cursor position
setImmediate(() => {
if (!inputTextRef.current) return;
const inputText = inputTextRef.current.querySelector("input");
inputText.focus();
const endPosition = inputText.value.length;
inputText.setSelectionRange(endPosition, endPosition);
});
}}
scopeList={[SCOPES.Configuration]}
selected={selected}
allowArchive={false}
></SelectScopeModal>
</InputAdornment>
),
}}
/>
);
};

const SCOPES = {
Configuration: "Configuration",
};

ConfigurationSelector.defaultProps = {};

ConfigurationSelector.propTypes = {
interface: PropTypes.object.isRequired,
};

export default ConfigurationSelector;
43 changes: 43 additions & 0 deletions src/Components/ConfigurationSelector/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// import React from "react";
// import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
// import ConfigurationSelector from "../ConfigurationSelector";
// import { DATA_TYPES } from "../../Utils/DataTypes";

const mockedRowData = { key: "key", type: "string", value: "value" };
const mockedProps = {
rowData: mockedRowData,
onChange: (val) => {
mockedRowData.value = val;
},
};

describe("Test the component ConfigurationSelector", () => {
it("renders the component (smoke test)", () => {
// const { container } = render(
// <ConfigurationSelector rowProps={mockedProps}></ConfigurationSelector>
// );
// const input = screen.getByTestId("selector-text-input");
// const iconButton = screen.getByTestId("open-selector-btn");
// // Validate if main elements are present in component (container, input and iconButton)
// expect(container).toBeInTheDocument();
// expect(input).toBeInTheDocument();
// expect(iconButton).toBeInTheDocument();
});

it("Open SelectScopeModal and validate rowData.value format", () => {
// render(
// <ConfigurationSelector rowProps={mockedProps}></ConfigurationSelector>
// );
// // simulate click to open modal
// // The mocked SelectScopeModal triggers the onSubmit prop when is opened
// const iconButton = screen.getByTestId("open-selector-btn");
// iconButton.click();
// // Check input value
// setImmediate(() => {
// const value = mockedProps.rowData.value;
// const isValidFormat = DATA_TYPES["config"].validation(value);
// expect(isValidFormat).toBeTruthy();
// });
});
});
52 changes: 52 additions & 0 deletions src/Components/CustomMaterialTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { useEffect, useRef } from "react";
import MaterialTable from "@material-table/core";

export default function CustomMaterialTable(props) {
const tableRef = useRef();
const openedPanels = useRef({});
const oldFunction = useRef();

useEffect(() => {
if (!oldFunction.current) {
oldFunction.current = tableRef.current?.onToggleDetailPanel;
}

if (oldFunction.current === tableRef.current?.onToggleDetailPanel) {
tableRef.current.onToggleDetailPanel = (path, render) => {
if (tableRef.current.props.data[path[0]]?.tableData?.showDetailPanel) {
delete openedPanels.current[path[0]];
} else {
openedPanels.current = {
...openedPanels.current,
[path[0]]: true,
};
}

oldFunction.current(path, render);
};
}
}, [tableRef]);

return (
<MaterialTable
tableRef={tableRef}
{...props}
data={
props.data?.map((d, i) => {
const detailPanelFunction =
typeof props.detailPanel === "function"
? props.detailPanel
: (rowData) => props.detailPanel[0](rowData).render();
return {
...d,
tableData: {
showDetailPanel: openedPanels.current[i]
? detailPanelFunction
: null,
},
};
}) || []
}
/>
);
}
65 changes: 65 additions & 0 deletions src/Components/JsonToReact/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# JsonToReact

## Introduction

The main motivation for JsonToReact component is to build forms in a easy way. The easy way is to create a function:Json -> Form.
This was implemented through a react component called JsonToReact. The whole concept and json semantics is based on [this project](https://github.com/rjsf-team/react-jsonschema-form).

## Json Semantics

In order to define the form you need 3 Json files:

- schema
- uiSchema
- formData

### Schema

Defines the main structure of the form. It has the following structure

```javascript
Root = {
title: "A Title",
description: "A description",
type: "object",
properties: {
ObjectA: Root || Atom,
...
}
};

Atom = {
AtomName: {
type: "a type",
title: "a title"
},
}
```

### UiSchema

Defines the types of objects.

```javascript
R = {
ObjectName: {
UiAtom || R
}
...
}

UiAtom = {
"ui:<type>": value
}

<type> := disable || widget || options
```

### Data

```javascript
R = {
ObjectA: R || value,
...
}
```
Loading

0 comments on commit 712c019

Please sign in to comment.