Skip to content

Commit

Permalink
implemented complex types except object
Browse files Browse the repository at this point in the history
  • Loading branch information
aednikanov committed Jul 2, 2024
1 parent af514a8 commit bce1631
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useContext, useEffect, useState } from "react";
import { FieldTemplateProps } from "@rjsf/utils";
import { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate";
import { SelectWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget";
import styles from "@site/src/components/ParserOpenRPC/InteractiveBox/styles.module.css";
import { ParserOpenRPCContext } from "@site/src/components/ParserOpenRPC";
import clsx from "clsx";

export const ConditionalField = (props: FieldTemplateProps) => {
const [isOpened, setIsOpened] = useState(false);
const [selectedTypeSchema, setSelectedTypeSchema] = useState(null);
const [isEditView, setIsEditView] = useState(false);
const { setIsDrawerContentFixed, setDrawerLabel } = useContext(ParserOpenRPCContext);
const { formData, schema, name, formContext, onChange } = props;
const { setIsComplexTypeView, isComplexTypeView } = formContext;
const listItems = schema?.anyOf ? schema?.anyOf : schema?.oneOf;
const checkForNullTypeSchema = (type) => type === "null";
const showComplexTypeView = () => {
setDrawerLabel(name);
setIsDrawerContentFixed(true);
setIsEditView(true);
setIsComplexTypeView(true);
}
const onDropdownOptionClick = (e) => {
const selectedSchema = listItems.find(({ title }) => title === e.target.innerText);
const isNullTypeSchema = checkForNullTypeSchema(selectedSchema?.type);
if (isNullTypeSchema) {
onChange(null);
} else {
setSelectedTypeSchema(listItems.find(({ title }) => title === e.target.innerText));
showComplexTypeView();
}
setIsOpened(false);
}
const selectWidgetProps = {
...props,
schema: selectedTypeSchema,
label: name,
value: formData,
...(selectedTypeSchema?.enum && {
options:{
enumOptions: selectedTypeSchema?.enum.map(item => ({ label: item, value: item }))
}
})
}
const baseInputProps = {
...props,
schema: selectedTypeSchema
}

useEffect(() => {
if(!isComplexTypeView) {
setIsEditView(false);
setSelectedTypeSchema(null);
}
}, [isComplexTypeView])

return listItems?.length > 0 ? (
<>
<div className={styles.tableRow}>
<div className={styles.tableColumn}>
<label className={styles.tableColumnParam}>{name}</label>
</div>
<div className={styles.tableColumn}>
<div className={clsx(styles.tableValueRow, styles.tableValueRowPadding)}>
{formData === undefined ? "" : String(formData)}
<span className={styles.tableColumnType}>
<span className={styles.dropdown} onClick={() => { setIsOpened(!isOpened); }}>
{schema?.anyOf ? "anyOf" : "oneOf"}
<span className={clsx(styles.tableColumnIcon, styles.chevronIcon, styles.dropdownChevronIcon, !isOpened && styles.chevronIconDown)}/>
<span className={clsx(styles.chevronIcon, styles.dropdownChevronIcon, !isOpened && styles.chevronIconDown)}/>
</span>
<ul className={clsx(styles.dropdownList, !isOpened && styles.dropdownListClosed)}>
{listItems?.map(({ title }, index) => (
<li
className={styles.dropdownItem}
key={index}
onClick={onDropdownOptionClick}
>
{String(title)}
</li>
))}
</ul>
</span>
</div>
</div>
</div>
{isComplexTypeView && isEditView && selectedTypeSchema && selectedTypeSchema.type !== "null" ?
<div className={styles.tableComplexType}>
{selectedTypeSchema?.enum ? <SelectWidget {...selectWidgetProps} /> : <BaseInputTemplate {...baseInputProps} />}
</div>
: null
}
</>
) : null;
}
37 changes: 20 additions & 17 deletions src/components/ParserOpenRPC/InteractiveBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React, { useContext, useEffect, useRef, useState } from "react";
import Form from "@rjsf/core";
import clsx from "clsx";
import { RJSFSchema, UiSchema, RegistryWidgetsType } from "@rjsf/utils";
import {RJSFSchema, UiSchema, RegistryWidgetsType, RegistryFieldsType} from "@rjsf/utils";
import validator from "@rjsf/validator-ajv8";
import $RefParser from "@apidevtools/json-schema-ref-parser";
import { MethodExample, MethodParam, SchemaComponents } from "@site/src/components/ParserOpenRPC/interfaces";
import styles from "./styles.module.css";
import global from "../global.module.css";
import { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate";
import { ArrayFieldTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate";
import { ConditionalField } from "@site/src/components/ParserOpenRPC/InteractiveBox/fields/ConditionalField";
import { DropdownWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget";
import { SelectWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/SelectWidget";
import { Tooltip } from "@site/src/components/ParserOpenRPC/Tooltip";
import { useColorMode } from "@docusaurus/theme-common";
import { ArrayFieldTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/ArrayFieldTemplate";
import { ParserOpenRPCContext } from "@site/src/components/ParserOpenRPC";

interface InteractiveBoxProps {
Expand Down Expand Up @@ -45,10 +47,20 @@ export default function InteractiveBox({ params, components, examples, onParamCh
},
"ui:widget": "checkbox",
};
const templates = {
BaseInputTemplate,
ArrayFieldTemplate,
FieldErrorTemplate: () => null,
ErrorListTemplate: () => null,
}
const widgets: RegistryWidgetsType = {
CheckboxWidget: DropdownWidget,
SelectWidget: SelectWidget,
};
const fields: RegistryFieldsType = {
AnyOfField: ConditionalField,
OneOfField: ConditionalField,
};
const log = (type) => console.log.bind(console, type);
const handleResetForm = (e) => {
e.preventDefault();
setDefaultFormData(defaultExampleFormData);
Expand Down Expand Up @@ -81,6 +93,7 @@ export default function InteractiveBox({ params, components, examples, onParamCh

const onChangeHandler = (data) => {
onParamChange(data);
setDefaultFormData(data);
};

const closeComplexTypeView = () => {
Expand All @@ -107,7 +120,7 @@ export default function InteractiveBox({ params, components, examples, onParamCh
}

const handleCancelClick = () => {
if (drawerLabel && drawerLabel !== null) {
if (drawerLabel) {
const upData = cloneAndSetNullIfExists(defaultFormData, drawerLabel);
setDefaultFormData(upData)
}
Expand All @@ -131,22 +144,12 @@ export default function InteractiveBox({ params, components, examples, onParamCh
validator={validator}
liveValidate
noHtml5Validate
onChange={(data) => {
console.log('changed', data);
onChangeHandler(data.formData);
setDefaultFormData(data.formData);
}}
onSubmit={() => {log("submitted");}}
onError={log("errors")}
templates={{
BaseInputTemplate,
ArrayFieldTemplate,
FieldErrorTemplate: () => null,
ErrorListTemplate: () => null,
}}
onChange={(data) => { onChangeHandler(data.formData); }}
templates={templates}
uiSchema={uiSchema}
widgets={widgets}
ref={formRef}
fields={fields}
>
<div className={clsx(styles.tableFooterRow, isLightTheme ? styles.tableFooterRowLight : styles.tableFooterRowDark)}>
<div className={clsx(styles.footerButtons, styles.footerButtonsLeft)}>
Expand Down
35 changes: 17 additions & 18 deletions src/components/ParserOpenRPC/InteractiveBox/styles.module.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
.tableHeadingRow {
display: flex;
border-top: 1px solid rgba(132, 140, 150, 1);
/*position: fixed;*/
/*z-index: 2;*/
/*width: 100%;*/
}
.tableHeadingColumn {
width: 50%;
Expand All @@ -29,10 +26,14 @@
height: 100%;
padding: 12px 16px 12px 12px;
border-left: 4px solid transparent;
line-height: 28px;
}
.tableColumnParamFocused {
border-left: 4px solid rgba(16, 152, 252, 1);
}
.tableColumnParamError {
border-left: 4px solid rgba(224, 100, 112, 1);
}
.tableColumn:first-child {
border-right: 1px solid rgba(132, 140, 150, 1);
}
Expand All @@ -43,9 +44,10 @@
justify-content: space-between;
align-items: center;
position: relative;
font-size: 14px;
}
.tableValueRowPadding {
padding: 12px 56px 12px 16px;
padding: 12px 72px 12px 16px;
}
.tableColumnType {
display: flex;
Expand All @@ -59,6 +61,12 @@
line-height: 24px;
font-size: 14px;
}
.tableLabelIconError {
width: 11px;
height: 11px;
margin-left: 8px;
background: url("/img/icons/error-icon.svg") no-repeat 50% 50%;
}
.tableColumnIcon {
position: absolute;
right: 13px;
Expand All @@ -68,9 +76,6 @@
.tableColumnIcon:hover {
cursor: pointer;
}
.tableColumnIconError {
background: url("/img/icons/error-icon.svg") no-repeat 50% 50%;
}
.tableColumnIconRemove {
background: url("/img/icons/remove-icon.svg") no-repeat 50% 50%;
}
Expand Down Expand Up @@ -119,18 +124,18 @@
.dropdownList {
position: absolute;
right: 0;
opacity: 1;
visibility: visible;
list-style: none;
border-radius: 10px;
padding: 0;
margin: 0;
top: 35px;
overflow: hidden;
border: 1px solid rgba(132, 140, 150, 1);
transition: 0.4s opacity;
z-index: 2;
}
.dropdownListClosed {
opacity: 0;
visibility: hidden;
}
.dropdownList li + li {
margin-top: 0;
Expand Down Expand Up @@ -255,14 +260,12 @@
width: 100%;
border-radius: 0;
}

.arrayParentRow {
position: relative;
width: 100%;
height: 100%;
padding: 12px 72px 12px 16px;
}

.arrayColumnType {
position: absolute;
top: 0;
Expand All @@ -275,21 +278,20 @@
font-size: 14px;
cursor: pointer;
}

.arrayFormDataWrap {
display: block;
max-width: 395px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}

.addItemBtnWrap {
min-height: 52px;
display: flex;
align-items: center;
padding: 12px;
border-bottom: 1px solid rgba(132, 140, 150, 1);
}

.addItemBtn {
display: flex;
align-items: center;
Expand All @@ -302,7 +304,6 @@
line-height: 1;
cursor: pointer;
}

.addItemIcon {
display: inline-flex;
align-items: center;
Expand All @@ -316,7 +317,6 @@
line-height: 1;
margin-right: 10px;
}

.arrayItemIcon {
position: absolute;
top: 50%;
Expand All @@ -326,7 +326,6 @@
line-height: 1;
font-weight: bold;
}

.arrayItemRowWrap {
position: relative;
padding-left: 40px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useContext } from "react";
import React, { useContext, useState } from "react";
import { useCollapsible, Collapsible } from "@docusaurus/theme-common";
import { ArrayFieldTemplateProps } from "@rjsf/utils";
import { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate";
import styles from "@site/src/components/ParserOpenRPC/InteractiveBox/styles.module.css";
import clsx from "clsx";
import { ParserOpenRPCContext } from "@site/src/components/ParserOpenRPC";

export const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
const { items, canAdd, onAddClick, title, schema, formData, formContext } = props;
export const ArrayFieldTemplate = ({ items, canAdd, onAddClick, title, schema, formData, formContext }: ArrayFieldTemplateProps) => {
const [isComplexArrayEditView, setIsComplexArrayEditView] = useState(false);
const { setIsDrawerContentFixed, setDrawerLabel } = useContext(ParserOpenRPCContext);
const { collapsed, toggleCollapsed } = useCollapsible({ initialState: true });
const itemsType = schema?.items?.type;
Expand All @@ -17,6 +17,7 @@ export const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
onAddClick();
setDrawerLabel(title);
setIsDrawerContentFixed(true);
setIsComplexArrayEditView(true);
setIsComplexTypeView(true);
}

Expand Down Expand Up @@ -48,7 +49,7 @@ export const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
</div>
</div>
</div>
{isComplexTypeView && !isSimpleArray ?
{isComplexTypeView && isComplexArrayEditView && !isSimpleArray ?
<div className={styles.tableComplexType}>
{items.map(({ children, index, onDropIndexClick, hasRemove }) => (
<div className={styles.tableComplexTypeItem} key={index}>
Expand All @@ -73,16 +74,17 @@ export const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
<Collapsible lazy collapsed={collapsed}>
<>
{items.map((el, i) => {
const props = {
const baseInputTemplateProps = {
...el.children.props,
isArray: true
isArray: true,
value: formData,
}
const { index, hasRemove, onDropIndexClick, schema } = el;
const isNumber = schema.type === "number" || schema.type === "integer";
return (
<div key={`${i}`} className={styles.arrayItemRowWrap} style={{ paddingRight: `${isNumber ? "25px" : "0"}` }}>
<span className={clsx(styles.addItemIcon, styles.arrayItemIcon)}>{i+1}</span>
<BaseInputTemplate {...props} />
<BaseInputTemplate {...baseInputTemplateProps} />
{hasRemove && (
<span
onClick={onDropIndexClick(index)}
Expand Down
Loading

0 comments on commit bce1631

Please sign in to comment.