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

🚧 [WIP][NEW SIGNUP] Add base for widgets #7252

Open
wants to merge 14 commits into
base: new-signup
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ const ElementPanelDraggableNode: FunctionComponent<ElementPanelDraggableNodeProp
variant="square"
className="flow-builder-element-panel-draggable-node-avatar"
/>
<Typography>{ node?.display?.label }</Typography>
<Stack direction="column" spacing={ 0.5 }>
<Typography>{ node?.display?.label }</Typography>
{ node?.display?.description && (
<Typography variant="body2">{ node?.display?.description }</Typography>
) }
</Stack>
</Stack>
</CardContent>
</Card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ export const ButtonAdapter: FunctionComponent<ButtonAdapterPropsInterface> = ({
type="source"
position={ Position.Left }
/>
<Button startIcon={ <img src={ node?.display?.image } /> } sx={ node?.config.styles } { ...config }>
{ node?.variants?.[0]?.config?.field?.text }
<Button sx={ node?.config.styles } { ...config }>
{ node?.config?.field?.text }
</Button>
<Handle
id={ `${node?.id}${ButtonAdapterConstants.NEXT_BUTTON_HANDLE_SUFFIX}` }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const ImageAdapter: FunctionComponent<ImageAdapterPropsInterface> = ({
<img
src={ node?.config?.field?.src }
alt={ node?.config?.field?.alt }
width="100%"
style={ node?.config?.styles }
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import OTPInputAdapter from "./adapters/input/otp-input-adapter";
import PhoneNumberInputAdapter from "./adapters/input/phone-number-input-adapter";
import RichTextAdapter from "./adapters/rich-text-adapter";
import TypographyAdapter from "./adapters/typography-adapter";
import { Component, ComponentTypes, InputVariants } from "../../../models/component";
import { ComponentTypes, InputVariants } from "../../../models/component";
import { Element } from "../../../models/elements";

/**
* Props interface of {@link CommonComponentFactory}
Expand All @@ -42,7 +43,7 @@ export interface CommonComponentFactoryPropsInterface extends IdentifiableCompon
/**
* The node properties.
*/
node: Component;
node: Element;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import Box, { BoxProps } from "@oxygen-ui/react/Box";
import { IdentifiableComponentInterface } from "@wso2is/core/models";
import { GetDragItemProps } from "@wso2is/dnd";
import { useNodeId } from "@xyflow/react";
import classNames from "classnames";
import React, { FunctionComponent, ReactElement, SVGProps } from "react";
import useAuthenticationFlowBuilderCore from "../../../../hooks/use-authentication-flow-builder-core-context";
import { Component } from "../../../../models/component";
import { Element } from "../../../../models/elements";
import getWidgetElements from "../../../../utils/get-widget-elements";
import isWidget from "../../../../utils/is-widget";

/**
* Props interface of {@link ReorderableComponent}
*/
export interface ReorderableComponentPropsInterface
extends IdentifiableComponentInterface,
Omit<BoxProps, "component"> {
/**
* The component to be rendered.
*/
component: Component;
/**
* Additional props needed for the draggable functionality.
*/
draggableProps?: Partial<GetDragItemProps>;
}

// TODO: Move this to Oxygen UI.
/* eslint-disable max-len */
const GridDotsVerticalIcon = ({ ...rest }: SVGProps<SVGSVGElement>): ReactElement => (
<svg fill="#a0a0a0" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg" { ...rest }>
<g id="SVGRepo_bgCarrier" strokeWidth="0" />
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round" />
<g id="SVGRepo_iconCarrier">
<path
d="M686.211 137.143v-.137l68.572.137H686.21Zm0 1508.571c75.566 0 137.143 61.577 137.143 137.143S761.777 1920 686.211 1920c-75.702 0-137.142-61.577-137.142-137.143s61.44-137.143 137.142-137.143Zm548.572 0c75.566 0 137.143 61.577 137.143 137.143S1310.349 1920 1234.783 1920c-75.703 0-137.143-61.577-137.143-137.143s61.44-137.143 137.143-137.143ZM686.21 1097.143c75.566 0 137.143 61.577 137.143 137.143 0 75.565-61.577 137.143-137.143 137.143-75.702 0-137.142-61.578-137.142-137.143 0-75.566 61.44-137.143 137.142-137.143Zm548.572 0c75.566 0 137.143 61.577 137.143 137.143 0 75.565-61.577 137.143-137.143 137.143-75.703 0-137.143-61.578-137.143-137.143 0-75.566 61.44-137.143 137.143-137.143ZM686.21 548.57c75.566 0 137.143 61.578 137.143 137.143 0 75.566-61.577 137.143-137.143 137.143-75.702 0-137.142-61.577-137.142-137.143 0-75.565 61.44-137.143 137.142-137.143Zm548.572 0c75.566 0 137.143 61.578 137.143 137.143 0 75.566-61.577 137.143-137.143 137.143-75.703 0-137.143-61.577-137.143-137.143 0-75.565 61.44-137.143 137.143-137.143ZM686.21 0c75.566 0 137.143 61.577 137.143 137.143S761.776 274.286 686.21 274.286c-75.702 0-137.142-61.577-137.142-137.143S610.509 0 686.21 0Zm548.503 0c75.566 0 137.143 61.577 137.143 137.143s-61.577 137.143-137.143 137.143c-75.565 0-137.143-61.577-137.143-137.143S1159.15 0 1234.714 0Z"
fillRule="evenodd"
/>
</g>
</svg>
);

/**
* Re-orderable component inside a step node.
*
* @param props - Props injected to the component.
* @returns ReorderableComponent component.
*/
export const ReorderableComponent: FunctionComponent<ReorderableComponentPropsInterface> = ({
component,
className,
"data-componentid": componentId = "reorderable-component",
draggableProps
}: ReorderableComponentPropsInterface): ReactElement => {
const nodeId: string = useNodeId();
const { ComponentFactory, setLastInteractedElement } = useAuthenticationFlowBuilderCore();

// Widgets have a flow property which contains the elements of the sub flow.
// If the component is a widget, render the elements of the flow.
if (isWidget(component)) {
return (
<>
{ getWidgetElements(component)?.map((element: Element) => (
<ReorderableComponent
key={ element.id }
component={ element }
className={ className }
draggableProps={ draggableProps }
/>
)
) }
</>
);
}

return (
<Box
display="flex"
alignItems="center"
className={ classNames("reorderable-component", className) }
onClick={ () => setLastInteractedElement(component) }
data-componentid={ `${componentId}-${component.type}` }
{ ...draggableProps }
// TODO: Temporary disable draggable until the dragging animation issue is fixed.
draggable={ false }
>
<div className="flow-builder-step-content-form-field-drag-handle">
<GridDotsVerticalIcon height={ 20 } />
</div>
<div className="flow-builder-step-content-form-field-content">
<ComponentFactory nodeId={ nodeId } node={ component } />
</div>
</Box>
);
};

export default ReorderableComponent;
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@

.flow-builder-step-content-form-field-content {
width: 100%;
display: flex;
flex-direction: column;
gap: var(--oxygen-spacing-1);

.adapter {
position: relative;
Expand All @@ -80,6 +83,8 @@
}
}
}


}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import React, {
MouseEvent,
MutableRefObject,
ReactElement,
SVGProps,
useCallback,
useRef
} from "react";
import ReorderableComponent from "./reorderable-component";
import useAuthenticationFlowBuilderCore from "../../../../hooks/use-authentication-flow-builder-core-context";
import { Component } from "../../../../models/component";
import "./step.scss";
Expand All @@ -47,21 +47,6 @@ import "./step.scss";
*/
export interface StepPropsInterface extends Node, IdentifiableComponentInterface {}

// TODO: Move this to Oxygen UI.
/* eslint-disable max-len */
const GridDotsVerticalIcon = ({ ...rest }: SVGProps<SVGSVGElement>): ReactElement => (
<svg fill="#a0a0a0" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg" { ...rest }>
<g id="SVGRepo_bgCarrier" strokeWidth="0" />
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round" />
<g id="SVGRepo_iconCarrier">
<path
d="M686.211 137.143v-.137l68.572.137H686.21Zm0 1508.571c75.566 0 137.143 61.577 137.143 137.143S761.777 1920 686.211 1920c-75.702 0-137.142-61.577-137.142-137.143s61.44-137.143 137.142-137.143Zm548.572 0c75.566 0 137.143 61.577 137.143 137.143S1310.349 1920 1234.783 1920c-75.703 0-137.143-61.577-137.143-137.143s61.44-137.143 137.143-137.143ZM686.21 1097.143c75.566 0 137.143 61.577 137.143 137.143 0 75.565-61.577 137.143-137.143 137.143-75.702 0-137.142-61.578-137.142-137.143 0-75.566 61.44-137.143 137.142-137.143Zm548.572 0c75.566 0 137.143 61.577 137.143 137.143 0 75.565-61.577 137.143-137.143 137.143-75.703 0-137.143-61.578-137.143-137.143 0-75.566 61.44-137.143 137.143-137.143ZM686.21 548.57c75.566 0 137.143 61.578 137.143 137.143 0 75.566-61.577 137.143-137.143 137.143-75.702 0-137.142-61.577-137.142-137.143 0-75.565 61.44-137.143 137.142-137.143Zm548.572 0c75.566 0 137.143 61.578 137.143 137.143 0 75.566-61.577 137.143-137.143 137.143-75.703 0-137.143-61.577-137.143-137.143 0-75.565 61.44-137.143 137.143-137.143ZM686.21 0c75.566 0 137.143 61.577 137.143 137.143S761.776 274.286 686.21 274.286c-75.702 0-137.142-61.577-137.142-137.143S610.509 0 686.21 0Zm548.503 0c75.566 0 137.143 61.577 137.143 137.143s-61.577 137.143-137.143 137.143c-75.565 0-137.143-61.577-137.143-137.143S1159.15 0 1234.714 0Z"
fillRule="evenodd"
/>
</g>
</svg>
);

/**
* Node for representing an empty step in the flow builder.
*
Expand All @@ -75,7 +60,7 @@ export const Step: FunctionComponent<StepPropsInterface> = ({
const nodeId: string = useNodeId();
const node: Pick<Node, "data"> = useNodesData(nodeId);
const { deleteElements, updateNodeData } = useReactFlow();
const { onElementDropOnCanvas, ComponentFactory, setLastInteractedElement } = useAuthenticationFlowBuilderCore();
const { onElementDropOnCanvas } = useAuthenticationFlowBuilderCore();
const { generateComponentId } = useDnD();

const ref: MutableRefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
Expand All @@ -99,8 +84,11 @@ export const Step: FunctionComponent<StepPropsInterface> = ({

// If the component has variants, add the default variant to the root.
if (!isEmpty(newComponent?.variants)) {
const defaultVariantType: string = newComponent?.display?.defaultVariant ?? newComponent?.variants[0]?.variant;
const defaultVariant: Component = newComponent.variants.find((variant: Component) => variant.variant === defaultVariantType);
const defaultVariantType: string =
newComponent?.display?.defaultVariant ?? newComponent?.variants[0]?.variant;
const defaultVariant: Component = newComponent.variants.find(
(variant: Component) => variant.variant === defaultVariantType
);

newComponent = {
...newComponent,
Expand Down Expand Up @@ -136,11 +124,7 @@ export const Step: FunctionComponent<StepPropsInterface> = ({
onDrop={ handleDrop }
onDrag={ handleDragOver }
>
<Box
display="flex"
justifyContent="space-between"
className="flow-builder-step-action-panel"
>
<Box display="flex" justifyContent="space-between" className="flow-builder-step-action-panel">
<Typography
variant="body2"
data-componentid={ `${componentId}-heading-text` }
Expand Down Expand Up @@ -183,26 +167,15 @@ export const Step: FunctionComponent<StepPropsInterface> = ({
} = getDragItemProps(index);

return (
<Box
display="flex"
alignItems="center"
key={ index }
<ReorderableComponent
key={ component.id }
component={ component }
className={ classNames(
"flow-builder-step-content-form-field",
dragItemClassName
) }
onClick={ () => setLastInteractedElement(component) }
{ ...otherDragItemProps }
// TODO: Fix this. Temporary fix to prevent dragging issues.
draggable={ false }
>
<div className="flow-builder-step-content-form-field-drag-handle">
<GridDotsVerticalIcon height={ 20 } />
</div>
<div className="flow-builder-step-content-form-field-content">
<ComponentFactory nodeId={ nodeId } node={ component } />
</div>
</Box>
draggableProps={ otherDragItemProps }
/>
);
})
}
Expand Down
Loading
Loading