Skip to content

Commit

Permalink
feat: ACT-1359 - Add Interactive Params Table (#1360)
Browse files Browse the repository at this point in the history
* feat(docs): added rpc-parser component for reference pages

* feat(docs): added mm install msg

* feat(docs): change mm condition

* feat(docs): refactored styles

* feat(docs): added request/response section

* feat(docs): added error section

* feat(docs): added eth_call

* added default logic for InteractiveBox

* Made enhancements for components

* returned condition for disabled button

* removed not needed styles in Drawer

* feat(docs): act-1397 - synced params with request section

* added log

* removed log and changed styles

---------

Co-authored-by: ae_atrofimov <[email protected]>
  • Loading branch information
aednikanov and TrofimovAnton85 authored Jun 25, 2024
1 parent d81d2e5 commit f7d3d0b
Show file tree
Hide file tree
Showing 21 changed files with 600 additions and 27 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,29 @@
"**/*.{md,mdx,ts,js,tsx,jsx,json}": "npm run format"
},
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^11.6.4",
"@docusaurus/core": "^3.0.0",
"@docusaurus/plugin-content-docs": "^3.0.0",
"@docusaurus/theme-common": "^3.0.0",
"@docusaurus/theme-mermaid": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"@metamask/design-tokens": "^1.11.1",
"@metamask/docusaurus-openrpc": "^0.4.1",
"@rjsf/core": "^5.18.4",
"@rjsf/utils": "^5.18.4",
"@rjsf/validator-ajv8": "^5.18.4",
"clsx": "^1.2.1",
"docusaurus-plugin-segment": "^1.0.4",
"dotenv": "^16.4.5",
"launchdarkly-js-client-sdk": "^3.3.0",
"lodash.debounce": "^4.0.8",
"node-polyfill-webpack-plugin": "^2.0.1",
"prettier": "^3.0.0",
"prism-react-renderer": "^2.1.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-player": "^2.13.0",
"react-tippy": "^1.4.0",
"remark-codesandbox": "^0.10.1",
"remark-docusaurus-tabs": "^0.2.0"
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/ParserOpenRPC/ErrorsBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function ErrorsBox ({ errors }: ErrorsBoxProps) {
Errors
</Heading>
<div className={styles.errWrapper}>
<div className={clsx(styles.errRowHeading, colorMode === "light" && styles.errRowHeadingLightView)}>
<div className={clsx(styles.errRowHeading, colorMode === "light" ? styles.errRowHeadingLightView : styles.errRowHeadingDarkView)}>
<div className={styles.errColCode}>Code</div>
<div className={styles.errColMsg}>Message</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/components/ParserOpenRPC/ErrorsBox/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
border-bottom: 1px solid #848C96;
font-size: 18px;
font-weight: 700;
}

.errRowHeadingDarkView {
background-color: #24272A;
}

Expand Down
137 changes: 126 additions & 11 deletions src/components/ParserOpenRPC/InteractiveBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,132 @@
import React from "react";
import { MethodParam, SchemaComponents } from "@site/src/components/ParserOpenRPC/interfaces";
import React, { useEffect, useRef, useState } from "react";
import Form from "@rjsf/core";
import clsx from "clsx";
import { RJSFSchema, UiSchema, RegistryWidgetsType } 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 { BaseInputTemplate } from "@site/src/components/ParserOpenRPC/InteractiveBox/templates/BaseInputTemplate";
import { DropdownWidget } from "@site/src/components/ParserOpenRPC/InteractiveBox/widgets/DropdownWidget";
import { Tooltip } from "@site/src/components/ParserOpenRPC/Tooltip";
import { useColorMode } from "@docusaurus/theme-common";

interface InteractiveBoxProps {
method: string;
params: MethodParam[];
components: SchemaComponents;
examples: MethodExample[];
onParamChange: (data) => void;
}

export default function InteractiveBox({ method, params, components }: InteractiveBoxProps) {
console.log("method_name___", method);
console.log("method_params___", params);
console.log("method_components___", components);
return (
<div></div>
);
}
export default function InteractiveBox({ params, components, examples, onParamChange }: InteractiveBoxProps) {
const [parsedSchema, setParsedSchema] = useState<RJSFSchema>(null);
const [defaultFormData, setDefaultFormData] = useState<any>({});
const [isFormReseted, setIsFormReseted] = useState(false);
const formRef = useRef(null);
const { colorMode } = useColorMode();

const defaultExampleFormData = examples ? Object.fromEntries(examples[0].params.map(({ name, value }) => [name, value])) : {};
const schema: RJSFSchema = {
"components": {
"schemas": components,
},
"type": "object",
"properties": Object.fromEntries(params.map(({ name, schema }) => [name, schema])),
};
const uiSchema: UiSchema = {
"ui:globalOptions": {
label: false,
},
"ui:widget": "checkbox",
};
const widgets: RegistryWidgetsType = {
CheckboxWidget: DropdownWidget,
};
const log = (type) => console.log.bind(console, type);
const handleResetForm = (e) => {
e.preventDefault();
setDefaultFormData(defaultExampleFormData);
setIsFormReseted(true);
};
const handleClearForm = (e) => {
e.preventDefault();
if (formRef) {
formRef?.current?.reset();
}
};
const isLightTheme = colorMode === "light"

useEffect(() => {
const dereferenceSchema = async () => {
try {
if (schema) {
setParsedSchema(await $RefParser.dereference(schema) as RJSFSchema);
}
} catch (error) {
console.error("Error of parsing schema:", error);
}
};
dereferenceSchema();
if (examples) {
setDefaultFormData(defaultExampleFormData);
onParamChange(defaultExampleFormData);
}
}, []);

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

return parsedSchema ? (
<>
<div className={styles.tableHeadingRow}>
<div className={styles.tableHeadingColumn}>
Parameter
</div>
<div className={styles.tableHeadingColumn}>
Value
</div>
</div>
<Form
schema={parsedSchema}
formData={defaultFormData}
formContext={{ isFormReseted }}
validator={validator}
liveValidate
noHtml5Validate
onChange={(data) => {
onChangeHandler(data.formData);
setDefaultFormData(data.formData);
}}
onSubmit={() => {log("submitted");}}
onError={log("errors")}
templates={{
BaseInputTemplate,
FieldErrorTemplate: () => null,
ErrorListTemplate: () => null,
}}
uiSchema={uiSchema}
widgets={widgets}
ref={formRef}
>
<div className={clsx(styles.tableFooterRow, isLightTheme ? styles.tableFooterRowLight : styles.tableFooterRowDark)}>
<div className={styles.footerButtons}>
<Tooltip message="Reset fields" theme={isLightTheme ? "dark" : "light"}>
<button className={styles.footerButton} onClick={handleResetForm}>
<img className={styles.footerButtonIcon} src="/img/icons/reset-icon.svg"/>
</button>
</Tooltip>
<Tooltip message="Clear fields" theme={isLightTheme ? "dark" : "light"}>
<button
className={styles.footerButton}
onClick={handleClearForm}
>
<img className={styles.footerButtonIcon} src="/img/icons/clear-icon.svg"/>
</button>
</Tooltip>
</div>
</div>
</Form>
</>
) : null;
}
187 changes: 187 additions & 0 deletions src/components/ParserOpenRPC/InteractiveBox/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
.tableHeadingRow {
display: flex;
border-top: 1px solid rgba(132, 140, 150, 1);
}
.tableHeadingColumn {
width: 50%;
padding: 16px;
line-height: 1.5;
background-color: #292A36;
color: #FFFFFF;
}
.tableRow {
display: flex;
border-top: 1px solid rgba(132, 140, 150, 1);
border-bottom: 1px solid rgba(132, 140, 150, 1);
}
.tableColumn {
width: 50%;
line-height: 24px;
background-color: #292A36;
color: #FFFFFF;
}
.tableColumnParam {
display: flex;
align-items: center;
height: 100%;
padding: 12px 16px 12px 12px;
border-left: 4px solid transparent;
}
.tableColumnParamFocused {
border-left: 4px solid rgba(16, 152, 252, 1);
}
.tableColumn:first-child {
border-right: 1px solid rgba(132, 140, 150, 1);
}
.tableValueRow {
display: flex;
width: 100%;
height: 100%;
justify-content: space-between;
align-items: center;
position: relative;
}
.tableValueRowPadding {
padding: 12px 56px 12px 16px;
}
.tableColumnType {
display: flex;
align-items: center;
position: absolute;
height: 100%;
right: 0;
padding-right: 28px;
padding-bottom: 2px;
color: rgba(187, 192, 197, 1);
line-height: 24px;
font-size: 14px;
}
.tableColumnTypeErrorIcon {
position: absolute;
right: 13px;
width: 11px;
height: 11px;
background: url("/img/icons/error-icon.svg") no-repeat 50% 50%;
}
.chevronIcon {
position: absolute;
right: 13px;
width: 11px;
height: 11px;
background: url("/img/icons/chevron-icon.svg") no-repeat 50% 50%;
}
.chevronIcon:hover {
cursor: pointer;
}
.chevronIconDown {
transform: rotate(180deg);
}
.dropdown {
display: flex;
align-items: center;
}
.dropdown:hover {
cursor: pointer;
}
.dropdownChevronIcon {
transition: 0.2s transform;
}
.dropdownChevronButtonUp {
transform: rotate(180deg);
}
.dropdownList {
position: absolute;
right: 0;
opacity: 1;
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;
}
.dropdownListClosed {
opacity: 0;
}
.dropdownList li + li {
margin-top: 0;
}
.dropdownItem {
width: 102px;
padding: 16px;
background-color: rgba(36, 39, 42, 1);
color: #FFFFFF;
}
.dropdownItem:hover {
background-color: rgba(20, 22, 24, 1);
cursor: pointer;
}
.dropdownItem:not(:last-child) {
border-bottom: 1px solid rgba(132, 140, 150, 1);
}
.tableFooterRow {
position: fixed;
display: flex;
padding: 21px 16px;
width: 100%;
bottom: 0;
}
.tableFooterRowDark {
background-color: #24272A;
}
.tableFooterRowLight {
background-color: #F2F4F6;
}
.formControl {
width: 100%;
padding: 12px 72px 12px 16px;
font-size: 14px;
line-height: 24px;
color: #FFFFFF;
border-radius: 0;
border: 2px solid transparent;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.formControl:focus {
border: 2px solid rgba(16, 152, 252, 1);
outline: none;
}
.formControl[type=number]::-webkit-inner-spin-button,
.formControl[type=number]::-webkit-outer-spin-button {
opacity: 0;
}
.formControlNumberUp {
top: 13px;
}
.formControlNumberDown {
bottom: 15px;
}
.formControlError {
border: 2px solid rgba(224, 100, 112, 1);
}
.footerButtons {
display: flex;
width: 48px;
justify-content: space-between;
}
.footerButton {
display: flex;
width: 16px;
height: 22px;
padding: 0;
align-items: center;
background: none;
border: none;
border-radius: 0;
}
.footerButton:hover {
cursor: pointer;
}
.footerButtonIcon {
width: 100%;
border-radius: 0;
}
Loading

0 comments on commit f7d3d0b

Please sign in to comment.