Skip to content

Commit

Permalink
feat(form): add steps component
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrc committed Dec 10, 2024
1 parent effb06d commit 0dc4a0e
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 13 deletions.
28 changes: 28 additions & 0 deletions formule-demo/cypress/e2e/builder.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,34 @@ describe("test basic functionality", () => {
.should("exist");
});

it("tests steps field", () => {
cy.addFieldWithName("stepsView", "mysteps");
cy.getByDataCy("treeItem").contains("mysteps").as("stepsField");
cy.addFieldWithName("text", "myfield1", "@stepsField");
cy.addFieldWithName("text", "myfield2", "@stepsField");

// Direct navigation
cy.getByDataCy("formPreview")
.find(`input#root${SEP}mysteps${SEP}myfield1`)
.should("exist");
cy.getByDataCy("formPreview")
.find(".ant-steps-item")
.contains("myfield2")
.click();
cy.getByDataCy("formPreview")
.find(`input#root${SEP}mysteps${SEP}myfield2`)
.should("exist");
// Navigation with previous and next buttons
cy.getByDataCy("formPreview").find("button").contains("Previous").click();
cy.getByDataCy("formPreview")
.find(`input#root${SEP}mysteps${SEP}myfield1`)
.should("exist");
cy.getByDataCy("formPreview").find("button").contains("Next").click();
cy.getByDataCy("formPreview")
.find(`input#root${SEP}mysteps${SEP}myfield2`)
.should("exist");
});

it("tests code editor field", () => {
const shouldHaveValidationErrors = (point: boolean, range: boolean) => {
if (!point && !range) {
Expand Down
8 changes: 5 additions & 3 deletions formule-demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
UploadOutlined,
RollbackOutlined,
ToolOutlined,
DownOutlined,
} from "@ant-design/icons";
import {
Button,
Expand Down Expand Up @@ -326,7 +327,7 @@ function App() {
<Row style={{ height: "100%" }}>
<Col
xs={10}
sm={5}
md={5}
style={{
overflowX: "hidden",
height: "100%",
Expand All @@ -337,7 +338,7 @@ function App() {
</Col>
<Col
xs={14}
sm={5}
md={5}
style={{
overflowX: "hidden",
padding: "0px 15px",
Expand All @@ -348,7 +349,7 @@ function App() {
</Col>
<Col
xs={24}
sm={14}
md={14}
style={{
overflowX: "hidden",
height: "100%",
Expand Down Expand Up @@ -386,6 +387,7 @@ function App() {
open={openFloatButtons}
onClick={() => setOpenFloatButtons(!openFloatButtons)}
icon={<ToolOutlined />}
closeIcon={<DownOutlined />}
type="primary"
badge={
!openFloatButtons && hasUnsavedChanges
Expand Down
3 changes: 3 additions & 0 deletions formule-demo/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ export const theme = {
Segmented: {
trackBg: "#E4E8EC",
},
Progress: {
defaultColor: PRIMARY_COLOR,
},
},
};
115 changes: 110 additions & 5 deletions src/admin/utils/fieldTypes.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import {
AimOutlined,
AppstoreOutlined,
BookOutlined,
BorderHorizontalOutlined,
BorderTopOutlined,
CalendarOutlined,
CheckSquareOutlined,
CloudDownloadOutlined,
CodeOutlined,
ContainerOutlined,
AlignCenterOutlined,
FontSizeOutlined,
LayoutOutlined,
LinkOutlined,
NumberOutlined,
SwapOutlined,
TagOutlined,
UnorderedListOutlined,
FieldNumberOutlined,
FileMarkdownOutlined,
NodeIndexOutlined,
} from "@ant-design/icons";
import { placeholder } from "@codemirror/view";

Expand Down Expand Up @@ -54,6 +56,7 @@ export const common = {
type: "boolean",
},
},
// Using dependencies here instead of if-then-else simplifies reusing the common properties
dependencies: {
showAsModal: {
oneOf: [
Expand Down Expand Up @@ -317,6 +320,108 @@ const collections = {
},
},
},
stepsView: {
title: "Steps",
icon: <NodeIndexOutlined />,
child: {},
optionsSchema: {
type: "object",
title: "Steps Field Schema",
properties: {
...common.optionsSchema,
},
},
optionsSchemaUiSchema: {},
optionsUiSchema: {
...common.optionsUiSchema,
type: "object",
title: "UI Schema",
properties: {
"ui:options": {
type: "object",
title: "UI Options",
dependencies:
common.optionsUiSchema.properties["ui:options"].dependencies,
properties: {
...common.optionsUiSchema.properties["ui:options"].properties,
hideSteps: {
type: "boolean",
title: "Hide steps",
tooltip:
"Hide the steps and display a simple progress bar instead",
},
},
if: {
properties: {
hideSteps: {
const: false,
},
},
},
then: {
properties: {
stepsPlacement: {
type: "string",
title: "Steps placement",
oneOf: [
{ const: "horizontal", title: "Horizontal" },
{ const: "vertical", title: "Vertical" },
],
},
hideButtons: {
type: "boolean",
title: "Hide buttons",
tooltip: "Hide the next and previous buttons",
},
hideNumbers: {
type: "boolean",
title: "Hide numbers",
tooltip: "Hide the step numbers and show a simple dot instead",
},
markAsCompleted: {
type: "boolean",
title: "Mark as completed",
tooltip:
"Mark the steps as completed (if correct) after moving to the next one",
},
},
},
},
"ui:label": common.optionsUiSchema.properties["ui:label"],
},
},
optionsUiSchemaUiSchema: {
"ui:options": {
...common.optionsUiSchemaUiSchema["ui:options"],
hideSteps: {
"ui:widget": "switch",
},
hideButtons: {
"ui:widget": "switch",
},
hideNumbers: {
"ui:widget": "switch",
},
markAsCompleted: {
"ui:widget": "switch",
},
},
"ui:label": common.optionsUiSchemaUiSchema["ui:label"],
},
default: {
schema: {
type: "object",
properties: {},
},
uiSchema: {
"ui:object": "stepsView",
"ui:options": {
stepsPlacement: "horizontal",
markAsCompleted: true,
},
},
},
},
layerObjectField: {
title: "Layer",
icon: <BorderHorizontalOutlined />,
Expand Down Expand Up @@ -433,7 +538,7 @@ const simple = {
},
textarea: {
title: "Text area",
icon: <ContainerOutlined />,
icon: <AlignCenterOutlined />,
description: "Text Area field",
child: {},
optionsSchema: {
Expand Down Expand Up @@ -499,7 +604,7 @@ const simple = {
},
number: {
title: "Number",
icon: <NumberOutlined />,
icon: <FieldNumberOutlined />,
description: "IDs, order number, rating, quantity",
child: {},
optionsSchema: {
Expand Down Expand Up @@ -973,7 +1078,7 @@ const advanced = {
},
richeditor: {
title: "Rich/LaTeX editor",
icon: <BookOutlined />,
icon: <FileMarkdownOutlined />,
description: "Rich/LaTeX Editor Field",
child: {},
optionsSchema: {
Expand Down
12 changes: 8 additions & 4 deletions src/forms/Form.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.__Form__ {
height: 100%;
fieldset {
min-width: 0; // prevents overflow of antd Steps component
border: 0;
}
label {
Expand Down Expand Up @@ -114,10 +115,6 @@
display: none;
}

.ant-select-dropdown .ant-select-item-option-content {
white-space: break-spaces;
}

.formule-field-modal {
.ant-modal-content .ant-modal-body {
margin-top: 20px;
Expand Down Expand Up @@ -157,6 +154,13 @@
.bounceShadow {
animation: bounceShadow 5s forwards;
}

.ant-steps-item-icon {
border-radius: unset !important;
.ant-steps-icon {
font-weight: bold;
}
}
}

.tabItemError {
Expand Down
9 changes: 9 additions & 0 deletions src/forms/templates/ObjectFieldTemplate.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PlusCircleOutlined } from "@ant-design/icons";
import TabField from "./Tabs/TabField";
import PropTypes from "prop-types";
import FieldHeader from "./Field/FieldHeader";
import StepsField from "./StepsField";

const ObjectFieldTemplate = ({
description,
Expand Down Expand Up @@ -85,6 +86,14 @@ const ObjectFieldTemplate = ({
idSchema={idSchema}
/>
);
if (uiSchema["ui:object"] == "stepsView")
return (
<StepsField
uiSchema={uiSchema}
properties={properties}
idSchema={idSchema}
/>
);
return (
<fieldset style={{ margin: "0 12px" }} id={idSchema.$id}>
<Row gutter={rowGutter}>
Expand Down
Loading

0 comments on commit 0dc4a0e

Please sign in to comment.