Repository: wso2/identity-apps
Pull request #7825: Implement Pre Update Profile Extension UI
Author: login: Shenali-SJ
Created: 2025-03-10T08:20:48Z | Merged: 2025-03-16T10:12:15Z

### Description
This PR onboards the pre-update profile extension UI.

**Feature Preview:**

https://github.com/user-attachments/assets/96330372-3efd-404c-92b3-5aa1feeb84ab

**User attribute list UI:**
<img width="600" alt="image" src="https://github.com/user-attachments/assets/cd050d0c-eb56-4847-b5d6-fdd42fa1e18f" />

### Related Issue
- https://github.com/wso2/product-is/issues/23401

NOTE: Please note that this has been temporarily disabled in the UI, until backend improvements are fully integrated.


Diff:
diff --git a/.changeset/mighty-cycles-yell.md b/.changeset/mighty-cycles-yell.md
new file mode 100644
index 00000000000..5ba58f8b43b
--- /dev/null
+++ b/.changeset/mighty-cycles-yell.md
@@ -0,0 +1,8 @@
+---
+"@wso2is/admin.actions.v1": minor
+"@wso2is/admin.core.v1": patch
+"@wso2is/console": patch
+"@wso2is/i18n": patch
+---
+
+Implement Pre Update Profile Extension UI
diff --git a/apps/console/src/configs/routes.tsx b/apps/console/src/configs/routes.tsx
index c124c2bcd2b..9cb570fb0a3 100644
--- a/apps/console/src/configs/routes.tsx
+++ b/apps/console/src/configs/routes.tsx
@@ -1362,6 +1362,17 @@ export const getAppViewRoutes = (): RouteInterface[] => {
                     path: AppConstants.getPaths().get("PRE_UPDATE_PASSWORD_EDIT"),
                     protected: true,
                     showOnSidePanel: false
+                },
+                {
+                    component: lazy(() =>
+                        import("@wso2is/admin.actions.v1/pages/action-configuration-page")
+                    ),
+                    exact: true,
+                    id: "pre-update-profile",
+                    name: "Pre Update Profile",
+                    path: AppConstants.getPaths().get("PRE_UPDATE_PROFILE_EDIT"),
+                    protected: true,
+                    showOnSidePanel: false
                 }
             ],
             component: lazy(() =>
diff --git a/features/admin.actions.v1/components/pre-update-profile-action-config-form.scss b/features/admin.actions.v1/components/pre-update-profile-action-config-form.scss
new file mode 100644
index 00000000000..06b81804e94
--- /dev/null
+++ b/features/admin.actions.v1/components/pre-update-profile-action-config-form.scss
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2025, 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.
+ */
+
+ .form-wrapper {
+    .form-container {
+        margin-top: 0px;
+        margin-bottom: 0px;
+    }
+
+    .box-container {
+        background-color: #f9fafb;
+        border-radius: 8px;
+        padding: 30px;
+
+        .box-field {
+            margin-top: 20px;
+            margin-left: 10px;
+            margin-right: 10px;
+        }
+    }
+
+    .text-field-container {
+        margin-top: 8px;
+        margin-bottom: 8px;
+    }
+
+    .select-field-container {
+        margin-bottom: 8px;
+    }
+
+    .hint-text {
+        margin-top: 0px;
+        margin-bottom: 8px;
+    }
+
+    .divider-container {
+        margin-top: 20px;
+        margin-bottom: 20px;
+    }
+
+    .heading-container {
+        margin-top: 20px;
+        margin-bottom: 20px;
+    }
+
+    .password-sharing-label {
+        margin-bottom: 30px;
+        font-weight: normal
+    }
+
+    .certificate-label {
+        font-weight: normal;
+    }
+
+    .button-container {
+        margin-top: 30px;
+    }
+
+    .alert-title {
+        font-weight: 100;
+    }
+
+    .secondary-button {
+        margin-top: 10px;
+    }
+
+    .placeholder {
+        border-radius: 8px;
+        margin-bottom: 8px;
+
+        &.label {
+            height: 20px;
+            max-width: 100px;
+        }
+
+        &.text-field {
+            height: 40px;
+        }
+    }
+
+    .placeholder-box {
+        > * {
+            margin-bottom: 8px;
+        }
+    }
+}
diff --git a/features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx b/features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
new file mode 100644
index 00000000000..c534e0f061e
--- /dev/null
+++ b/features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
@@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2025, 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 from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import Typography from "@oxygen-ui/react/Typography";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { Claim, IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import UserAttributeList from "./user-attributes/user-attribute-list";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType,
+    PreUpdatePasswordActionConfigFormPropertyInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionInterface,
+    PreUpdateProfileActionUpdateInterface
+} from "../models/actions";
+import "./pre-update-profile-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: PreUpdateProfileActionConfigFormPropertyInterface;
+    /**
+     * Specifies whether the data is still loading.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ userAttributesList, setUserAttributesList ] = useState<Claim[]>([]);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * This sets the the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    /**
+     * Renders the loading placeholders.
+     */
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    /**
+     * Callback function to be triggered when the user attribute list is changed in the child component.
+     * This updates the parent's state.
+     * @param attributes - attributes list.
+     */
+    const handleUserAttributeChange = (attributes: Claim[]) => {
+
+        setUserAttributesList([ ...attributes ]);
+    };
+
+    /**
+     * Validates the pre update profile config form.
+     * @param values - Form values.
+     * @returns form errors.
+     */
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError };
+    };
+
+    /**
+     * Handles the pre update profile form submit.
+     */
+    const handleSubmit = (
+        values: PreUpdatePasswordActionConfigFormPropertyInterface,
+        changedFields: PreUpdatePasswordActionConfigFormPropertyInterface) => {
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: PreUpdateProfileActionInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            const updatingValues: PreUpdateProfileActionUpdateInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: isAuthenticationUpdateFormState || changedFields?.endpointUri ? {
+                    authentication: isAuthenticationUpdateFormState ? {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    } : undefined,
+                    uri: changedFields?.endpointUri ? values.endpointUri : undefined
+                } : undefined,
+                name: changedFields?.name ? values.name : undefined
+            };
+
+            setIsSubmitting(true);
+            updateAction(actionTypeApiPath, initialValues.id, updatingValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.UPDATE);
+                    setIsAuthenticationUpdateFormState(false);
+                    mutateAction();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.UPDATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        }
+    };
+
+    /**
+     * Renders the fields of the pre update profile form.
+     * @returns form fields.
+     */
+    const renderFormFields = (): ReactElement => {
+
+        if (isLoading) {
+            return renderLoadingPlaceholders();
+        }
+
+        return (
+            <>
+                <CommonActionConfigForm
+                    initialValues={ initialValues }
+                    isCreateFormState={ isCreateFormState }
+                    isReadOnly={ isReadOnly }
+                    onAuthenticationTypeChange={ (updatedValue: AuthenticationType, change: boolean) => {
+                        setAuthenticationType(updatedValue);
+                        setIsAuthenticationUpdateFormState(change);
+                    } } />
+                <Divider className="divider-container" />
+                <Typography variant="h6" className="heading-container" >
+                    { t("actions:fields.userAttributes.heading") }
+                </Typography>
+                <UserAttributeList
+                    initialValues={ initialValues?.attributes }
+                    onAttributesChange={ handleUserAttributeChange }
+                    isReadOnly={ isReadOnly }
+                    data-componentid={ `${ componentId }-user-attributes` }
+                />
+
+                { /* This is currently disabled */ }
+                { RuleExpressionsMetaData && showRuleComponent && (
+                    <RuleConfigForm
+                        readonly={ isReadOnly }
+                        rule={ rule }
+                        ruleActionType={ actionTypeApiPath }
+                        setRule={ setRule }
+                        isHasRule={ isHasRule }
+                        setIsHasRule={ setIsHasRule }
+                        data-componentid={ `${ componentId }-rule` }
+                    />
+                ) }
+            </>
+        );
+    };
+
+    return (
+        <>
+            { (isCreateFormState || initialValues) && (
+                <RulesProvider
+                    conditionExpressionsMetaData={ RuleExpressionsMetaData }
+                    initialData={ initialValues?.rule }
+                >
+                    <FinalForm
+                        onSubmit={ (values: PreUpdatePasswordActionConfigFormPropertyInterface, form: any) => {
+                            handleSubmit(values, form.getState().dirtyFields);
+                        } }
+                        validate={ validateForm }
+                        initialValues={ initialValues }
+                        render={ ({ handleSubmit }: FormRenderProps) => (
+                            <EmphasizedSegment
+                                className="form-wrapper"
+                                padded={ "very" }
+                                data-componentid={ `${componentId}-section` }
+                            >
+                                <div className="form-container with-max-width">
+                                    { renderFormFields() }
+                                    { !isLoading && (
+                                        <Button
+                                            size="medium"
+                                            variant="contained"
+                                            onClick={ handleSubmit }
+                                            className={ "button-container" }
+                                            data-componentid={ `${componentId}-primary-button` }
+                                            loading={ isSubmitting }
+                                            disabled={ isReadOnly }
+                                        >
+                                            {
+                                                isCreateFormState
+                                                    ? t("actions:buttons.create")
+                                                    : t("actions:buttons.update")
+                                            }
+                                        </Button>
+                                    ) }
+                                </div>
+                            </EmphasizedSegment>
+                        ) }
+                    >
+                    </FinalForm>
+                </RulesProvider>
+            ) }
+        </>
+    );
+};
+
+export default PreUpdateProfileActionConfigForm;
diff --git a/features/admin.actions.v1/components/user-attributes/user-attribute-list.scss b/features/admin.actions.v1/components/user-attributes/user-attribute-list.scss
new file mode 100644
index 00000000000..1c8eeb71d34
--- /dev/null
+++ b/features/admin.actions.v1/components/user-attributes/user-attribute-list.scss
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2025, 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.
+ */
+
+ .user-attribute-list {
+    padding-top: 3px;
+    
+    .clear-all-button-container {
+        text-align: right;
+        margin-top: 1px;
+        background-color: #f9fafb;
+        box-shadow: 0 2px 2px rgba(203, 206, 219, .2);
+        border-radius: 8px;
+    }
+    .clear-all-button {
+        height: 35px;
+        vertical-align: middle;
+        margin-top: 0;
+        margin: 10px;
+    }
+    .selected-attributes-list{
+        margin-top: 1px;
+        max-height: 300px;
+        overflow-y: auto;
+        scrollbar-width: thin;
+        scrollbar-color: #adb2b6 #f1f1f1;
+    }
+ }
diff --git a/features/admin.actions.v1/components/user-attributes/user-attribute-list.tsx b/features/admin.actions.v1/components/user-attributes/user-attribute-list.tsx
new file mode 100644
index 00000000000..dc88ebfa973
--- /dev/null
+++ b/features/admin.actions.v1/components/user-attributes/user-attribute-list.tsx
@@ -0,0 +1,399 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./user-attribute-list.scss";
+
+export interface UserAttributeListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Previously saved attribute list.
+     */
+    initialValues: string[];
+    /**
+     * Triggers on attribute change to pass the selected attributes to the parent component.
+     */
+    onAttributesChange: (selectedUserAttributes: Claim[]) => void;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const UserAttributeList: FunctionComponent<UserAttributeListPropsInterface> = ({
+    initialValues,
+    onAttributesChange,
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: UserAttributeListPropsInterface): ReactElement => {
+
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ finalAttributeList, setFinalAttributeList ] = useState<Claim[]>([]);
+    const [ isGetAllLocalClaimsLoading, setIsGetAllLocalClaimsLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * This useEffect retrieves all the claims in the local dialect.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsGetAllLocalClaimsLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsGetAllLocalClaimsLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsGetAllLocalClaimsLoading(false);
+        });
+    }, []);
+
+    /**
+     * This useEffect handles previously added attributes.
+     */
+    useEffect(() => {
+
+        if(!initialValues?.length || !allAttributesList?.length) {
+            return;
+        }
+
+        // Remove duplicates and create a new array with the initial values and the final attribute list.
+        const tempFinalURIs: string[] =
+        [ ...new Set([ ...initialValues, ...finalAttributeList?.map((claim: Claim) => claim.claimURI) ]) ];
+
+        setFinalAttributeList(allAttributesList?.filter((claim: Claim) => tempFinalURIs?.includes(claim.claimURI)));
+    }, [ initialValues, allAttributesList ]);
+
+    /**
+     * This useEffects passes the final attribute list to the parent.
+     */
+    useEffect(() => {
+
+        onAttributesChange(finalAttributeList);
+    }, [ finalAttributeList ]);
+
+    /**
+     * Renders the loading placeholders for the user attribute list.
+     */
+    const renderAttributeListLoadingPlaceholders = (): ReactElement => (
+
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 10 } />
+            <Skeleton variant="rectangular" height={ 25 } />
+            <Skeleton variant="rectangular" height={ 10 } />
+            <Skeleton variant="rectangular" height={ 10 } />
+        </Box>
+    );
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     *
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Checks if the selected attribute is already added.
+     *
+     * @param selectedAttribute - Selected attribute.
+     */
+    const isAttributeAlreadyAdded = (selectedAttribute: Claim): boolean => {
+
+        return finalAttributeList?.some((existingAttribute: Claim) =>
+            existingAttribute?.claimURI === selectedAttribute?.claimURI
+        );
+    };
+
+    /**
+     * Handles the selection of an attribute from the autocomplete dropdown.
+     *
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        // Clears the search input after the selected attribute is added.
+        setInputValue(ActionsConstants.EMPTY_STRING);
+
+        if (isAttributeAlreadyAdded(data as Claim)) {
+            return;
+        };
+
+        setFinalAttributeList([ ...finalAttributeList, data as Claim ]);
+    };
+
+    /**
+     * Handles the deletion of an attribute from the selected attributes list.
+     *
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setFinalAttributeList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     *
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the columns to be displayed in the selected attributes list table.
+     *
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-selected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+
+            {
+                isGetAllLocalClaimsLoading ? renderAttributeListLoadingPlaceholders() : (
+                    finalAttributeList?.length > 0 && (
+                        <div className="user-attribute-list">
+                            <div className="clear-all-button-container">
+                                <Button
+                                    onClick={ () => setFinalAttributeList([]) }
+                                    variant="outlined"
+                                    size="small"
+                                    className="secondary-button clear-all-button"
+                                    data-componentid={ `${ componentId }-clear-all-button` }
+                                    disabled={ false }
+                                >
+                                    { t("actions:fields.userAttributes.search.clearButton") }
+                                </Button>
+                            </div>
+                            <div className="selected-attributes-list">
+                                <DataTable<Claim[]>
+                                    className="selected-attributes-list-data-table"
+                                    actions={ resolveTableActions() }
+                                    columns={ resolveTableColumns() }
+                                    data={ finalAttributeList }
+                                    onRowClick={ () => null }
+                                    showHeader={ false }
+                                    data-componentid={ `${componentId}-selected-attributes-list` }
+                                />
+                            </div>
+                        </div>
+                    ))
+            }
+        </>
+    );
+};
+
+export default UserAttributeList;
diff --git a/features/admin.actions.v1/constants/actions-constants.ts b/features/admin.actions.v1/constants/actions-constants.ts
index a8135322a30..b0030d1b830 100644
--- a/features/admin.actions.v1/constants/actions-constants.ts
+++ b/features/admin.actions.v1/constants/actions-constants.ts
@@ -70,6 +70,8 @@ export class ActionsConstants {
 
     public static readonly ACTION_COMING_SOON_LABEL: string = "COMING_SOON";
 
+    public static readonly EMPTY_STRING: string = "";
+
     public static readonly ERROR_MESSAGES: {
         CREATE_ACTION_INVALID_STATUS_CODE_ERROR: IdentityAppsError;
         DELETE_ACTION_INVALID_STATUS_CODE_ERROR: IdentityAppsError;
@@ -154,5 +156,6 @@ export class ActionsConstants {
      */
     public static readonly FEATURE_DICTIONARY: Map<string, string> = new Map<string, string>()
         .set("PRE_ISSUE_ACCESS_TOKEN_RULE", "actions.types.preIssueAccessToken.edit.rule")
-        .set("PRE_UPDATE_PASSWORD_RULE", "actions.types.preUpdatePassword.edit.rule");
+        .set("PRE_UPDATE_PASSWORD_RULE", "actions.types.preUpdatePassword.edit.rule")
+        .set("PRE_UPDATE_PROFILE_RULE", "actions.types.preUpdateProfile.edit.rule");
 }
diff --git a/features/admin.actions.v1/models/actions.ts b/features/admin.actions.v1/models/actions.ts
index c9c7d6a70ae..04edbdad9f6 100644
--- a/features/admin.actions.v1/models/actions.ts
+++ b/features/admin.actions.v1/models/actions.ts
@@ -97,6 +97,16 @@ export interface PreUpdatePasswordActionInterface extends ActionInterface {
     passwordSharing: PasswordSharing;
 }
 
+/**
+ * Pre Update Profile Action configuration.
+ */
+export interface PreUpdateProfileActionInterface extends ActionInterface {
+    /**
+     * User attribute list.
+     */
+    attributes?: string[];
+}
+
 /**
  *  Endpoint configuration.
  */
@@ -236,6 +246,13 @@ export interface PreUpdatePasswordActionResponseInterface extends ActionResponse
     passwordSharing: PasswordSharing;
 }
 
+export interface PreUpdateProfileActionResponseInterface extends ActionResponseInterface {
+    /**
+     * User attribute list.
+     */
+    attributes?: string[];
+}
+
 /**
  *  Password Sharing configuration.
  */
@@ -301,6 +318,16 @@ export interface PreUpdatePasswordActionUpdateInterface extends ActionUpdateInte
     passwordSharing?: PasswordSharingUpdate;
 }
 
+/**
+ * Pre Update Profile Action Update configuration.
+ */
+export interface PreUpdateProfileActionUpdateInterface extends ActionUpdateInterface {
+    /**
+     * User attribute list.
+     */
+    attributes?: string[];
+}
+
 /**
  *  Password Sharing Format in Update configuration
  */
@@ -423,6 +450,16 @@ export interface PreUpdatePasswordActionConfigFormPropertyInterface extends Acti
     certificate: string;
 }
 
+/**
+ * Pre Update Profile Action config form property Interface.
+ */
+export interface PreUpdateProfileActionConfigFormPropertyInterface extends ActionConfigFormPropertyInterface {
+    /**
+     * User attribute list.
+     */
+    attributes: string[];
+}
+
 /**
  *  Action Type card info Interface.
  */
diff --git a/features/admin.actions.v1/package.json b/features/admin.actions.v1/package.json
index d80dc6224fc..8e6335c372d 100644
--- a/features/admin.actions.v1/package.json
+++ b/features/admin.actions.v1/package.json
@@ -12,6 +12,7 @@
         "@oxygen-ui/react-icons": "^2.3.4",
         "@wso2is/access-control": "^3.3.20",
         "@wso2is/admin.core.v1": "^2.40.6",
+        "@wso2is/admin.claims.v1": "^2.27.113",
         "@wso2is/admin.extensions.v1": "^2.36.128",
         "@wso2is/admin.feature-gate.v1": "^1.4.203",
         "@wso2is/admin.rules.v1": "^0.4.19",
diff --git a/features/admin.actions.v1/pages/action-configuration-page.tsx b/features/admin.actions.v1/pages/action-configuration-page.tsx
index 7e7b85f1df8..3ef9a6c8b28 100644
--- a/features/admin.actions.v1/pages/action-configuration-page.tsx
+++ b/features/admin.actions.v1/pages/action-configuration-page.tsx
@@ -51,10 +51,13 @@ import useGetActionById from "../api/use-get-action-by-id";
 import useGetActionsByType from "../api/use-get-actions-by-type";
 import PreIssueAccessTokenActionConfigForm from "../components/pre-issue-access-token-action-config-form";
 import PreUpdatePasswordActionConfigForm from "../components/pre-update-password-action-config-form";
+import PreUpdateProfileActionConfigForm from "../components/pre-update-profile-action-config-form";
 import { ActionsConstants } from "../constants/actions-constants";
 import {
     ActionConfigFormPropertyInterface, PreUpdatePasswordActionConfigFormPropertyInterface,
-    PreUpdatePasswordActionResponseInterface
+    PreUpdatePasswordActionResponseInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionResponseInterface
 } from "../models/actions";
 import "./action-configuration-page.scss";
 import { useHandleError, useHandleSuccess } from "../util/alert-util";
@@ -160,6 +163,19 @@ const ActionConfigurationPage: FunctionComponent<ActionConfigurationPageInterfac
             }
         }, [ action ]);
 
+    const preUpdateProfileActionInitialValues: PreUpdateProfileActionConfigFormPropertyInterface =
+        useMemo(() => {
+
+            if (action && actionTypeApiPath === ActionsConstants.PRE_UPDATE_PROFILE_API_PATH ) {
+                return {
+                    ...actionCommonInitialValues,
+                    attributes: (action as PreUpdateProfileActionResponseInterface)?.attributes
+                };
+            } else {
+                return null;
+            }
+        }, [ action ]);
+
     /**
      * The following useEffect is used to handle if any error occurs while fetching Actions by Type.
      */
@@ -414,6 +430,16 @@ const ActionConfigurationPage: FunctionComponent<ActionConfigurationPageInterfac
                                 />
                             )
                             }
+                            { actionTypeApiPath === ActionsConstants.PRE_UPDATE_PROFILE_API_PATH && (
+                                <PreUpdateProfileActionConfigForm
+                                    initialValues={ preUpdateProfileActionInitialValues }
+                                    isLoading={ isLoading }
+                                    isReadOnly={ isReadOnly() }
+                                    actionTypeApiPath={ actionTypeApiPath }
+                                    isCreateFormState={ showCreateForm }
+                                />
+                            )
+                            }
                         </Grid.Column>
                     </Grid.Row>
                 </Grid>
diff --git a/features/admin.actions.v1/pages/actions.tsx b/features/admin.actions.v1/pages/actions.tsx
index d96a2fe968c..768adcbdb05 100644
--- a/features/admin.actions.v1/pages/actions.tsx
+++ b/features/admin.actions.v1/pages/actions.tsx
@@ -270,7 +270,7 @@ export const ActionTypesListingPage: FunctionComponent<ActionTypesListingPageInt
                 icon: <ProfileFlowIcon size="small" className="icon"/>,
                 identifier: ActionsConstants.PRE_UPDATE_PROFILE_URL_PATH,
                 route: isActionTypeDisabled(FeatureFlagConstants.FEATURE_FLAG_KEY_MAP
-                    .ACTIONS_TYPES_PRE_UPDATE_PASSWORD) ? undefined
+                    .ACTIONS_TYPES_PRE_UPDATE_PROFILE) ? undefined
                     : AppConstants.getPaths().get("PRE_UPDATE_PROFILE_EDIT")
             },
             {
diff --git a/features/admin.actions.v1/public-api.ts b/features/admin.actions.v1/public-api.ts
index 234d9638345..3b396c59621 100644
--- a/features/admin.actions.v1/public-api.ts
+++ b/features/admin.actions.v1/public-api.ts
@@ -19,3 +19,4 @@
 export { default as ActionTypesListingPage } from "./pages/actions";
 export { default as PreIssueAccessTokenActionConfigForm } from "./components/pre-issue-access-token-action-config-form";
 export { default as PreUpdatePasswordActionConfigForm } from "./components/pre-update-password-action-config-form";
+export { default as PreUpdateProfileActionConfigForm } from "./components/pre-update-profile-action-config-form";
diff --git a/features/admin.core.v1/constants/app-constants.ts b/features/admin.core.v1/constants/app-constants.ts
index d9ae10189b5..6040611102d 100644
--- a/features/admin.core.v1/constants/app-constants.ts
+++ b/features/admin.core.v1/constants/app-constants.ts
@@ -416,6 +416,8 @@ export class AppConstants {
                 `${AppConstants.getAdminViewBasePath()}/actions/pre-issue-access-token` ],
             [ "PRE_UPDATE_PASSWORD_EDIT",
                 `${AppConstants.getAdminViewBasePath()}/actions/pre-update-password` ],
+            [ "PRE_UPDATE_PROFILE_EDIT",
+                `${AppConstants.getAdminViewBasePath()}/actions/pre-update-profile` ],
             [ "TENANTS", `${AppConstants.getDefaultLayoutBasePath()}/organizations` ],
             [ "EDIT_TENANT", `${AppConstants.getDefaultLayoutBasePath()}/organizations/:id` ],
             [ "SYSTEM_SETTINGS", `${AppConstants.getDefaultLayoutBasePath()}/organizations/system-settings` ],
diff --git a/modules/i18n/src/models/namespaces/actions-ns.ts b/modules/i18n/src/models/namespaces/actions-ns.ts
index 0163134af23..d470cd4c82d 100644
--- a/modules/i18n/src/models/namespaces/actions-ns.ts
+++ b/modules/i18n/src/models/namespaces/actions-ns.ts
@@ -184,7 +184,15 @@ export interface actionsNS {
                 }
             };
             label: string;
-        }
+        };
+        userAttributes: {
+            heading: string;
+            hint: string;
+            search: {
+                placeholder: string;
+                clearButton: string;
+            };
+        };
     };
     goBackActions: string,
     notification: {
@@ -283,6 +291,12 @@ export interface actionsNS {
                     message: string;
                 };
             };
+            userAttributes: {
+                getAttributes: {
+                    description: string;
+                    message: string;
+                };
+            };
         };
         success: {
             activate: {
diff --git a/modules/i18n/src/translations/en-US/portals/actions.ts b/modules/i18n/src/translations/en-US/portals/actions.ts
index 408686f2bc0..586458e5671 100644
--- a/modules/i18n/src/translations/en-US/portals/actions.ts
+++ b/modules/i18n/src/translations/en-US/portals/actions.ts
@@ -194,6 +194,14 @@ export const actions: actionsNS = {
                 title: "No execution rule is configured."
             },
             label: "Execution Rule"
+        },
+        userAttributes: {
+            heading: "Attributes",
+            hint: "Select user attributes that need to be shared with the external service.",
+            search: {
+                clearButton: "Clear all",
+                placeholder: "Search user attribute"
+            }
         }
     },
     goBackActions: "Go back to Actions",
@@ -292,6 +300,12 @@ export const actions: actionsNS = {
             update: {
                 description: "Couldn't update the action.",
                 message: "Something went wrong."
+            },
+            userAttributes: {
+                getAttributes: {
+                    description: "Couldn't retrieve the user attributes.",
+                    message: "Something went wrong"
+                }
             }
         },
         success: {
@@ -362,8 +376,7 @@ export const actions: actionsNS = {
         },
         preUpdateProfile: {
             description: {
-                expanded: "This action is executed before updating the profile of a user. " +
-                "Refer the documentation for the API definition to implement.",
+                expanded: "Use this action to validate user attributes at profile update.",
                 shortened: "This action is executed before updating the profile of a user."
             },
             heading: "Pre Update Profile"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bc24ae0cc53..e8f5da03e37 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1568,6 +1568,9 @@ importers:
       '@wso2is/access-control':
         specifier: ^3.3.20
         version: link:../../modules/access-control
+      '@wso2is/admin.claims.v1':
+        specifier: ^2.27.113
+        version: link:../admin.claims.v1
       '@wso2is/admin.core.v1':
         specifier: ^2.40.6
         version: link:../admin.core.v1
@@ -25721,7 +25724,6 @@ packages:
   /@mui/base@5.0.0-alpha.108(@types/react@18.0.18)(react-dom@18.3.1)(react@18.3.1):
     resolution: {integrity: sha512-KjzRUts2i/ODlMfywhFTqTzQl+Cr9nlDSZxJcnYjrbOV/iRyQNBTDoiFJt+XEdRi0fZBHnk74AFbnP56ehybsA==}
     engines: {node: '>=12.0.0'}
-    deprecated: This package has been replaced by @base-ui-components/react
     peerDependencies:
       '@types/react': 18.0.18
       react: ^17.0.0 || ^18.0.0


Reviews:
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:23:56Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:27:30Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:27:38Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:29:21Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:30:26Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:32:17Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:35:07Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T04:38:31Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T05:00:50Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T05:04:11Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T20:49:22Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T07:36:36Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T07:37:02Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:45:21Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:45:27Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:45:37Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:45:47Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:47:32Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:47:50Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:47:56Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:57:02Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:57:17Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T17:03:23Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T17:03:35Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T17:13:03Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T17:13:21Z
user: login: pavinduLakshan
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-15T03:39:37Z
user: login: pavinduLakshan
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-15T03:40:07Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:17:14Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:18:20Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:19:45Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:20:16Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:26:55Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:27:41Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:27:53Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:27:59Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:28:50Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:29:14Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T09:29:21Z
user: login: pavinduLakshan
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-15T09:42:23Z
user: login: pavinduLakshan
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-03-15T09:44:09Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T10:10:49Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T15:01:02Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T15:01:09Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:27:48Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:28:14Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:30:29Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:54:12Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:54:25Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:54:31Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T08:54:53Z
user: login: ashanthamara
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T10:10:46Z
user: login: ashanthamara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-16T10:12:01Z
user: login: Shenali-SJ
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T04:25:04Z

Review comments:
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: We may need to duplicate this api in actions component as actions should not depend on claims component
created_at: 2025-03-12T04:23:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: Lets remove the data-testid
created_at: 2025-03-12T04:27:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-testid={ `${componentId}-selected-attribute-initial-letter` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: Same as above
created_at: 2025-03-12T04:27:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-testid={ `${componentId}-selected-attribute-initial-letter` }
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:attributes.hint") }</Hint>
+            <Autocomplete
+                disablePortal
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                renderOption={ (props, option: Claim) => (
+                    <li { ...props }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:attributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                key="autocompleteSearchWithList"
+                data-testid={ `${componentId}-select-attributes` }
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden />
+            {
+                selectedAttributesList?.length > 0 && (
+                    <DataTable<Claim[]>
+                        className="external-dialects-list"
+                        actions={ resolveTableActions() }
+                        columns={ resolveTableColumns() }
+                        data={ selectedAttributesList }
+                        onRowClick={ () => null }
+                        showHeader={ false }
+                        data-testid={ `${componentId}-selected-attributes-list` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: same as above
created_at: 2025-03-12T04:29:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: This should have a separate translation in actions namespace
created_at: 2025-03-12T04:30:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -19,6 +19,13 @@
 import { actionsNS } from "../../../models";
 
 export const actions: actionsNS = {
+    attributes: {
path: modules/i18n/src/translations/en-US/portals/actions.ts
user: login: ashanthamara
body: This should be inside `fields`
created_at: 2025-03-12T04:32:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleExecuteCollectionWithoutIdInterface, RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    ActionInterface,
+    ActionUpdateInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType
+} from "../models/actions";
+import "./pre-update-password-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+import AttributeSearchList from "./attributesSection/attribute-search-list";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: ActionConfigFormPropertyInterface;
+    /**
+     * Flag for loading state.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Action Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: _componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * The following useEffect is used to set the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const customError: Partial<ActionConfigFormPropertyInterface> = {};
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: ashanthamara
body: We don't have custom validations for the attributes dropdown right ?
created_at: 2025-03-12T04:35:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleExecuteCollectionWithoutIdInterface, RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    ActionInterface,
+    ActionUpdateInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType
+} from "../models/actions";
+import "./pre-update-password-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+import AttributeSearchList from "./attributesSection/attribute-search-list";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: ActionConfigFormPropertyInterface;
+    /**
+     * Flag for loading state.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Action Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: _componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * The following useEffect is used to set the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const customError: Partial<ActionConfigFormPropertyInterface> = {};
+
+        // Call the utility validate function
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError, ...customError };
+
+    };
+
+    const handleSubmit = (
+        values: ActionConfigFormPropertyInterface,
+        changedFields: ActionConfigFormPropertyInterface) => {
+
+        let rulePayload: RuleWithoutIdInterface | RuleExecuteCollectionWithoutIdInterface | Record<string, never>;
+
+        if (isHasRule) {
+            rulePayload = rule;
+        } else if (!isCreateFormState && !rule) {
+            rulePayload = {};
+        }
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: ActionInterface = {
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name,
+                rule: rulePayload ?? undefined
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            // Updating the action
+            const updatingValues: ActionUpdateInterface = {
+                endpoint: isAuthenticationUpdateFormState || changedFields?.endpointUri ? {
+                    authentication: isAuthenticationUpdateFormState ? {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    } : undefined,
+                    uri: changedFields?.endpointUri ? values.endpointUri : undefined
+                } : undefined,
+                name: changedFields?.name ? values.name : undefined,
+                rule: rulePayload ?? undefined
+            };
+
+            setIsSubmitting(true);
+            updateAction(actionTypeApiPath, initialValues.id, updatingValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.UPDATE);
+                    setIsAuthenticationUpdateFormState(false);
+                    mutateAction();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.UPDATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        }
+    };
+
+    const renderFormFields = (): ReactElement => {
+
+        if (isLoading) {
+            return renderLoadingPlaceholders();
+        }
+
+        return (
+            <>
+                <CommonActionConfigForm
+                    initialValues={ initialValues }
+                    isCreateFormState={ isCreateFormState }
+                    isReadOnly={ isReadOnly }
+                    onAuthenticationTypeChange={ (updatedValue: AuthenticationType, change: boolean) => {
+                        setAuthenticationType(updatedValue);
+                        setIsAuthenticationUpdateFormState(change);
+                    } } />
+                <Divider className="divider-container" />
+                <Typography variant="h6" className="heading-container" >
+                    { t("actions:attributes.heading") }
+                </Typography>
+                <AttributeSearchList
+                    data-componentid={ "selectedTemplate?.templateId " }
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: ashanthamara
body: We need to pass initialvalues and also get the selected attributes back and isAttributesLoading state to this component as well
created_at: 2025-03-12T04:38:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-testid={ `${componentId}-selected-attribute-initial-letter` }
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:attributes.hint") }</Hint>
+            <Autocomplete
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: This should have a way to disable the field for a readOnly user
created_at: 2025-03-12T05:00:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: This action is also should be disabled for a readOnly user
created_at: 2025-03-12T05:04:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: Ack noted
created_at: 2025-03-12T20:49:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleExecuteCollectionWithoutIdInterface, RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    ActionInterface,
+    ActionUpdateInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType
+} from "../models/actions";
+import "./pre-update-password-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+import AttributeSearchList from "./attributesSection/attribute-search-list";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: ActionConfigFormPropertyInterface;
+    /**
+     * Flag for loading state.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Action Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: _componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * The following useEffect is used to set the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const customError: Partial<ActionConfigFormPropertyInterface> = {};
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: We will be updating this along with API integrations.
created_at: 2025-03-13T07:36:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleExecuteCollectionWithoutIdInterface, RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    ActionInterface,
+    ActionUpdateInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType
+} from "../models/actions";
+import "./pre-update-password-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+import AttributeSearchList from "./attributesSection/attribute-search-list";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: ActionConfigFormPropertyInterface;
+    /**
+     * Flag for loading state.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Action Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: _componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * The following useEffect is used to set the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const customError: Partial<ActionConfigFormPropertyInterface> = {};
+
+        // Call the utility validate function
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError, ...customError };
+
+    };
+
+    const handleSubmit = (
+        values: ActionConfigFormPropertyInterface,
+        changedFields: ActionConfigFormPropertyInterface) => {
+
+        let rulePayload: RuleWithoutIdInterface | RuleExecuteCollectionWithoutIdInterface | Record<string, never>;
+
+        if (isHasRule) {
+            rulePayload = rule;
+        } else if (!isCreateFormState && !rule) {
+            rulePayload = {};
+        }
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: ActionInterface = {
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name,
+                rule: rulePayload ?? undefined
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            // Updating the action
+            const updatingValues: ActionUpdateInterface = {
+                endpoint: isAuthenticationUpdateFormState || changedFields?.endpointUri ? {
+                    authentication: isAuthenticationUpdateFormState ? {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    } : undefined,
+                    uri: changedFields?.endpointUri ? values.endpointUri : undefined
+                } : undefined,
+                name: changedFields?.name ? values.name : undefined,
+                rule: rulePayload ?? undefined
+            };
+
+            setIsSubmitting(true);
+            updateAction(actionTypeApiPath, initialValues.id, updatingValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.UPDATE);
+                    setIsAuthenticationUpdateFormState(false);
+                    mutateAction();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.UPDATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        }
+    };
+
+    const renderFormFields = (): ReactElement => {
+
+        if (isLoading) {
+            return renderLoadingPlaceholders();
+        }
+
+        return (
+            <>
+                <CommonActionConfigForm
+                    initialValues={ initialValues }
+                    isCreateFormState={ isCreateFormState }
+                    isReadOnly={ isReadOnly }
+                    onAuthenticationTypeChange={ (updatedValue: AuthenticationType, change: boolean) => {
+                        setAuthenticationType(updatedValue);
+                        setIsAuthenticationUpdateFormState(change);
+                    } } />
+                <Divider className="divider-container" />
+                <Typography variant="h6" className="heading-container" >
+                    { t("actions:attributes.heading") }
+                </Typography>
+                <AttributeSearchList
+                    data-componentid={ "selectedTemplate?.templateId " }
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: Ack will onboard that with API intergrations.
created_at: 2025-03-13T07:37:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:45:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-testid={ `${componentId}-selected-attribute-initial-letter` }
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:attributes.hint") }</Hint>
+            <Autocomplete
+                disablePortal
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                renderOption={ (props, option: Claim) => (
+                    <li { ...props }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:attributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                key="autocompleteSearchWithList"
+                data-testid={ `${componentId}-select-attributes` }
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden />
+            {
+                selectedAttributesList?.length > 0 && (
+                    <DataTable<Claim[]>
+                        className="external-dialects-list"
+                        actions={ resolveTableActions() }
+                        columns={ resolveTableColumns() }
+                        data={ selectedAttributesList }
+                        onRowClick={ () => null }
+                        showHeader={ false }
+                        data-testid={ `${componentId}-selected-attributes-list` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:45:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -19,6 +19,13 @@
 import { actionsNS } from "../../../models";
 
 export const actions: actionsNS = {
+    attributes: {
path: modules/i18n/src/translations/en-US/portals/actions.ts
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:45:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:45:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-testid={ `${componentId}-selected-attribute-initial-letter` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:47:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-testid={ `${componentId}-selected-attribute-initial-letter-image` }
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-testid={ `${componentId}-selected-attribute-initial-letter` }
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:attributes.hint") }</Hint>
+            <Autocomplete
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:47:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("claims:local.notifications.getClaims.genericError.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("claims:local.notifications.getClaims.genericError.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 692ffe95a0b28e0abda41248c1ee4de0d4b58eed
created_at: 2025-03-13T16:47:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: elected or selected ?
created_at: 2025-03-13T16:57:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: same as above
created_at: 2025-03-13T16:57:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+            {
+                selectedAttributesList?.length > 0 && (
+
+                    <div className="attribute-search-list">
+                        <div className="clear-all-button-container">
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: Can't we set the className inside the Button component ?
created_at: 2025-03-13T17:03:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+            {
+                selectedAttributesList?.length > 0 && (
+
+                    <div className="attribute-search-list">
+                        <div className="clear-all-button-container">
+                            <Button
+                                onClick={ () => setSelectedAttributesList([]) }
+                                variant="outlined"
+                                size="small"
+                                className={ "secondary-button clear-all-button" }
+                                data-componentid={ `${ componentId }-clear-all-button` }
+                                disabled={ false }
+                            >
+                                { t("actions:fields.userAttributes.search.clearButton") }
+                            </Button>
+                        </div>
+                        <div className="selected-attributes-list">
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: ashanthamara
body: Same as above
created_at: 2025-03-13T17:03:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -184,7 +184,15 @@ export interface actionsNS {
                 }
             };
             label: string;
-        }
+        };
+        userAttributes: {
+            heading: string;
+            hint: string;
+            search: {
+                placeholder: string
+                clearButton: string
+            }
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: ashanthamara
body: ```suggestion
            };
```
created_at: 2025-03-13T17:13:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,6 +291,12 @@ export interface actionsNS {
                     message: string;
                 };
             };
+            userAttributes: {
+                getAttributes: {
+                    description: string
+                    message: string
+                }
+            }
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: ashanthamara
body: ```suggestion
                };
            };
```
created_at: 2025-03-13T17:13:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+            {
+                selectedAttributesList?.length > 0 && (
+
+                    <div className="attribute-search-list">
+                        <div className="clear-all-button-container">
+                            <Button
+                                onClick={ () => setSelectedAttributesList([]) }
+                                variant="outlined"
+                                size="small"
+                                className={ "secondary-button clear-all-button" }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: pavinduLakshan
body: ```suggestion
                                className="secondary-button clear-all-button"
```
created_at: 2025-03-15T03:39:37Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,356 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: pavinduLakshan
body: Let's import from oxygen ui
created_at: 2025-03-15T03:40:07Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleExecuteCollectionWithoutIdInterface, RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    ActionInterface,
+    ActionUpdateInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType
+} from "../models/actions";
+import "./pre-update-password-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+import AttributeSearchList from "./attributesSection/attribute-search-list";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: ActionConfigFormPropertyInterface;
+    /**
+     * Flag for loading state.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Action Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: _componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * The following useEffect is used to set the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const customError: Partial<ActionConfigFormPropertyInterface> = {};
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: This is update with 57031ff56eca5b14ac6dfe987d6ebed5591dfdb1
created_at: 2025-03-15T09:17:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,343 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleExecuteCollectionWithoutIdInterface, RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    ActionInterface,
+    ActionUpdateInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType
+} from "../models/actions";
+import "./pre-update-password-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+import AttributeSearchList from "./attributesSection/attribute-search-list";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: ActionConfigFormPropertyInterface;
+    /**
+     * Flag for loading state.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Action Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: _componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * The following useEffect is used to set the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const customError: Partial<ActionConfigFormPropertyInterface> = {};
+
+        // Call the utility validate function
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError, ...customError };
+
+    };
+
+    const handleSubmit = (
+        values: ActionConfigFormPropertyInterface,
+        changedFields: ActionConfigFormPropertyInterface) => {
+
+        let rulePayload: RuleWithoutIdInterface | RuleExecuteCollectionWithoutIdInterface | Record<string, never>;
+
+        if (isHasRule) {
+            rulePayload = rule;
+        } else if (!isCreateFormState && !rule) {
+            rulePayload = {};
+        }
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: ActionInterface = {
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name,
+                rule: rulePayload ?? undefined
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            // Updating the action
+            const updatingValues: ActionUpdateInterface = {
+                endpoint: isAuthenticationUpdateFormState || changedFields?.endpointUri ? {
+                    authentication: isAuthenticationUpdateFormState ? {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    } : undefined,
+                    uri: changedFields?.endpointUri ? values.endpointUri : undefined
+                } : undefined,
+                name: changedFields?.name ? values.name : undefined,
+                rule: rulePayload ?? undefined
+            };
+
+            setIsSubmitting(true);
+            updateAction(actionTypeApiPath, initialValues.id, updatingValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.UPDATE);
+                    setIsAuthenticationUpdateFormState(false);
+                    mutateAction();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.UPDATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        }
+    };
+
+    const renderFormFields = (): ReactElement => {
+
+        if (isLoading) {
+            return renderLoadingPlaceholders();
+        }
+
+        return (
+            <>
+                <CommonActionConfigForm
+                    initialValues={ initialValues }
+                    isCreateFormState={ isCreateFormState }
+                    isReadOnly={ isReadOnly }
+                    onAuthenticationTypeChange={ (updatedValue: AuthenticationType, change: boolean) => {
+                        setAuthenticationType(updatedValue);
+                        setIsAuthenticationUpdateFormState(change);
+                    } } />
+                <Divider className="divider-container" />
+                <Typography variant="h6" className="heading-container" >
+                    { t("actions:attributes.heading") }
+                </Typography>
+                <AttributeSearchList
+                    data-componentid={ "selectedTemplate?.templateId " }
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: This is updated with e7f3972da7a2e98ca53c134f2880ec9f91bec945
created_at: 2025-03-15T09:18:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+            {
+                selectedAttributesList?.length > 0 && (
+
+                    <div className="attribute-search-list">
+                        <div className="clear-all-button-container">
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This class is used in order to properly place the button therefore we'd have to proceed with the above.
created_at: 2025-03-15T09:19:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+            {
+                selectedAttributesList?.length > 0 && (
+
+                    <div className="attribute-search-list">
+                        <div className="clear-all-button-container">
+                            <Button
+                                onClick={ () => setSelectedAttributesList([]) }
+                                variant="outlined"
+                                size="small"
+                                className={ "secondary-button clear-all-button" }
+                                data-componentid={ `${ componentId }-clear-all-button` }
+                                disabled={ false }
+                            >
+                                { t("actions:fields.userAttributes.search.clearButton") }
+                            </Button>
+                        </div>
+                        <div className="selected-attributes-list">
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This class is used in order to properly place the button therefore we'd have to proceed with the above.
created_at: 2025-03-15T09:20:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,285 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, { AutocompleteRenderInputParams } from "@oxygen-ui/react/Autocomplete";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, { FunctionComponent, ReactElement, SyntheticEvent, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    const enableIdentityClaims: boolean = useSelector(
+        (state: AppState) => state?.config?.ui?.enableIdentityClaims);
+
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": !enableIdentityClaims,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: Since the API is related to a separate component this seems to be not necessary.

cc: @NipuniBhagya 
created_at: 2025-03-15T09:26:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is update with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T09:27:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T09:27:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -184,7 +184,15 @@ export interface actionsNS {
                 }
             };
             label: string;
-        }
+        };
+        userAttributes: {
+            heading: string;
+            hint: string;
+            search: {
+                placeholder: string
+                clearButton: string
+            }
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: Shenali-SJ
body: This is updated with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T09:27:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,6 +291,12 @@ export interface actionsNS {
                     message: string;
                 };
             };
+            userAttributes: {
+                getAttributes: {
+                    description: string
+                    message: string
+                }
+            }
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: Shenali-SJ
body: This is updated with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T09:28:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,331 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Button from "@oxygen-ui/react/Button";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./attribute-search-list.scss";
+
+export interface AttributeSearchListPropsInterface extends IdentifiableComponentInterface {
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+}
+
+const AttributeSearchList: FunctionComponent<AttributeSearchListPropsInterface> = ({
+    isReadOnly,
+    "data-componentid": componentId = "autocomplete-search-list"
+}: AttributeSearchListPropsInterface): ReactElement => {
+
+    const [ selectedAttributesList, setSelectedAttributesList ] = useState<Claim[]>([]);
+    const [ allAttributesList, setAllAttributesList ] = useState<Claim[]>();
+    const [ isAttributeListLoading, setIsAttributeListLoading ] = useState<boolean>(false);
+    const [ inputValue, setInputValue ] = useState("");
+
+    const { t } = useTranslation();
+
+    const dispatch: Dispatch = useDispatch();
+
+    /**
+     * Retrieves all the local claims.
+     */
+    useEffect(() => {
+
+        const params: ClaimsGetParams = {
+            "exclude-identity-claims": true,
+            filter: null,
+            limit: null,
+            offset: null,
+            sort: null
+        };
+
+        setIsAttributeListLoading(true);
+
+        getAllLocalClaims(params).then((response: Claim[]) => {
+            const sortedClaims: Claim[] = response?.sort((a: Claim, b: Claim) => {
+                return a.displayName > b.displayName ? 1 : -1;
+            });
+
+            setAllAttributesList(sortedClaims);
+            setIsAttributeListLoading(false);
+        }).catch((error: IdentityAppsApiException) => {
+            dispatch(addAlert(
+                {
+                    description: error?.response?.data?.description
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.description"),
+                    level: AlertLevels.ERROR,
+                    message: error?.response?.data?.message
+                        || t("actions:notifications.genericError.userAttributes.getAttributes.message")
+                }
+            ));
+            setIsAttributeListLoading(false);
+        });
+    }, []);
+
+    /**
+     * Retrieves the initial letter of the provided claim.
+     * @param claim - Claim.
+     * @returns the initial letter of the claim.
+     */
+    const retrieveInitialLetterOfClaim = (claim: Claim): string => {
+
+        const parts: string[] = claim?.claimURI?.split("/");
+
+        return parts[ parts?.length - 1 ];
+    };
+
+    /**
+     * Handle the selection of an attribute from the autocomplete dropdown.
+     * @param data - Dropdown data.
+     */
+    const handleAttributeSelect = (data: DropdownProps) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.some((claim: Claim) => claim?.claimURI === (data as Claim)?.claimURI)
+                ? userAttributes
+                : [ ...userAttributes, data as Claim ]
+        );
+
+        setInputValue(ActionsConstants.EMPTY_STRING);
+    };
+
+    /**
+     * Handle the deletion of an attribute from the selected attributes list.
+     * @param item - Attribute to be deleted.
+     */
+    const handleAttributeDelete = (item: Claim) => {
+
+        setSelectedAttributesList((userAttributes: Claim[]) =>
+            userAttributes?.filter((claim: Claim) => claim?.claimURI !== item?.claimURI)
+        );
+    };
+
+    /**
+     * Resolves the table actions.
+     * Only delete action is supported as the list is static.
+     * @returns - Table actions.
+     */
+    const resolveTableActions = (): TableActionsInterface[] => {
+
+        return [
+            {
+                disabled: isReadOnly,
+                icon: (): SemanticICONS => "trash alternate",
+                onClick: (e: SyntheticEvent, claim: Claim): void =>
+                    handleAttributeDelete(claim),
+                popupText: (): string => t("common:delete"),
+                renderer: "semantic-icon"
+            }
+        ];
+    };
+
+    /**
+     * Resolves the table columns to be displayed in the selected attributes list.
+     * @returns - Table columns.
+     */
+    const resolveTableColumns = (): TableColumnInterface[] => {
+
+        return [
+            {
+                allowToggleVisibility: false,
+                dataIndex: "displayName",
+                id: "displayName",
+                key: "displayName",
+                render: (claim: Claim) => {
+
+                    return (
+                        <Header as="h6" image>
+                            <AppAvatar
+                                image={ (
+                                    <AnimatedAvatar
+                                        name={ retrieveInitialLetterOfClaim(claim) }
+                                        size="mini"
+                                        data-componentid={ `${componentId}-elected-attribute-initial-letter-image` }
+                                    />
+                                ) }
+                                size="mini"
+                                spaced="right"
+                                data-componentid={ `${componentId}-elected-attribute-initial-letter` }
+                            />
+                            <Header.Content>
+                                { claim?.displayName }
+                                <Header.Subheader>
+                                    <code className="inline-code compact transparent">{ claim?.claimURI }</code>
+                                </Header.Subheader>
+                            </Header.Content>
+                        </Header>
+                    );
+                },
+                title: ActionsConstants.EMPTY_STRING
+            },
+            {
+                allowToggleVisibility: false,
+                dataIndex: "action",
+                id: "actions",
+                key: "actions",
+                textAlign: "right",
+                title: ActionsConstants.EMPTY_STRING
+            }
+        ];
+    };
+
+    return (
+        <>
+            <Hint>{ t("actions:fields.userAttributes.hint") }</Hint>
+            <Autocomplete
+                fullWidth
+                aria-label="Attribute selection"
+                className="pt-2"
+                defaultValue={ null }
+                componentsProps={ {
+                    paper: {
+                        elevation: 2
+                    },
+                    popper: {
+                        modifiers: [
+                            {
+                                enabled: false,
+                                name: "flip"
+                            },
+                            {
+                                enabled: false,
+                                name: "preventOverflow"
+                            }
+                        ]
+                    }
+                } }
+                inputValue={ inputValue }
+                value={ null }
+                onInputChange={ (event: React.SyntheticEvent, newInputValue: string,
+                    reason: AutocompleteInputChangeReason) => {
+
+                    if (reason === "reset") {
+                        setInputValue(null);
+
+                        return;
+                    } else {
+                        setInputValue(newInputValue);
+                    }
+                } }
+                onChange={ (
+                    event: SyntheticEvent<HTMLElement>,
+                    data: DropdownProps
+                ) => handleAttributeSelect(data) }
+                options={ allAttributesList }
+                getOptionLabel={ (claim: DropdownProps) =>
+                    claim?.displayName
+                }
+                isOptionEqualToValue={
+                    (option: Claim, value: Claim) =>
+                        option.id === value.id
+                }
+                renderOption={ (props: HTMLAttributes<HTMLLIElement>, option: Claim) => (
+                    <li { ...props } key={ option.id }>
+                        <div className="multiline">
+                            <div>{ option?.displayName }</div>
+                            <div>
+                                <Code className="description" compact withBackground={ false }>
+                                    { option?.claimURI }
+                                </Code>
+                            </div>
+                        </div>
+                    </li>
+                ) }
+                renderInput={ (params: AutocompleteRenderInputParams) => (
+                    <TextField
+                        { ...params }
+                        placeholder={ t("actions:fields.userAttributes.search.placeholder") }
+                        size="small"
+                        variant="outlined"
+                    />
+                ) }
+                disabled={ isReadOnly }
+                key="autocompleteSearchWithList"
+                data-componentid={ `${componentId}-select-attributes` }
+            />
+            <Divider hidden/>
+            {
+                selectedAttributesList?.length > 0 && (
+
+                    <div className="attribute-search-list">
+                        <div className="clear-all-button-container">
+                            <Button
+                                onClick={ () => setSelectedAttributesList([]) }
+                                variant="outlined"
+                                size="small"
+                                className={ "secondary-button clear-all-button" }
path: features/admin.actions.v1/components/attributesSection/attribute-search-list.tsx
user: login: Shenali-SJ
body: This is updated with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T09:29:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,356 @@
+/**
+ * Copyright (c) 2025, 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 { Typography } from "@mui/material";
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: This is updated with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T09:29:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -362,8 +376,7 @@ export const actions: actionsNS = {
         },
         preUpdateProfile: {
             description: {
-                expanded: "This action is executed before updating the profile of a user. " +
-                "Refer the documentation for the API definition to implement.",
+                expanded: "This action is executed before updating the profile of a user.",
                 shortened: "This action is executed before updating the profile of a user."
path: modules/i18n/src/translations/en-US/portals/actions.ts
user: login: pavinduLakshan
body: Is keeping both same intentional?
created_at: 2025-03-15T09:42:23Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2025, 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 from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import Typography from "@oxygen-ui/react/Typography";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { Claim, IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import UserAttributeList from "./userAttributes/user-attribute-list";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType,
+    PreUpdatePasswordActionConfigFormPropertyInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionInterface,
+    PreUpdateProfileActionUpdateInterface
+} from "../models/actions";
+import "./pre-update-profile-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: PreUpdateProfileActionConfigFormPropertyInterface;
+    /**
+     * Specifies whether the data is still loading.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ userAttributesList, setUserAttributesList ] = useState<Claim[]>([]);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * This sets the the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    /**
+     * Renders the loading placeholders.
+     */
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    /**
+     * Callback function to be triggered when the user attribute list is changed in the child component.
+     * This updates the parent's state.
+     * @param attributes - attributes list.
+     */
+    const handleUserAttributeChange = (attributes: Claim[]) => {
+
+        setUserAttributesList([ ...attributes ]);
+    };
+
+    /**
+     * Validates the pre update profile config form.
+     * @param values - Form values.
+     * @returns form errors.
+     */
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError };
+    };
+
+    /**
+     * Handles the pre update profile form submit.
+     */
+    const handleSubmit = (
+        values: PreUpdatePasswordActionConfigFormPropertyInterface,
+        changedFields: PreUpdatePasswordActionConfigFormPropertyInterface) => {
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: PreUpdateProfileActionInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            const updatingValues: PreUpdateProfileActionUpdateInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: isAuthenticationUpdateFormState || changedFields?.endpointUri ? {
+                    authentication: isAuthenticationUpdateFormState ? {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    } : undefined,
+                    uri: changedFields?.endpointUri ? values.endpointUri : undefined
+                } : undefined,
+                name: changedFields?.name ? values.name : undefined
+            };
+
+            setIsSubmitting(true);
+            updateAction(actionTypeApiPath, initialValues.id, updatingValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.UPDATE);
+                    setIsAuthenticationUpdateFormState(false);
+                    mutateAction();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.UPDATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        }
+    };
+
+    /**
+     * Renders the fields of the pre update profile form.
+     * @returns form fields.
+     */
+    const renderFormFields = (): ReactElement => {
+
+        if (isLoading) {
+            return renderLoadingPlaceholders();
+        }
+
+        return (
+            <>
+                <CommonActionConfigForm
+                    initialValues={ initialValues }
+                    isCreateFormState={ isCreateFormState }
+                    isReadOnly={ isReadOnly }
+                    onAuthenticationTypeChange={ (updatedValue: AuthenticationType, change: boolean) => {
+                        setAuthenticationType(updatedValue);
+                        setIsAuthenticationUpdateFormState(change);
+                    } } />
+                <Divider className="divider-container" />
+                <Typography variant="h6" className="heading-container" >
+                    { t("actions:fields.userAttributes.heading") }
+                </Typography>
+                <UserAttributeList
+                    initialValues={ initialValues?.attributes }
+                    onAttributesChange={ handleUserAttributeChange }
+                    isReadOnly={ isReadOnly }
+                    data-componentid={ "selectedTemplate?.templateId " }
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: ashanthamara
body: Is this the expected component id ?
created_at: 2025-03-15T10:10:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2025, 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 from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import Typography from "@oxygen-ui/react/Typography";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { Claim, IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import UserAttributeList from "./userAttributes/user-attribute-list";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType,
+    PreUpdatePasswordActionConfigFormPropertyInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionInterface,
+    PreUpdateProfileActionUpdateInterface
+} from "../models/actions";
+import "./pre-update-profile-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: PreUpdateProfileActionConfigFormPropertyInterface;
+    /**
+     * Specifies whether the data is still loading.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ userAttributesList, setUserAttributesList ] = useState<Claim[]>([]);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * This sets the the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    /**
+     * Renders the loading placeholders.
+     */
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    /**
+     * Callback function to be triggered when the user attribute list is changed in the child component.
+     * This updates the parent's state.
+     * @param attributes - attributes list.
+     */
+    const handleUserAttributeChange = (attributes: Claim[]) => {
+
+        setUserAttributesList([ ...attributes ]);
+    };
+
+    /**
+     * Validates the pre update profile config form.
+     * @param values - Form values.
+     * @returns form errors.
+     */
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError };
+    };
+
+    /**
+     * Handles the pre update profile form submit.
+     */
+    const handleSubmit = (
+        values: PreUpdatePasswordActionConfigFormPropertyInterface,
+        changedFields: PreUpdatePasswordActionConfigFormPropertyInterface) => {
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: PreUpdateProfileActionInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            const updatingValues: PreUpdateProfileActionUpdateInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: isAuthenticationUpdateFormState || changedFields?.endpointUri ? {
+                    authentication: isAuthenticationUpdateFormState ? {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    } : undefined,
+                    uri: changedFields?.endpointUri ? values.endpointUri : undefined
+                } : undefined,
+                name: changedFields?.name ? values.name : undefined
+            };
+
+            setIsSubmitting(true);
+            updateAction(actionTypeApiPath, initialValues.id, updatingValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.UPDATE);
+                    setIsAuthenticationUpdateFormState(false);
+                    mutateAction();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.UPDATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        }
+    };
+
+    /**
+     * Renders the fields of the pre update profile form.
+     * @returns form fields.
+     */
+    const renderFormFields = (): ReactElement => {
+
+        if (isLoading) {
+            return renderLoadingPlaceholders();
+        }
+
+        return (
+            <>
+                <CommonActionConfigForm
+                    initialValues={ initialValues }
+                    isCreateFormState={ isCreateFormState }
+                    isReadOnly={ isReadOnly }
+                    onAuthenticationTypeChange={ (updatedValue: AuthenticationType, change: boolean) => {
+                        setAuthenticationType(updatedValue);
+                        setIsAuthenticationUpdateFormState(change);
+                    } } />
+                <Divider className="divider-container" />
+                <Typography variant="h6" className="heading-container" >
+                    { t("actions:fields.userAttributes.heading") }
+                </Typography>
+                <UserAttributeList
+                    initialValues={ initialValues?.attributes }
+                    onAttributesChange={ handleUserAttributeChange }
+                    isReadOnly={ isReadOnly }
+                    data-componentid={ "selectedTemplate?.templateId " }
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: This is fixed with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T15:01:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -362,8 +376,7 @@ export const actions: actionsNS = {
         },
         preUpdateProfile: {
             description: {
-                expanded: "This action is executed before updating the profile of a user. " +
-                "Refer the documentation for the API definition to implement.",
+                expanded: "This action is executed before updating the profile of a user.",
                 shortened: "This action is executed before updating the profile of a user."
path: modules/i18n/src/translations/en-US/portals/actions.ts
user: login: Shenali-SJ
body: This is fixed with 5c6987fafbb1162df51233427cd5cda8fa1d7216
created_at: 2025-03-15T15:01:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -184,7 +184,15 @@ export interface actionsNS {
                 }
             };
             label: string;
-        }
+        };
+        userAttributes: {
+            heading: string;
+            hint: string;
+            search: {
+                placeholder: string
+                clearButton: string
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: ashanthamara
body: ```suggestion
                placeholder: string;
                clearButton: string;
```
created_at: 2025-03-16T08:27:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,6 +291,12 @@ export interface actionsNS {
                     message: string;
                 };
             };
+            userAttributes: {
+                getAttributes: {
+                    description: string
+                    message: string
+                }
+            }
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: ashanthamara
body: ```suggestion
            userAttributes: {
                getAttributes: {
                    description: string;
                    message: string;
                };
            };
```
created_at: 2025-03-16T08:28:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,399 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./user-attribute-list.scss";
+
+export interface UserAttributeListPropsInterface extends IdentifiableComponentInterface {
path: features/admin.actions.v1/components/userAttributes/user-attribute-list.tsx
user: login: ashanthamara
body: Lets rename `userAttributes` folder to `user-attributes`
created_at: 2025-03-16T08:30:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2025, 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 from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import Typography from "@oxygen-ui/react/Typography";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { Claim, IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import UserAttributeList from "./user-attributes/user-attribute-list";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType,
+    PreUpdatePasswordActionConfigFormPropertyInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionInterface,
+    PreUpdateProfileActionUpdateInterface
+} from "../models/actions";
+import "./pre-update-profile-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: PreUpdateProfileActionConfigFormPropertyInterface;
+    /**
+     * Specifies whether the data is still loading.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ userAttributesList, setUserAttributesList ] = useState<Claim[]>([]);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * This sets the the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    /**
+     * Renders the loading placeholders.
+     */
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    /**
+     * Callback function to be triggered when the user attribute list is changed in the child component.
+     * This updates the parent's state.
+     * @param attributes - attributes list.
+     */
+    const handleUserAttributeChange = (attributes: Claim[]) => {
+
+        setUserAttributesList([ ...attributes ]);
+    };
+
+    /**
+     * Validates the pre update profile config form.
+     * @param values - Form values.
+     * @returns form errors.
+     */
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError };
+    };
+
+    /**
+     * Handles the pre update profile form submit.
+     */
+    const handleSubmit = (
+        values: PreUpdatePasswordActionConfigFormPropertyInterface,
+        changedFields: PreUpdatePasswordActionConfigFormPropertyInterface) => {
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: PreUpdateProfileActionInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            const updatingValues: PreUpdateProfileActionUpdateInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: ashanthamara
body: Seems like we are sending attributes list in every update call.
Can we have a logic to send it only when it is updated ?
created_at: 2025-03-16T08:54:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,399 @@
+/**
+ * Copyright (c) 2025, 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 Autocomplete, {
+    AutocompleteInputChangeReason,
+    AutocompleteRenderInputParams
+} from "@oxygen-ui/react/Autocomplete";
+import Box from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import TextField from "@oxygen-ui/react/TextField";
+import { getAllLocalClaims } from "@wso2is/admin.claims.v1/api";
+import { IdentityAppsApiException } from "@wso2is/core/exceptions";
+import {
+    AlertLevels,
+    Claim,
+    ClaimsGetParams,
+    IdentifiableComponentInterface
+} from "@wso2is/core/models";
+import { addAlert } from "@wso2is/core/store";
+import {
+    AnimatedAvatar,
+    AppAvatar,
+    Code,
+    DataTable,
+    Hint,
+    TableActionsInterface,
+    TableColumnInterface
+} from "@wso2is/react-components";
+import React, {
+    FunctionComponent,
+    HTMLAttributes,
+    ReactElement,
+    SyntheticEvent,
+    useEffect,
+    useState
+} from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch } from "react-redux";
+import { Dispatch } from "redux";
+import { Divider, DropdownProps, Header, SemanticICONS } from "semantic-ui-react";
+import { ActionsConstants } from "../../constants/actions-constants";
+import "./user-attribute-list.scss";
+
+export interface UserAttributeListPropsInterface extends IdentifiableComponentInterface {
path: features/admin.actions.v1/components/userAttributes/user-attribute-list.tsx
user: login: Shenali-SJ
body: This is updated with 7dbbe214275c37a72c4fb09f0a2501a34191e2fb
created_at: 2025-03-16T08:54:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -283,6 +291,12 @@ export interface actionsNS {
                     message: string;
                 };
             };
+            userAttributes: {
+                getAttributes: {
+                    description: string
+                    message: string
+                }
+            }
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: Shenali-SJ
body: This is updated with 7dbbe214275c37a72c4fb09f0a2501a34191e2fb
created_at: 2025-03-16T08:54:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -184,7 +184,15 @@ export interface actionsNS {
                 }
             };
             label: string;
-        }
+        };
+        userAttributes: {
+            heading: string;
+            hint: string;
+            search: {
+                placeholder: string
+                clearButton: string
path: modules/i18n/src/models/namespaces/actions-ns.ts
user: login: Shenali-SJ
body: This is updated with 7dbbe214275c37a72c4fb09f0a2501a34191e2fb
created_at: 2025-03-16T08:54:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2025, 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 from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import Typography from "@oxygen-ui/react/Typography";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { Claim, IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import UserAttributeList from "./user-attributes/user-attribute-list";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType,
+    PreUpdatePasswordActionConfigFormPropertyInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionInterface,
+    PreUpdateProfileActionUpdateInterface
+} from "../models/actions";
+import "./pre-update-profile-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: PreUpdateProfileActionConfigFormPropertyInterface;
+    /**
+     * Specifies whether the data is still loading.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ userAttributesList, setUserAttributesList ] = useState<Claim[]>([]);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * This sets the the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    /**
+     * Renders the loading placeholders.
+     */
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    /**
+     * Callback function to be triggered when the user attribute list is changed in the child component.
+     * This updates the parent's state.
+     * @param attributes - attributes list.
+     */
+    const handleUserAttributeChange = (attributes: Claim[]) => {
+
+        setUserAttributesList([ ...attributes ]);
+    };
+
+    /**
+     * Validates the pre update profile config form.
+     * @param values - Form values.
+     * @returns form errors.
+     */
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError };
+    };
+
+    /**
+     * Handles the pre update profile form submit.
+     */
+    const handleSubmit = (
+        values: PreUpdatePasswordActionConfigFormPropertyInterface,
+        changedFields: PreUpdatePasswordActionConfigFormPropertyInterface) => {
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: PreUpdateProfileActionInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            const updatingValues: PreUpdateProfileActionUpdateInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: ashanthamara
body: Lets address this in a follow up PR
created_at: 2025-03-16T10:12:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2025, 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 from "@oxygen-ui/react/Box";
+import Button from "@oxygen-ui/react/Button";
+import Divider from "@oxygen-ui/react/Divider";
+import Skeleton from "@oxygen-ui/react/Skeleton";
+import Typography from "@oxygen-ui/react/Typography";
+import { FeatureAccessConfigInterface } from "@wso2is/access-control";
+import { AppState } from "@wso2is/admin.core.v1/store";
+import useGetRulesMeta from "@wso2is/admin.rules.v1/api/use-get-rules-meta";
+import { RuleWithoutIdInterface } from "@wso2is/admin.rules.v1/models/rules";
+import { RulesProvider } from "@wso2is/admin.rules.v1/providers/rules-provider";
+import { isFeatureEnabled } from "@wso2is/core/helpers";
+import { Claim, IdentifiableComponentInterface } from "@wso2is/core/models";
+import {
+    FinalForm,
+    FormRenderProps } from "@wso2is/form";
+import { EmphasizedSegment } from "@wso2is/react-components";
+import { AxiosError } from "axios";
+import React, { FunctionComponent, ReactElement, useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import CommonActionConfigForm from "./common-action-config-form";
+import RuleConfigForm from "./rule-config-form";
+import UserAttributeList from "./user-attributes/user-attribute-list";
+import createAction from "../api/create-action";
+import updateAction from "../api/update-action";
+import useGetActionById from "../api/use-get-action-by-id";
+import useGetActionsByType from "../api/use-get-actions-by-type";
+import { ActionsConstants } from "../constants/actions-constants";
+import {
+    ActionConfigFormPropertyInterface,
+    AuthenticationPropertiesInterface,
+    AuthenticationType,
+    PreUpdatePasswordActionConfigFormPropertyInterface,
+    PreUpdateProfileActionConfigFormPropertyInterface,
+    PreUpdateProfileActionInterface,
+    PreUpdateProfileActionUpdateInterface
+} from "../models/actions";
+import "./pre-update-profile-action-config-form.scss";
+import { useHandleError, useHandleSuccess } from "../util/alert-util";
+import { validateActionCommonFields } from "../util/form-field-util";
+
+/**
+ * Prop types for the action configuration form component.
+ */
+interface PreUpdateProfileActionConfigFormInterface extends IdentifiableComponentInterface {
+    /**
+     * Action's initial values.
+     */
+    initialValues: PreUpdateProfileActionConfigFormPropertyInterface;
+    /**
+     * Specifies whether the data is still loading.
+     */
+    isLoading?: boolean;
+    /**
+     * Specifies whether the form is read-only.
+     */
+    isReadOnly: boolean;
+    /**
+     * Type of the Action.
+     */
+    actionTypeApiPath: string;
+    /**
+     * Specifies action creation state.
+     */
+    isCreateFormState: boolean;
+}
+
+const PreUpdateProfileActionConfigForm: FunctionComponent<PreUpdateProfileActionConfigFormInterface> = ({
+    initialValues,
+    isLoading,
+    isReadOnly,
+    actionTypeApiPath,
+    isCreateFormState,
+    ["data-componentid"]: componentId = "pre-update-password-action-config-form"
+}: PreUpdateProfileActionConfigFormInterface): ReactElement => {
+
+    const actionsFeatureConfig: FeatureAccessConfigInterface = useSelector(
+        (state: AppState) => state.config.ui.features.actions);
+    const [ isAuthenticationUpdateFormState, setIsAuthenticationUpdateFormState ] = useState<boolean>(false);
+    const [ userAttributesList, setUserAttributesList ] = useState<Claim[]>([]);
+    const [ authenticationType, setAuthenticationType ] = useState<AuthenticationType>(null);
+    const [ isSubmitting, setIsSubmitting ] = useState<boolean>(false);
+    const [ isHasRule, setIsHasRule ] = useState<boolean>(false);
+    const [ rule, setRule ] = useState<RuleWithoutIdInterface>(null);
+
+    const { t } = useTranslation();
+
+    const handleSuccess: (operation: string) => void = useHandleSuccess();
+    const handleError: (error: AxiosError, operation: string) => void = useHandleError();
+
+    const {
+        mutate: mutateActions
+    } = useGetActionsByType(actionTypeApiPath);
+
+    const {
+        mutate: mutateAction
+    } = useGetActionById(actionTypeApiPath, initialValues?.id);
+
+    const {
+        data: RuleExpressionsMetaData
+    } = useGetRulesMeta(actionTypeApiPath);
+
+    const showRuleComponent: boolean = isFeatureEnabled(
+        actionsFeatureConfig, ActionsConstants.FEATURE_DICTIONARY.get("PRE_UPDATE_PROFILE_RULE"));
+
+    /**
+     * This sets the the current Action Authentication Type.
+     */
+    useEffect(() => {
+        if (!initialValues?.id) {
+            setIsAuthenticationUpdateFormState(true);
+        } else {
+            setAuthenticationType(initialValues.authenticationType as AuthenticationType);
+            setIsAuthenticationUpdateFormState(false);
+        }
+
+        if (initialValues?.rule) {
+            setIsHasRule(true);
+        }
+    }, [ initialValues ]);
+
+    /**
+     * Renders the loading placeholders.
+     */
+    const renderLoadingPlaceholders = (): ReactElement => (
+        <Box className="placeholder-box">
+            <Skeleton variant="rectangular" height={ 7 } width="30%" />
+            <Skeleton variant="rectangular" height={ 28 } />
+            <Skeleton variant="rectangular" height={ 7 } width="90%" />
+            <Skeleton variant="rectangular" height={ 7 } />
+        </Box>
+    );
+
+    /**
+     * Callback function to be triggered when the user attribute list is changed in the child component.
+     * This updates the parent's state.
+     * @param attributes - attributes list.
+     */
+    const handleUserAttributeChange = (attributes: Claim[]) => {
+
+        setUserAttributesList([ ...attributes ]);
+    };
+
+    /**
+     * Validates the pre update profile config form.
+     * @param values - Form values.
+     * @returns form errors.
+     */
+    const validateForm = (values: ActionConfigFormPropertyInterface):
+        Partial<ActionConfigFormPropertyInterface> => {
+
+        const commonFieldError: Partial<ActionConfigFormPropertyInterface> = validateActionCommonFields(values, {
+            authenticationType: authenticationType,
+            isAuthenticationUpdateFormState: isAuthenticationUpdateFormState,
+            isCreateFormState: isCreateFormState
+        });
+
+        return { ...commonFieldError };
+    };
+
+    /**
+     * Handles the pre update profile form submit.
+     */
+    const handleSubmit = (
+        values: PreUpdatePasswordActionConfigFormPropertyInterface,
+        changedFields: PreUpdatePasswordActionConfigFormPropertyInterface) => {
+
+        const authProperties: Partial<AuthenticationPropertiesInterface> = {};
+
+        if (isAuthenticationUpdateFormState || isCreateFormState) {
+            switch (values.authenticationType) {
+                case AuthenticationType.BASIC:
+                    authProperties.username = values.usernameAuthProperty;
+                    authProperties.password = values.passwordAuthProperty;
+
+                    break;
+                case AuthenticationType.BEARER:
+                    authProperties.accessToken = values.accessTokenAuthProperty;
+
+                    break;
+                case AuthenticationType.API_KEY:
+                    authProperties.header = values.headerAuthProperty;
+                    authProperties.value = values.valueAuthProperty;
+
+                    break;
+                case AuthenticationType.NONE:
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        if (isCreateFormState) {
+            const actionValues: PreUpdateProfileActionInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
+                endpoint: {
+                    authentication: {
+                        properties: authProperties,
+                        type: values.authenticationType as AuthenticationType
+                    },
+                    uri: values.endpointUri
+                },
+                name: values.name
+            };
+
+            setIsSubmitting(true);
+            createAction(actionTypeApiPath, actionValues)
+                .then(() => {
+                    handleSuccess(ActionsConstants.CREATE);
+                    mutateActions();
+                })
+                .catch((error: AxiosError) => {
+                    handleError(error, ActionsConstants.CREATE);
+                })
+                .finally(() => {
+                    setIsSubmitting(false);
+                });
+        } else {
+            const updatingValues: PreUpdateProfileActionUpdateInterface = {
+                attributes: userAttributesList.map((claim: Claim) => claim.claimURI),
path: features/admin.actions.v1/components/pre-update-profile-action-config-form.tsx
user: login: Shenali-SJ
body: Ack will be updating the behavior through a follow-up PR.
created_at: 2025-03-17T04:25:04Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-10T09:59:26Z
body: ## [Codecov](https://app.codecov.io/gh/wso2/identity-apps/pull/7825?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wso2) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 41.85%. Comparing base [(`13f669c`)](https://app.codecov.io/gh/wso2/identity-apps/commit/13f669c16e2c69f06d9d17c50b23f0b694186458?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wso2) to head [(`7dbbe21`)](https://app.codecov.io/gh/wso2/identity-apps/commit/7dbbe214275c37a72c4fb09f0a2501a34191e2fb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wso2).
> Report is 16 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #7825   +/-   ##
=======================================
  Coverage   41.85%   41.85%           
=======================================
  Files          42       42           
  Lines         939      939           
  Branches      238      231    -7     
=======================================
  Hits          393      393           
  Misses        502      502           
  Partials       44       44           
```

| [Flag](https://app.codecov.io/gh/wso2/identity-apps/pull/7825/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wso2) | Coverage Δ | |
|---|---|---|
| [@wso2is/core](https://app.codecov.io/gh/wso2/identity-apps/pull/7825/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wso2) | `41.85% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wso2#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>
<details><summary>🚀 New features to boost your workflow: </summary>

- ❄ [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- 📦 [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: wso2-jenkins-bot
created_at: 2025-03-16T08:48:10Z
body: <h3>🦋 Changeset detected</h3><p><b>The changes in this PR will be included in the next version bump.</b></p><p>Not sure what this means? <a href="https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md">Click here to learn what changesets are</a>.</p>
author_association: CONTRIBUTOR