From 04b8c2d293a28c4ced820f8666aa8c895d08400e Mon Sep 17 00:00:00 2001 From: Ashan Thamara Palihakkara <75057725+ashanthamara@users.noreply.github.com> Date: Sun, 1 Dec 2024 22:26:01 +0530 Subject: [PATCH 1/4] Add getActionByActionId api --- .../api/use-get-action-by-id.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 features/admin.actions.v1/api/use-get-action-by-id.ts diff --git a/features/admin.actions.v1/api/use-get-action-by-id.ts b/features/admin.actions.v1/api/use-get-action-by-id.ts new file mode 100644 index 00000000000..2ea0adf062a --- /dev/null +++ b/features/admin.actions.v1/api/use-get-action-by-id.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import useRequest, { + RequestConfigInterface, + RequestErrorInterface, + RequestResultInterface +} from "@wso2is/admin.core.v1/hooks/use-request"; +import { store } from "@wso2is/admin.core.v1/store"; +import { HttpMethods } from "@wso2is/core/models"; +import { ActionResponseInterface } from "../models/actions"; + +/** + * Hook to get the action configurations by id. + * + * @param actionType - Type of the action. + * @param actionId - ID of the action. + * @returns SWR response object containing the data, error, isLoading, isValidating, mutate. + */ +const useGetActionById = + (actionType: string, actionId: string): RequestResultInterface => { + + const requestConfig: RequestConfigInterface = { + headers: { + Accept: "application/json", + "Content-Type": "application/json" + }, + method: HttpMethods.GET, + url: `${ store.getState().config.endpoints.actions }/${ actionType }/${ actionId }` + }; + + const shouldFetch: boolean = actionId !== undefined && actionId !== null; + const { data, error, isLoading, isValidating, mutate } = useRequest( + shouldFetch ? requestConfig : null, + { shouldRetryOnError: false } + ); + + return { + data, + error, + isLoading, + isValidating, + mutate + }; +}; + +export default useGetActionById; From eb2b27a9d56bec6e126f908339f151cab80e0ad5 Mon Sep 17 00:00:00 2001 From: Ashan Thamara Palihakkara <75057725+ashanthamara@users.noreply.github.com> Date: Sun, 1 Dec 2024 23:09:58 +0530 Subject: [PATCH 2/4] Add getActionById api call in the actions ui --- .changeset/violet-lobsters-smile.md | 6 ++ .../api/use-get-actions-by-type.ts | 6 +- .../components/action-config-form.tsx | 7 +- features/admin.actions.v1/models/actions.ts | 42 ++++++++++- .../pages/action-configuration-page.tsx | 70 +++++++++++++++---- .../i18n/src/models/namespaces/actions-ns.ts | 12 +++- .../src/translations/en-US/portals/actions.ts | 12 +++- 7 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 .changeset/violet-lobsters-smile.md diff --git a/.changeset/violet-lobsters-smile.md b/.changeset/violet-lobsters-smile.md new file mode 100644 index 00000000000..8f94a0eeacb --- /dev/null +++ b/.changeset/violet-lobsters-smile.md @@ -0,0 +1,6 @@ +--- +"@wso2is/admin.actions.v1": minor +"@wso2is/i18n": patch +--- + +Add getActionByActionId api to actions ui diff --git a/features/admin.actions.v1/api/use-get-actions-by-type.ts b/features/admin.actions.v1/api/use-get-actions-by-type.ts index 9f896992657..47e6354c37c 100644 --- a/features/admin.actions.v1/api/use-get-actions-by-type.ts +++ b/features/admin.actions.v1/api/use-get-actions-by-type.ts @@ -23,16 +23,16 @@ import useRequest, { } from "@wso2is/admin.core.v1/hooks/use-request"; import { store } from "@wso2is/admin.core.v1/store"; import { HttpMethods } from "@wso2is/core/models"; -import { ActionResponseInterface } from "../models/actions"; +import { ActionBasicResponseInterface } from "../models/actions"; /** - * Hook to get the action configurations. + * Hook to get the actions configurations by action type. * * @param actionType - Type of the action. * @param shouldFetch - Should fetch the data. * @returns SWR response object containing the data, error, isLoading, isValidating, mutate. */ -const useGetActionsByType = +const useGetActionsByType = (actionType: string, shouldFetch: boolean = true): RequestResultInterface => { const requestConfig: RequestConfigInterface = { diff --git a/features/admin.actions.v1/components/action-config-form.tsx b/features/admin.actions.v1/components/action-config-form.tsx index 1dcdc69afe6..5c77b78872a 100644 --- a/features/admin.actions.v1/components/action-config-form.tsx +++ b/features/admin.actions.v1/components/action-config-form.tsx @@ -46,6 +46,7 @@ import { Dispatch } from "redux"; import { Icon } from "semantic-ui-react"; 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 { @@ -106,6 +107,10 @@ const ActionConfigForm: FunctionComponent = ({ mutate: mutateActions } = useGetActionsByType(actionTypeApiPath); + const { + mutate: mutateAction + } = useGetActionById(actionTypeApiPath, initialValues?.id); + /** * The following useEffect is used to set the current Action Authentication Type. */ @@ -342,7 +347,7 @@ const ActionConfigForm: FunctionComponent = ({ .then(() => { handleSuccess(ActionsConstants.UPDATE); setIsAuthenticationUpdateFormState(false); - mutateActions(); + mutateAction(); }) .catch((error: AxiosError) => { handleError(error, ActionsConstants.UPDATE); diff --git a/features/admin.actions.v1/models/actions.ts b/features/admin.actions.v1/models/actions.ts index f61dd236c4e..b931e439983 100644 --- a/features/admin.actions.v1/models/actions.ts +++ b/features/admin.actions.v1/models/actions.ts @@ -16,6 +16,7 @@ * under the License. */ +import { HttpMethod } from "@asgardeo/auth-react"; import { FeatureStatusLabel } from "@wso2is/admin.feature-gate.v1/models/feature-status"; import { ReactNode } from "react"; @@ -102,6 +103,31 @@ interface AuthenticationInterface { properties: Partial; } +/** + * Link Relation type. + */ +enum Relation { + SELF = "self" +} + +/** + * Link Interface. + */ +interface LinkInterface { + /** + * Url of the endpoint. + */ + href: string; + /** + * Http method. + */ + method: HttpMethod + /** + * Relation to the resource. + */ + rel: Relation; +} + /** * Authentication Properties. */ @@ -129,9 +155,9 @@ export interface AuthenticationPropertiesInterface { } /** - * Action Basic Response. + * Action Base Response. */ -export interface ActionBasicResponseInterface { +export interface ActionBaseResponseInterface { /** * ID of the Action. */ @@ -154,10 +180,20 @@ export interface ActionBasicResponseInterface { status: ActionStatus; } +/** + * Action Basic Response. + */ +export interface ActionBasicResponseInterface extends ActionBaseResponseInterface { + /** + * Links of the Action. + */ + links: LinkInterface[]; +} + /** * Action Response. */ -export interface ActionResponseInterface extends ActionBasicResponseInterface { +export interface ActionResponseInterface extends ActionBaseResponseInterface { /** * Endpoint configuration of the Action. */ diff --git a/features/admin.actions.v1/pages/action-configuration-page.tsx b/features/admin.actions.v1/pages/action-configuration-page.tsx index e50798c4ee3..0dbf38cb87a 100644 --- a/features/admin.actions.v1/pages/action-configuration-page.tsx +++ b/features/admin.actions.v1/pages/action-configuration-page.tsx @@ -44,6 +44,7 @@ import { Dispatch } from "redux"; import { Checkbox, CheckboxProps, Grid } from "semantic-ui-react"; import changeActionStatus from "../api/change-action-status"; import deleteAction from "../api/delete-action"; +import useGetActionById from "../api/use-get-action-by-id"; import useGetActionsByType from "../api/use-get-actions-by-type"; import ActionConfigForm from "../components/action-config-form"; import { ActionsConstants } from "../constants/actions-constants"; @@ -97,20 +98,35 @@ const ActionConfigurationPage: FunctionComponent { + if (actions && actions.length >= 1) { + return actions[0].id; + } else { + return null; + } + }, [ actions ]); + + const { + data: action, + error: actionFetchRequestError, + isLoading: isActionLoading, + mutate: mutateAction + } = useGetActionById(actionTypeApiPath, actionId); + + const isLoading: boolean = isActionsLoading || !actions || !Array.isArray(actions) || isActionLoading; const actionInitialValues: ActionConfigFormPropertyInterface = useMemo(() => { - if (actions) { + if (action) { return { - authenticationType: actions[0]?.endpoint?.authentication?.type.toString(), - endpointUri: actions[0]?.endpoint?.uri, - id: actions[0]?.id, - name: actions[0]?.name + authenticationType: action?.endpoint?.authentication?.type.toString(), + endpointUri: action?.endpoint?.uri, + id: action?.id, + name: action?.name }; } else { return null; } - }, [ actions ]); + }, [ action ]); useEffect(() => { if (actions?.length >= 1) { @@ -122,7 +138,7 @@ const ActionConfigurationPage: FunctionComponent { if (isActionsLoading || !actionsFetchRequestError) { @@ -132,23 +148,51 @@ const ActionConfigurationPage: FunctionComponent({ - description: t("actions:notification.error.fetch.description", + description: t("actions:notification.error.fetchByType.description", { description: actionsFetchRequestError.response.data.description }), level: AlertLevels.ERROR, - message: t("actions:notification.error.fetch.message") + message: t("actions:notification.error.fetchByType.message") }) ); } else { dispatch( addAlert({ - description: t("actions:notification.genericError.fetch.description"), + description: t("actions:notification.genericError.fetchByType.description"), level: AlertLevels.ERROR, - message: t("actions:notification.genericError.fetch.message") + message: t("actions:notification.genericError.fetchByType.message") }) ); } }, [ isActionsLoading, actionsFetchRequestError ]); + /** + * The following useEffect is used to handle if any error occurs while fetching the Action by Id. + */ + useEffect(() => { + if (isActionLoading || !actionFetchRequestError) { + return; + } + + if (actionFetchRequestError.response?.data?.description) { + dispatch( + addAlert({ + description: t("actions:notification.error.fetchById.description", + { description: actionFetchRequestError.response.data.description }), + level: AlertLevels.ERROR, + message: t("actions:notification.error.fetchById.message") + }) + ); + } else { + dispatch( + addAlert({ + description: t("actions:notification.genericError.fetchById.description"), + level: AlertLevels.ERROR, + message: t("actions:notification.genericError.fetchById.message") + }) + ); + } + }, [ isActionLoading, actionFetchRequestError ]); + /** * Handles the back button click event. */ @@ -258,7 +302,7 @@ const ActionConfigurationPage: FunctionComponent { - mutateActions(); + mutateAction(); setIsSubmitting(false); }); }; diff --git a/modules/i18n/src/models/namespaces/actions-ns.ts b/modules/i18n/src/models/namespaces/actions-ns.ts index 60681266652..6dd77156847 100644 --- a/modules/i18n/src/models/namespaces/actions-ns.ts +++ b/modules/i18n/src/models/namespaces/actions-ns.ts @@ -155,7 +155,11 @@ export interface actionsNS { description: string; message: string; }; - fetch: { + fetchById: { + description: string; + message: string; + }; + fetchByType: { description: string; message: string; }; @@ -185,7 +189,11 @@ export interface actionsNS { description: string; message: string; }; - fetch: { + fetchById: { + description: string; + message: string; + }; + fetchByType: { description: string; message: string; }; diff --git a/modules/i18n/src/translations/en-US/portals/actions.ts b/modules/i18n/src/translations/en-US/portals/actions.ts index 1b84736cdbc..9e87c43d163 100644 --- a/modules/i18n/src/translations/en-US/portals/actions.ts +++ b/modules/i18n/src/translations/en-US/portals/actions.ts @@ -162,10 +162,14 @@ export const actions: actionsNS = { description: "{{description}}", message: "Error deleting the action." }, - fetch: { + fetchById: { description: "{{description}}", message: "Error fetching the action." }, + fetchByType: { + description: "{{description}}", + message: "Error fetching actions." + }, typesFetch: { description: "{{description}}", message: "Error fetching the action types." @@ -192,10 +196,14 @@ export const actions: actionsNS = { description: "Couldn't delete the action.", message: "Something went wrong." }, - fetch: { + fetchById: { description: "Couldn't fetch the action.", message: "Something went wrong." }, + fetchByType: { + description: "Couldn't fetch actions.", + message: "Something went wrong." + }, typesFetch: { description: "Couldn't fetch the action types.", message: "Something went wrong." From 1ba4f62f4c5620a326ae4ee9e34ab74d23d98e0b Mon Sep 17 00:00:00 2001 From: Ashan Thamara Palihakkara <75057725+ashanthamara@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:17:46 +0530 Subject: [PATCH 3/4] Address comments --- features/admin.actions.v1/api/use-get-action-by-id.ts | 3 ++- .../admin.actions.v1/pages/action-configuration-page.tsx | 8 +------- modules/i18n/src/translations/en-US/portals/actions.ts | 6 +++--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/features/admin.actions.v1/api/use-get-action-by-id.ts b/features/admin.actions.v1/api/use-get-action-by-id.ts index 2ea0adf062a..e9b525729b2 100644 --- a/features/admin.actions.v1/api/use-get-action-by-id.ts +++ b/features/admin.actions.v1/api/use-get-action-by-id.ts @@ -23,6 +23,7 @@ import useRequest, { } from "@wso2is/admin.core.v1/hooks/use-request"; import { store } from "@wso2is/admin.core.v1/store"; import { HttpMethods } from "@wso2is/core/models"; +import isEmpty from "lodash-es/isEmpty"; import { ActionResponseInterface } from "../models/actions"; /** @@ -44,7 +45,7 @@ const useGetActionById = ( shouldFetch ? requestConfig : null, { shouldRetryOnError: false } diff --git a/features/admin.actions.v1/pages/action-configuration-page.tsx b/features/admin.actions.v1/pages/action-configuration-page.tsx index 0dbf38cb87a..be900c321ff 100644 --- a/features/admin.actions.v1/pages/action-configuration-page.tsx +++ b/features/admin.actions.v1/pages/action-configuration-page.tsx @@ -98,13 +98,7 @@ const ActionConfigurationPage: FunctionComponent { - if (actions && actions.length >= 1) { - return actions[0].id; - } else { - return null; - } - }, [ actions ]); + const actionId: string = useMemo(() => actions?.[0]?.id || null, [ actions ]); const { data: action, diff --git a/modules/i18n/src/translations/en-US/portals/actions.ts b/modules/i18n/src/translations/en-US/portals/actions.ts index 9e87c43d163..0b1d7a13f86 100644 --- a/modules/i18n/src/translations/en-US/portals/actions.ts +++ b/modules/i18n/src/translations/en-US/portals/actions.ts @@ -197,15 +197,15 @@ export const actions: actionsNS = { message: "Something went wrong." }, fetchById: { - description: "Couldn't fetch the action.", + description: "Couldn't retrieve the action.", message: "Something went wrong." }, fetchByType: { - description: "Couldn't fetch actions.", + description: "Couldn't retrieve actions.", message: "Something went wrong." }, typesFetch: { - description: "Couldn't fetch the action types.", + description: "Couldn't retrieve the action types.", message: "Something went wrong." }, update: { From d6e7e3512f0791c828b5e4fa57cd14a5bfaecdd3 Mon Sep 17 00:00:00 2001 From: Ashan Thamara Palihakkara <75057725+ashanthamara@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:12:02 +0530 Subject: [PATCH 4/4] Address comments --- features/admin.actions.v1/api/use-get-action-by-id.ts | 1 + modules/i18n/src/translations/en-US/portals/actions.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/features/admin.actions.v1/api/use-get-action-by-id.ts b/features/admin.actions.v1/api/use-get-action-by-id.ts index e9b525729b2..238697ca2c4 100644 --- a/features/admin.actions.v1/api/use-get-action-by-id.ts +++ b/features/admin.actions.v1/api/use-get-action-by-id.ts @@ -46,6 +46,7 @@ const useGetActionById = ( shouldFetch ? requestConfig : null, { shouldRetryOnError: false } diff --git a/modules/i18n/src/translations/en-US/portals/actions.ts b/modules/i18n/src/translations/en-US/portals/actions.ts index 0b1d7a13f86..f01e41f244b 100644 --- a/modules/i18n/src/translations/en-US/portals/actions.ts +++ b/modules/i18n/src/translations/en-US/portals/actions.ts @@ -164,15 +164,15 @@ export const actions: actionsNS = { }, fetchById: { description: "{{description}}", - message: "Error fetching the action." + message: "Error retrieving the action." }, fetchByType: { description: "{{description}}", - message: "Error fetching actions." + message: "Error retrieving actions." }, typesFetch: { description: "{{description}}", - message: "Error fetching the action types." + message: "Error retrieving the action types." }, update: { description: "{{description}}",