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(codeeditor): add diff viewer, types, schema viewer to demo #43

Merged
merged 1 commit into from
May 27, 2024
Merged
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
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<p align="center"><img src="https://raw.githubusercontent.com/cern-sis/react-formule/master/docs/logo.png" width="350px"/></p>

<h3 align="center"> 🕹️ <a href="https://cern-sis.github.io/react-formule/">DEMO</a> </h2>
<h3 align="center"> 🕹️ <a href="https://cern-sis.github.io/react-formule/">DEMO</a> 🕹️</h3>

[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)

Expand Down Expand Up @@ -32,9 +32,15 @@ Formule consists of the following main components:

It also exports the following functions:

- **`initFormuleSchema`**: Inits the JSONSchema, _needs_ to be run on startup.
- **`initFormuleSchema`**: Inits the JSONSchema, **_needs_** to be run on startup.
- **`getFormuleState`**: Formule has its own internal redux state. You can retrieve it at any moment if you so require for more advanced use cases. If you want to continuosly synchronize the Formule state in your app, you can pass a callback function to FormuleContext instead (see below), which will be called every time the form state changes.

And the following utilities:

- **`CodeEditor`**: Useful if you want to edit the JSON schemas (or any other code) manually.
- **`CodeViewer`**: Useful if you want to visualize the JSON schemas that are being generated (as you can see in the demo).
- **`CodeDiffViewer`**: Useful if you want to compare two different JSON schemas, for example to see the changes since the last save.

### Field types

Formule includes a variety of predefined field types, grouped in three categories:
Expand All @@ -46,7 +52,7 @@ Formule includes a variety of predefined field types, grouped in three categorie
- `Accordion`: When containing a `List`, it works as a `List` with collapsible entries.
- `Layer`: When containing a `List`, it works as a `List` whose entries will open in a dialog window.
- `Tab`: It's commonly supposed to be used as a wrapper around the rest of the elements. You will normally want to add an `Object` inside and you can use it to separate the form in different pages or sections.
- **Advanced fields**: More complex or situational fields such as `URI`, `Rich/Latex editor`, `Tags` and `ID Fetcher`.
- **Advanced fields**: More complex or situational fields such as `URI`, `Rich/Latex editor`, `Tags`, `ID Fetcher` and `Code Editor`.

You can freely remove some of these predefined fields and add your own custom fields and widgets following the JSON Schema specifications. More details below.

Expand Down Expand Up @@ -126,4 +132,4 @@ Alternatively, you can pull the current state on demand by calling `getFormuleSt

## :space_invader: Local demo & how to contribute

You can also clone the repo and run `formule-demo` to play around. Follow the instructions in its [README](./formule-demo/README.md): it will explain how to install `react-formule` as a local dependency (with either `yarn link` or, better, `yalc`) so that you can modify Formule and test the changes live in your host app, which will be ideal if you want to troubleshoot or contribute to the project.
Apart from trying the online [demo](https://cern-sis.github.io/react-formule/) you can clone the repo and run `formule-demo` to play around. Follow the instructions in its [README](./formule-demo/README.md): it will explain how to install `react-formule` as a local dependency (with either `yarn link` or, better, `yalc`) so that you can modify Formule and test the changes live in your host app, which will be ideal if you want to troubleshoot or contribute to the project.
193 changes: 131 additions & 62 deletions formule-demo/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { FormuleContext, SelectOrEdit } from "react-formule";
import { SchemaPreview } from "react-formule";
import { FormPreview } from "react-formule";
import { initFormuleSchema } from "react-formule";
import { useEffect } from "react";
import { Row, Col, Layout, Space, Typography } from "antd";
import { FileTextOutlined } from "@ant-design/icons";
import { Col, FloatButton, Layout, Modal, Row, Space, Typography } from "antd";
import { useEffect, useState } from "react";
import {
CodeViewer,
FormPreview,
FormuleContext,
SchemaPreview,
SchemaWizardState,
SelectOrEdit,
initFormuleSchema,
} from "react-formule";
import { theme } from "./theme";

import "./style.css";
Expand All @@ -15,64 +21,127 @@ function App() {
initFormuleSchema();
}, []);

const [formuleState, setFormuleState] = useState<SchemaWizardState>();
const [modalOpen, setModalOpen] = useState(false);

const handleFormuleStateChange = (newState: SchemaWizardState) => {
setFormuleState(newState);
};

return (
<Layout style={{ height: "100%" }}>
<Content>
<FormuleContext theme={theme}>
<Row style={{ height: "100%" }}>
<Col
xs={10}
sm={5}
style={{
overflowX: "hidden",
height: "100%",
display: "flex",
}}
className="tour-field-types"
>
<SelectOrEdit />
</Col>
<Col
xs={14}
sm={5}
style={{
overflowX: "hidden",
padding: "0px 15px",
backgroundColor: "#F6F7F8",
}}
className="tour-schema-preview"
>
<SchemaPreview />
</Col>
<Col
xs={24}
sm={14}
style={{
overflowX: "hidden",
height: "100%",
padding: "0px 15px",
}}
className="tour-form-preview"
>
<FormPreview liveValidate={true} />
</Col>
</Row>
</FormuleContext>
</Content>
<Footer style={{ padding: 0 }}>
<Row
align="bottom"
justify="center"
style={{ padding: "5px", background: "#001529" }}
>
<Space direction="horizontal" size="middle">
<Typography.Text style={{ color: "rgba(255, 255, 255, 0.65)" }}>
Running react-formule v{import.meta.env.REACT_FORMULE_VERSION}
</Typography.Text>
</Space>
<>
<Modal
title="Generated JSON schemas"
open={modalOpen}
onCancel={() => setModalOpen(false)}
width={1000}
footer={null}
>
<Row gutter={10}>
<Col
xs={12}
style={{
overflowX: "hidden",
height: "100%",
}}
>
<Typography.Text strong>Schema</Typography.Text>
<CodeViewer
value={JSON.stringify(formuleState?.current.schema, null, 2)}
lang="json"
height="50vh"
reset
/>
</Col>
<Col
xs={12}
style={{
overflowX: "hidden",
height: "100%",
}}
>
<Typography.Text strong>UI Schema</Typography.Text>
<CodeViewer
value={JSON.stringify(formuleState?.current.uiSchema, null, 2)}
lang="json"
height="50vh"
reset
/>
</Col>
</Row>
</Footer>
</Layout>
</Modal>
<Layout style={{ height: "100%" }}>
<Content>
<FormuleContext
theme={theme}
synchronizeState={handleFormuleStateChange}
>
<Row style={{ height: "100%" }}>
<Col
xs={10}
sm={5}
style={{
overflowX: "hidden",
height: "100%",
display: "flex",
}}
className="tour-field-types"
>
<SelectOrEdit />
</Col>
<Col
xs={14}
sm={5}
style={{
overflowX: "hidden",
padding: "0px 15px",
backgroundColor: "#F6F7F8",
}}
className="tour-schema-preview"
>
<SchemaPreview />
</Col>
<Col
xs={24}
sm={14}
style={{
overflowX: "hidden",
height: "100%",
padding: "0px 15px",
}}
className="tour-form-preview"
>
<FormPreview liveValidate={true} />
</Col>
</Row>
</FormuleContext>
</Content>
<Footer style={{ padding: 0 }}>
<Row
align="bottom"
justify="center"
style={{ padding: "5px", background: "#001529" }}
>
<Space direction="horizontal" size="middle">
<Typography.Text style={{ color: "rgba(255, 255, 255, 0.65)" }}>
Running react-formule v{import.meta.env.REACT_FORMULE_VERSION}
</Typography.Text>
</Space>
</Row>
</Footer>
</Layout>
<FloatButton
onClick={() => setModalOpen(true)}
shape="square"
description={
<div>
<FileTextOutlined /> View generated schemas
</div>
}
style={{ width: "200px" }}
type="primary"
/>
</>
);
}

Expand Down
14 changes: 7 additions & 7 deletions src/exposed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { ConfigProvider, ThemeConfig } from "antd";
import { Provider } from "react-redux";
import store from "./store/configureStore";
import fieldTypes from "./admin/utils/fieldTypes";
import { FC, ReactNode } from "react";
import { ReactNode } from "react";
import { RJSFSchema } from "@rjsf/utils";
import { schemaInit } from "./store/schemaWizard";
import { SchemaWizardState, schemaInit } from "./store/schemaWizard";
import StateSynchronizer from "./StateSynchronizer";

type FormuleContextProps = {
Expand All @@ -17,19 +17,19 @@ type FormuleContextProps = {
customFields?: object;
customWidgets?: object;
theme?: ThemeConfig;
synchronizeState?: (state: string) => void;
synchronizeState?: (state: SchemaWizardState) => void;
transformSchema?: (schema: object) => object;
};

export const FormuleContext: FC<FormuleContextProps> = ({
export const FormuleContext = ({
children,
customFieldTypes,
customFields,
customWidgets,
theme,
synchronizeState,
transformSchema = (schema) => schema,
}) => {
}: FormuleContextProps) => {
const content = synchronizeState ? (
<StateSynchronizer synchronizeState={synchronizeState}>
{children}
Expand Down Expand Up @@ -63,7 +63,7 @@ export const FormuleContext: FC<FormuleContextProps> = ({
export const initFormuleSchema = (
data?: RJSFSchema,
name?: string,
description?: string
description?: string,
) => {
const { deposit_schema, deposit_options, ...configs } = data || {};
store.dispatch(
Expand All @@ -73,7 +73,7 @@ export const initFormuleSchema = (
? { schema: deposit_schema, uiSchema: deposit_options }
: initSchemaStructure(name, description),
configs: configs || { fullname: name },
})
}),
);
};

Expand Down
17 changes: 13 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { initFormuleSchema } from "./exposed"
export { getFormuleState } from "./exposed"
export { FormuleContext } from "./exposed"
export { initFormuleSchema } from "./exposed";
export { getFormuleState } from "./exposed";
export { FormuleContext } from "./exposed";

export { default as PropertyEditor } from "./admin/components/PropertyEditor";
export { default as SelectFieldType } from "./admin/components/SelectFieldType";
Expand All @@ -10,4 +10,13 @@ export { default as SelectOrEdit } from "./admin/components/SelectOrEdit";

export { default as FormuleForm } from "./forms/Form";

export { common as commonFields, extra as extraFields } from "./admin/utils/fieldTypes"
export {
common as commonFields,
extra as extraFields,
} from "./admin/utils/fieldTypes";

export { default as CodeEditor } from "./utils/CodeEditor";
export { default as CodeViewer } from "./utils/CodeViewer";
export { default as CodeDiffViewer } from "./utils/CodeDiffViewer";

export type { SchemaWizardState } from "./store/schemaWizard";
2 changes: 2 additions & 0 deletions src/store/schemaWizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const initialState = {
version: null,
};

export type SchemaWizardState = typeof initialState;

const schemaWizard = createSlice({
name: "schemaWizard",
initialState,
Expand Down
Loading
Loading