Skip to content

Commit

Permalink
Merge pull request #7229 from brionmario/feat-sign-up-composer
Browse files Browse the repository at this point in the history
🚧 [WIP][NEW SIGNUP] Improve functionality
  • Loading branch information
brionmario authored Jan 2, 2025
2 parents 5b8e0d0 + 3956034 commit a7bd1cd
Show file tree
Hide file tree
Showing 47 changed files with 2,011 additions and 456 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* 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 { RequestErrorInterface, RequestResultInterface } from "@wso2is/admin.core.v1/hooks/use-request";
import actions from "../data/actions.json";
import { Actions } from "../models/actions";

/**
* Hook to get the actions supported by the flow builder.
*
* This function calls the GET method of the following endpoint to get the elements.
* - TODO: Fill this
* For more details, refer to the documentation:
* {@link https://TODO:<fillthis>)}
*
* @returns SWR response object containing the data, error, isLoading, isValidating, mutate.
*/
const useGetFlowBuilderCoreActions = <Data = Actions, Error = RequestErrorInterface>(
_shouldFetch: boolean = true
): RequestResultInterface<Data, Error> => {
return {
data: (actions as unknown) as Data,
error: null,
isLoading: false,
isValidating: false,
mutate: () => null
};
};

export default useGetFlowBuilderCoreActions;
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,17 @@ import { IdentifiableComponentInterface } from "@wso2is/core/models";
import { DnDProvider } from "@wso2is/dnd";
import { ReactFlowProvider } from "@xyflow/react";
import classNames from "classnames";
import React, { FunctionComponent, HTMLAttributes, ReactElement } from "react";
import React, { FunctionComponent, ReactElement } from "react";
import ElementPanel from "./element-panel/element-panel";
import ElementPropertiesPanel from "./element-property-panel/element-property-panel";
import VisualFlow from "./visual-flow";
import VisualFlow, { VisualFlowPropsInterface } from "./visual-flow";
import useAuthenticationFlowBuilderCore from "../hooks/use-authentication-flow-builder-core-context";
import { Elements } from "../models/elements";


/**
* Props interface of {@link DecoratedVisualFlow}
*/
export interface DecoratedVisualFlowPropsInterface
extends IdentifiableComponentInterface,
HTMLAttributes<HTMLDivElement> {
/**
* Flow elements.
*/
elements: Elements;
}
export type DecoratedVisualFlowPropsInterface = VisualFlowPropsInterface & IdentifiableComponentInterface;

/**
* Component to decorate the visual flow editor with the necessary providers.
Expand All @@ -56,13 +49,12 @@ const DecoratedVisualFlow: FunctionComponent<DecoratedVisualFlowPropsInterface>
<div
className={ classNames("decorated-visual-flow", "react-flow-container", "visual-editor") }
data-componentid={ componentId }
{ ...rest }
>
<ReactFlowProvider>
<DnDProvider>
<ElementPanel elements={ elements } open={ isElementPanelOpen }>
<ElementPropertiesPanel open={ isElementPropertiesPanelOpen }>
<VisualFlow />
<VisualFlow elements={ elements } { ...rest } />
</ElementPropertiesPanel>
</ElementPanel>
</DnDProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,10 @@ export interface CommonComponentPropertyFactoryPropsInterface extends Identifiab
/**
* The event handler for the property change.
* @param propertyKey - The key of the property.
* @param previousValue - The previous value of the property.
* @param newValue - The new value of the property.
* @param element - The element associated with the property.
*/
onChange: (propertyKey: string, previousValue: any, newValue: any, element: Element) => void;
onChange: (propertyKey: string, newValue: any, element: Element) => void;
}

/**
Expand All @@ -74,10 +73,10 @@ const CommonComponentPropertyFactory: FunctionComponent<CommonComponentPropertyF
if (typeof propertyValue === "boolean") {
return (
<FormControlLabel
control={ <Checkbox /> }
control={ <Checkbox defaultChecked={ propertyValue } /> }
label={ startCase(propertyKey) }
onChange={ (e: ChangeEvent<HTMLInputElement>) =>
onChange(propertyKey, propertyValue, e.target.checked, element)
onChange(`config.field.${propertyKey}`, e.target.checked, element)
}
data-componentid={ `${componentId}-${propertyKey}` }
/>
Expand All @@ -91,7 +90,7 @@ const CommonComponentPropertyFactory: FunctionComponent<CommonComponentPropertyF
label={ startCase(propertyKey) }
defaultValue={ propertyValue }
onChange={ (e: ChangeEvent<HTMLInputElement>) =>
onChange(propertyKey, propertyValue, e.target.value, element)
onChange(`config.field.${propertyKey}`, e.target.value, element)
}
data-componentid={ `${componentId}-${propertyKey}` }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ export interface CommonWidgetPropertyFactoryPropsInterface extends IdentifiableC
/**
* The event handler for the property change.
* @param propertyKey - The key of the property.
* @param previousValue - The previous value of the property.
* @param newValue - The new value of the property.
* @param element - The element associated with the property.
*/
onChange: (propertyKey: string, previousValue: any, newValue: any, element: Element) => void;
onChange: (propertyKey: string, newValue: any, element: Element) => void;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,50 @@
* under the License.
*/

import FormControl from "@oxygen-ui/react/FormControl";
import MenuItem from "@oxygen-ui/react/MenuItem";
import Select from "@oxygen-ui/react/Select";
import Stack from "@oxygen-ui/react/Stack";
import Typography from "@oxygen-ui/react/Typography";
import { IdentifiableComponentInterface } from "@wso2is/core/models";
import { useReactFlow } from "@xyflow/react";
import capitalize from "lodash-es/capitalize";
import isEmpty from "lodash-es/isEmpty";
import React, { ChangeEvent, FunctionComponent, HTMLAttributes, ReactElement } from "react";
import merge from "lodash-es/merge";
import set from "lodash-es/set";
import React, { FunctionComponent, ReactElement } from "react";
import useAuthenticationFlowBuilderCore from "../../hooks/use-authentication-flow-builder-core-context";
import { Base } from "../../models/base";
import { Properties } from "../../models/base";
import { Component } from "../../models/component";
import { Element } from "../../models/elements";

/**
* Props interface of {@link ElementProperties}
*/
export type ElementPropertiesPropsInterface = IdentifiableComponentInterface & HTMLAttributes<HTMLDivElement>;
export type CommonElementPropertiesPropsInterface = IdentifiableComponentInterface & {
properties?: Properties;
/**
* The element associated with the property.
*/
element: Element;
/**
* The event handler for the property change.
* @param propertyKey - The key of the property.
* @param newValue - The new value of the property.
* @param element - The element associated with the property.
*/
onChange: (propertyKey: string, newValue: any, element: Element) => void;
/**
* The event handler for the variant change.
* @param variant - The variant of the element.
*/
onVariantChange?: (variant: string) => void;
};

/**
* Component to generate the properties panel for the selected element.
*
* @param props - Props injected to the component.
* @returns The ElementProperties component.
*/
const ElementProperties: FunctionComponent<ElementPropertiesPropsInterface> = ({
"data-componentid": componentId = "element-properties",
...rest
}: ElementPropertiesPropsInterface): ReactElement => {
const ElementProperties: FunctionComponent<Partial<CommonElementPropertiesPropsInterface>> = ({
"data-componentid": componentId = "element-properties"
}: Partial<CommonElementPropertiesPropsInterface>): ReactElement => {
const { updateNodeData } = useReactFlow();
const {
lastInteractedElement,
Expand All @@ -54,8 +68,6 @@ const ElementProperties: FunctionComponent<ElementPropertiesPropsInterface> = ({
lastInteractedNodeId
} = useAuthenticationFlowBuilderCore();

const hasVariants: boolean = !isEmpty(lastInteractedElement?.variants);

const changeSelectedVariant = (selected: string) => {
const selectedVariant: Component = lastInteractedElement?.variants?.find(
(element: Component) => element.variant === selected
Expand All @@ -64,31 +76,25 @@ const ElementProperties: FunctionComponent<ElementPropertiesPropsInterface> = ({
updateNodeData(lastInteractedNodeId, (node: any) => {
const components: Component = node?.data?.components?.map((component: any) => {
if (component.id === lastInteractedElement.id) {
return {
...component,
...selectedVariant
};
return merge(component, selectedVariant);
}

return component;
});

setLastInteractedElement({
...lastInteractedElement,
...selectedVariant
});
setLastInteractedElement(merge(lastInteractedElement, selectedVariant));

return {
components
};
});
};

const handlePropertyChange = (propertyKey: string, previousValue: any, newValue: any, element: Element) => {
const handlePropertyChange = (propertyKey: string, newValue: any, element: Element) => {
updateNodeData(lastInteractedNodeId, (node: any) => {
const components: Component = node?.data?.components?.map((component: any) => {
if (component.id === element.id) {
component.config.field[propertyKey] = newValue;
set(component, propertyKey, newValue);
}

return component;
Expand All @@ -101,33 +107,15 @@ const ElementProperties: FunctionComponent<ElementPropertiesPropsInterface> = ({
};

return (
<div className="flow-builder-element-properties" data-componentid={ componentId } { ...rest }>
<div className="flow-builder-element-properties" data-componentid={ componentId }>
{ lastInteractedElement ? (
<Stack gap={ 1 }>
{ hasVariants && (
<FormControl size="small" variant="outlined">
<Select
labelId={ `${lastInteractedElement?.variant}-variants` }
id={ `${lastInteractedElement?.variant}-variants` }
value={ lastInteractedElement?.variant }
label="variant"
onChange={ (e: ChangeEvent<HTMLInputElement>) =>
changeSelectedVariant(e.target.value as string)
}
>
{ lastInteractedElement?.variants?.map((element: Base) => (
<MenuItem key={ element?.variant } value={ element?.variant }>
{ capitalize(element?.display?.label) }
</MenuItem>
)) }
</Select>
</FormControl>
) }
{ lastInteractedElement && (
<ElementProperties
element={ lastInteractedElement }
properties={ lastInteractedElement?.config?.field }
onChange={ handlePropertyChange }
onVariantChange={ changeSelectedVariant }
/>
) }
</Stack>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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.
*/

.social-button.oxygen-button {
background: var(--oxygen-palette-common-white);
color: var(--oxygen-palette-common-black);
width: 100%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 1px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);

&:hover {
color: rgba(0, 0, 0, .8);
}

.oxygen-sign-in-option-image {
height: 20px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@

import Button, { ButtonProps } from "@oxygen-ui/react/Button";
import { IdentifiableComponentInterface } from "@wso2is/core/models";
import { Handle, Position } from "@xyflow/react";
import React, { FunctionComponent, ReactElement } from "react";
import ButtonAdapterConstants from "../../../../constants/button-adapter-constants";
import { ButtonVariants, Component } from "../../../../models/component";
import "./button-adapter.scss";

/**
* Props interface of {@link ButtonAdapter}
Expand Down Expand Up @@ -50,25 +53,47 @@ export const ButtonAdapter: FunctionComponent<ButtonAdapterPropsInterface> = ({
config = {
...config,
color: "primary",
fullWidth: true,
variant: "contained"
};
} else if (node.variant === ButtonVariants.Secondary) {
config = {
...config,
color: "secondary",
fullWidth: true,
variant: "contained"
};
} else if (node.variant === ButtonVariants.Text) {
config = {
...config,
fullWidth: true,
variant: "text"
};
} else if (node.variant === ButtonVariants.Social) {
config = {
...config,
className: "social-button",
fullWidth: true,
variant: "contained"
};
}

return (
<Button sx={ node?.variants?.[0]?.config.styles } { ...config }>
{ node?.variants?.[0]?.config?.field?.text }
</Button>
<div className="adapter button-adapter">
<Handle
id={ `${node?.id}${ButtonAdapterConstants.PREVIOUS_BUTTON_HANDLE_SUFFIX}` }
type="source"
position={ Position.Left }
/>
<Button startIcon={ <img src={ node?.display?.image } /> } sx={ node?.config.styles } { ...config }>
{ node?.variants?.[0]?.config?.field?.text }
</Button>
<Handle
id={ `${node?.id}${ButtonAdapterConstants.NEXT_BUTTON_HANDLE_SUFFIX}` }
type="source"
position={ Position.Right }
/>
</div>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export const DefaultInputAdapter: FunctionComponent<DefaultInputAdapterPropsInte
multiline={ node.config?.field?.multiline }
placeholder={ node.config?.field?.placeholder || "" }
required={ node.config?.field?.required }
InputLabelProps={ {
required: node.config?.field?.required
} }
type={ node.config?.field?.type }
style={ node.config?.styles }
/>
Expand Down
Loading

0 comments on commit a7bd1cd

Please sign in to comment.