Skip to content

Commit 712c019

Browse files
committed
Add data types here
1 parent ccae965 commit 712c019

36 files changed

+4963
-117
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
"material-icons": "^0.1.0",
5353
"notistack": "^1.0.10",
5454
"prop-types": "^15.7.2",
55+
"react-ace": "^13.0.0",
56+
"react-beautiful-dnd": "^13.1.1",
57+
"react-color": "^2.19.3",
58+
"react-table": "^7.8.0",
5559
"react-virtualized": "^9.22.3",
5660
"react-virtualized-tree": "^3.4.1",
5761
"react-virtuoso": "^4.6.3",
@@ -74,6 +78,7 @@
7478
"@material-ui/lab": "^4.0.0-alpha.61",
7579
"@material-ui/pickers": "^3.3.10",
7680
"@material-ui/styles": "^4.11.5",
81+
"@mov-ai/mov-fe-lib-code-editor": "1.1.4-1",
7782
"@mov-ai/mov-fe-lib-core": "^1.2.3-1",
7883
"@storybook/addon-actions": "^6.4.19",
7984
"@storybook/addon-controls": "^6.4.19",

pnpm-lock.yaml

Lines changed: 461 additions & 117 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import React, { useState, useRef } from "react";
2+
import PropTypes from "prop-types";
3+
import { IconButton, InputAdornment, TextField } from "@material-ui/core";
4+
import { SCOPES } from "../Utils/Constants";
5+
import SelectScopeModal from "./Modal/SelectScopeModal";
6+
import CodeIcon from "@material-ui/icons/Code";
7+
8+
function formatValue(value) {
9+
return value.split("/").pop();
10+
}
11+
12+
const ConfigurationSelector = (props) => {
13+
// Props
14+
const { rowProps = {} } = props;
15+
// State Hooks
16+
const [openModal, setOpenModal] = useState(false);
17+
const [selected, setSelected] = useState(rowProps.rowData?.value);
18+
// Refs
19+
const inputTextRef = useRef();
20+
21+
/**
22+
* On Configuration selected
23+
* @param {string} selectedConfiguration
24+
*/
25+
const onSubmit = (selectedConfiguration) => {
26+
const formatted = formatValue(selectedConfiguration);
27+
rowProps.onChange(formatted);
28+
setSelected(formatted);
29+
setOpenModal(false);
30+
// Set cursor position
31+
globalThis.setImmediate(() => {
32+
if (!inputTextRef.current) return;
33+
const inputText = inputTextRef.current.querySelector("input");
34+
inputText.focus();
35+
const endPosition = inputText.value.length;
36+
inputText.setSelectionRange(endPosition, endPosition);
37+
});
38+
};
39+
40+
//========================================================================================
41+
/* *
42+
* Render *
43+
* */
44+
//========================================================================================
45+
46+
return (
47+
<TextField
48+
style={{ width: "100%" }}
49+
value={selected || ""}
50+
data-testid="selector-text-input"
51+
onChange={(evt) => {
52+
setSelected(evt.target.value);
53+
rowProps.onChange(evt.target.value);
54+
}}
55+
InputProps={{
56+
ref: inputTextRef,
57+
endAdornment: (
58+
<InputAdornment position="end">
59+
<IconButton
60+
data-testid="open-selector-btn"
61+
aria-label="Select configuration"
62+
onClick={() => setOpenModal(true)}
63+
disabled={props.rowProps.disabled}
64+
onMouseDown={(evt) => evt.preventDefault()}
65+
>
66+
<CodeIcon></CodeIcon>
67+
</IconButton>
68+
<SelectScopeModal
69+
open={openModal}
70+
onCancel={() => setOpenModal(false)}
71+
onSubmit={onSubmit}
72+
scopeList={[SCOPES.CONFIGURATION]}
73+
selected={selected}
74+
allowArchive={false}
75+
></SelectScopeModal>
76+
</InputAdornment>
77+
),
78+
}}
79+
/>
80+
);
81+
};
82+
83+
ConfigurationSelector.propTypes = {
84+
rowProps: {
85+
disabled: PropTypes.bool,
86+
onChange: PropTypes.func,
87+
rowData: PropTypes.shape({
88+
value: PropTypes.string,
89+
}),
90+
},
91+
};
92+
93+
export default ConfigurationSelector;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React, { useRef } from "react";
2+
import { IconButton, InputAdornment, TextField } from "@material-ui/core";
3+
import { SelectScopeModal } from "@mov-ai/mov-fe-lib-react";
4+
import { Document } from "@mov-ai/mov-fe-lib-core";
5+
import CodeIcon from "@material-ui/icons/Code";
6+
import PropTypes from "prop-types";
7+
8+
const ConfigurationSelector = (props) => {
9+
const [openModal, setOpenModal] = React.useState(false);
10+
const [selected, setSelected] = React.useState(null);
11+
const inputTextRef = useRef();
12+
const rowProps = props.rowProps;
13+
const rowData = props.rowProps?.rowData;
14+
15+
const formatConfigurationValue = (configuration) => {
16+
const document = Document.parsePath(configuration, SCOPES.Configuration);
17+
// Temporary validation if document is from archive
18+
// TO BE REMOVED AFTER STANDARDIZATION OF PARSING PROCESS
19+
if (document.workspace !== "global") {
20+
props.interface.alert(
21+
"Please note that only configurations from 'global' workspace are accepted at the moment.",
22+
props.interface.ALERTS.warning,
23+
);
24+
}
25+
// Return formatted config name
26+
return document.name;
27+
};
28+
29+
return (
30+
<TextField
31+
style={{ width: "100%" }}
32+
value={rowData?.value || ""}
33+
data-testid="selector-text-input"
34+
onChange={(evt) => rowProps?.onChange(evt.target.value)}
35+
InputProps={{
36+
ref: inputTextRef,
37+
endAdornment: (
38+
<InputAdornment position="end">
39+
<IconButton
40+
data-testid="open-selector-btn"
41+
aria-label="Select configuration"
42+
onClick={() => setOpenModal(true)}
43+
disabled={props.rowProps.disabled}
44+
onMouseDown={(evt) => evt.preventDefault()}
45+
>
46+
<CodeIcon></CodeIcon>
47+
</IconButton>
48+
<SelectScopeModal
49+
open={openModal}
50+
onCancel={() => setOpenModal(false)}
51+
onSubmit={(selectedConfiguration) => {
52+
const formatted = formatConfigurationValue(
53+
selectedConfiguration,
54+
);
55+
rowProps.onChange(formatted);
56+
setSelected(selectedConfiguration);
57+
setOpenModal(false);
58+
// Set cursor position
59+
setImmediate(() => {
60+
if (!inputTextRef.current) return;
61+
const inputText = inputTextRef.current.querySelector("input");
62+
inputText.focus();
63+
const endPosition = inputText.value.length;
64+
inputText.setSelectionRange(endPosition, endPosition);
65+
});
66+
}}
67+
scopeList={[SCOPES.Configuration]}
68+
selected={selected}
69+
allowArchive={false}
70+
></SelectScopeModal>
71+
</InputAdornment>
72+
),
73+
}}
74+
/>
75+
);
76+
};
77+
78+
const SCOPES = {
79+
Configuration: "Configuration",
80+
};
81+
82+
ConfigurationSelector.defaultProps = {};
83+
84+
ConfigurationSelector.propTypes = {
85+
interface: PropTypes.object.isRequired,
86+
};
87+
88+
export default ConfigurationSelector;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// import React from "react";
2+
// import { render, screen } from "@testing-library/react";
3+
import "@testing-library/jest-dom";
4+
// import ConfigurationSelector from "../ConfigurationSelector";
5+
// import { DATA_TYPES } from "../../Utils/DataTypes";
6+
7+
const mockedRowData = { key: "key", type: "string", value: "value" };
8+
const mockedProps = {
9+
rowData: mockedRowData,
10+
onChange: (val) => {
11+
mockedRowData.value = val;
12+
},
13+
};
14+
15+
describe("Test the component ConfigurationSelector", () => {
16+
it("renders the component (smoke test)", () => {
17+
// const { container } = render(
18+
// <ConfigurationSelector rowProps={mockedProps}></ConfigurationSelector>
19+
// );
20+
// const input = screen.getByTestId("selector-text-input");
21+
// const iconButton = screen.getByTestId("open-selector-btn");
22+
// // Validate if main elements are present in component (container, input and iconButton)
23+
// expect(container).toBeInTheDocument();
24+
// expect(input).toBeInTheDocument();
25+
// expect(iconButton).toBeInTheDocument();
26+
});
27+
28+
it("Open SelectScopeModal and validate rowData.value format", () => {
29+
// render(
30+
// <ConfigurationSelector rowProps={mockedProps}></ConfigurationSelector>
31+
// );
32+
// // simulate click to open modal
33+
// // The mocked SelectScopeModal triggers the onSubmit prop when is opened
34+
// const iconButton = screen.getByTestId("open-selector-btn");
35+
// iconButton.click();
36+
// // Check input value
37+
// setImmediate(() => {
38+
// const value = mockedProps.rowData.value;
39+
// const isValidFormat = DATA_TYPES["config"].validation(value);
40+
// expect(isValidFormat).toBeTruthy();
41+
// });
42+
});
43+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React, { useEffect, useRef } from "react";
2+
import MaterialTable from "@material-table/core";
3+
4+
export default function CustomMaterialTable(props) {
5+
const tableRef = useRef();
6+
const openedPanels = useRef({});
7+
const oldFunction = useRef();
8+
9+
useEffect(() => {
10+
if (!oldFunction.current) {
11+
oldFunction.current = tableRef.current?.onToggleDetailPanel;
12+
}
13+
14+
if (oldFunction.current === tableRef.current?.onToggleDetailPanel) {
15+
tableRef.current.onToggleDetailPanel = (path, render) => {
16+
if (tableRef.current.props.data[path[0]]?.tableData?.showDetailPanel) {
17+
delete openedPanels.current[path[0]];
18+
} else {
19+
openedPanels.current = {
20+
...openedPanels.current,
21+
[path[0]]: true,
22+
};
23+
}
24+
25+
oldFunction.current(path, render);
26+
};
27+
}
28+
}, [tableRef]);
29+
30+
return (
31+
<MaterialTable
32+
tableRef={tableRef}
33+
{...props}
34+
data={
35+
props.data?.map((d, i) => {
36+
const detailPanelFunction =
37+
typeof props.detailPanel === "function"
38+
? props.detailPanel
39+
: (rowData) => props.detailPanel[0](rowData).render();
40+
return {
41+
...d,
42+
tableData: {
43+
showDetailPanel: openedPanels.current[i]
44+
? detailPanelFunction
45+
: null,
46+
},
47+
};
48+
}) || []
49+
}
50+
/>
51+
);
52+
}

src/Components/JsonToReact/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# JsonToReact
2+
3+
## Introduction
4+
5+
The main motivation for JsonToReact component is to build forms in a easy way. The easy way is to create a function:Json -> Form.
6+
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).
7+
8+
## Json Semantics
9+
10+
In order to define the form you need 3 Json files:
11+
12+
- schema
13+
- uiSchema
14+
- formData
15+
16+
### Schema
17+
18+
Defines the main structure of the form. It has the following structure
19+
20+
```javascript
21+
Root = {
22+
title: "A Title",
23+
description: "A description",
24+
type: "object",
25+
properties: {
26+
ObjectA: Root || Atom,
27+
...
28+
}
29+
};
30+
31+
Atom = {
32+
AtomName: {
33+
type: "a type",
34+
title: "a title"
35+
},
36+
}
37+
```
38+
39+
### UiSchema
40+
41+
Defines the types of objects.
42+
43+
```javascript
44+
R = {
45+
ObjectName: {
46+
UiAtom || R
47+
}
48+
...
49+
}
50+
51+
UiAtom = {
52+
"ui:<type>": value
53+
}
54+
55+
<type> := disable || widget || options
56+
```
57+
58+
### Data
59+
60+
```javascript
61+
R = {
62+
ObjectA: R || value,
63+
...
64+
}
65+
```

0 commit comments

Comments
 (0)