chore: Refactor widget rename saga to extend for packages (#40243)
## Description This PR implements a flexible extension system for widget name updates by: - Creating a singleton WidgetNameUpdateExtension class for pluggable widget renaming handlers - Adding default implementation with handleWidgetNameUpdateDefault function - Refactoring UpdateWidgetNameRequest interface to support optional fields (pageId, moduleId, contextType) - Extracting widget name update logic to dedicated functions for better maintainability - Adding packageMiddleware to the Redux store configuration These changes enable customized widget naming behavior in different contexts without modifying core code, improving extensibility while maintaining backward compatibility. PR for https://github.com/appsmithorg/appsmith-ee/pull/7122 ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/14463310871> > Commit: 4b4433fa68479ada6426ee39d353abc3973a2864 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=14463310871&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Tue, 15 Apr 2025 15:51:36 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Modularized the widget name update process, allowing for extension or override of update behavior. - Improved the structure of widget name update logic for better maintainability. - **Chores** - Updated internal interfaces to support additional parameters and optional properties. - Added a new middleware to the Redux store setup. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
c8a132f88d
commit
b5d22b8ba0
|
|
@ -135,10 +135,12 @@ export interface ClonePageRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateWidgetNameRequest {
|
export interface UpdateWidgetNameRequest {
|
||||||
pageId: string;
|
pageId?: string;
|
||||||
layoutId: string;
|
layoutId: string;
|
||||||
newName: string;
|
newName: string;
|
||||||
oldName: string;
|
oldName: string;
|
||||||
|
moduleId?: string;
|
||||||
|
contextType?: "MODULE" | "PAGE";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenerateTemplatePageRequest {
|
export interface GenerateTemplatePageRequest {
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,11 @@ import {
|
||||||
} from "selectors/gitModSelectors";
|
} from "selectors/gitModSelectors";
|
||||||
import captureException from "instrumentation/sendFaroErrors";
|
import captureException from "instrumentation/sendFaroErrors";
|
||||||
|
|
||||||
|
export interface HandleWidgetNameUpdatePayload {
|
||||||
|
newName: string;
|
||||||
|
widgetName: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const checkIfMigrationIsNeeded = (
|
export const checkIfMigrationIsNeeded = (
|
||||||
fetchPageResponse?: FetchPageResponse,
|
fetchPageResponse?: FetchPageResponse,
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -954,6 +959,96 @@ export function* clonePageSaga(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class WidgetNameUpdateExtension {
|
||||||
|
// Singleton instance
|
||||||
|
private static instance = new WidgetNameUpdateExtension();
|
||||||
|
|
||||||
|
// The extension function storage
|
||||||
|
private extensionFunction:
|
||||||
|
| ((params: HandleWidgetNameUpdatePayload) => Generator)
|
||||||
|
| null = null;
|
||||||
|
|
||||||
|
// Private constructor
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
// Get the instance
|
||||||
|
static getInstance() {
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the extension function
|
||||||
|
setExtension(fn: (params: HandleWidgetNameUpdatePayload) => Generator) {
|
||||||
|
this.extensionFunction = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the extension function
|
||||||
|
getExtension() {
|
||||||
|
return this.extensionFunction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* updateWidgetNameAPISaga(
|
||||||
|
requestParams: UpdateWidgetNameRequest,
|
||||||
|
) {
|
||||||
|
const response: UpdateWidgetNameResponse = yield call(
|
||||||
|
PageApi.updateWidgetName,
|
||||||
|
requestParams,
|
||||||
|
);
|
||||||
|
|
||||||
|
const isValidResponse: boolean = yield validateResponse(response);
|
||||||
|
|
||||||
|
return { response, isValidResponse };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* handleWidgetNameUpdateDefault(
|
||||||
|
params: HandleWidgetNameUpdatePayload,
|
||||||
|
) {
|
||||||
|
const { newName, widgetName } = params;
|
||||||
|
|
||||||
|
const layoutId: string | undefined = yield select(getCurrentLayoutId);
|
||||||
|
const pageId: string | undefined = yield select(getCurrentPageId);
|
||||||
|
|
||||||
|
const request: UpdateWidgetNameRequest = {
|
||||||
|
newName: newName,
|
||||||
|
oldName: widgetName,
|
||||||
|
pageId,
|
||||||
|
// @ts-expect-error: layoutId can be undefined
|
||||||
|
layoutId,
|
||||||
|
};
|
||||||
|
const { isValidResponse, response } = yield call(
|
||||||
|
updateWidgetNameAPISaga,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isValidResponse) {
|
||||||
|
// @ts-expect-error: pageId can be undefined
|
||||||
|
yield updateCanvasWithDSL(response.data, pageId, layoutId);
|
||||||
|
yield put(updateWidgetNameSuccess());
|
||||||
|
// Add this to the page DSLs for entity explorer
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionTypes.FETCH_PAGE_DSL_SUCCESS,
|
||||||
|
payload: {
|
||||||
|
pageId: pageId,
|
||||||
|
dsl: response.data.dsl,
|
||||||
|
layoutId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
checkAndLogErrorsIfCyclicDependency(
|
||||||
|
(response.data as PageLayout).layoutOnLoadActionErrors,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* handleWidgetNameUpdate(params: HandleWidgetNameUpdatePayload) {
|
||||||
|
const extension = WidgetNameUpdateExtension.getInstance().getExtension();
|
||||||
|
|
||||||
|
if (extension) {
|
||||||
|
yield call(extension, params);
|
||||||
|
} else {
|
||||||
|
yield call(handleWidgetNameUpdateDefault, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this saga do two things
|
* this saga do two things
|
||||||
*
|
*
|
||||||
|
|
@ -967,8 +1062,6 @@ export function* updateWidgetNameSaga(
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { widgetName } = yield select(getWidgetName, action.payload.id);
|
const { widgetName } = yield select(getWidgetName, action.payload.id);
|
||||||
const layoutId: string | undefined = yield select(getCurrentLayoutId);
|
|
||||||
const pageId: string | undefined = yield select(getCurrentPageId);
|
|
||||||
const getUsedNames: Record<string, true> = yield select(
|
const getUsedNames: Record<string, true> = yield select(
|
||||||
getUsedActionNames,
|
getUsedActionNames,
|
||||||
"",
|
"",
|
||||||
|
|
@ -1058,37 +1151,10 @@ export function* updateWidgetNameSaga(
|
||||||
// check if name is not conflicting with any
|
// check if name is not conflicting with any
|
||||||
// existing entity/api/queries/reserved words
|
// existing entity/api/queries/reserved words
|
||||||
if (isNameValid(action.payload.newName, getUsedNames)) {
|
if (isNameValid(action.payload.newName, getUsedNames)) {
|
||||||
const request: UpdateWidgetNameRequest = {
|
yield call(handleWidgetNameUpdate, {
|
||||||
newName: action.payload.newName,
|
newName: action.payload.newName,
|
||||||
oldName: widgetName,
|
widgetName,
|
||||||
// @ts-expect-error: pageId can be undefined
|
|
||||||
pageId,
|
|
||||||
// @ts-expect-error: layoutId can be undefined
|
|
||||||
layoutId,
|
|
||||||
};
|
|
||||||
const response: UpdateWidgetNameResponse = yield call(
|
|
||||||
PageApi.updateWidgetName,
|
|
||||||
request,
|
|
||||||
);
|
|
||||||
const isValidResponse: boolean = yield validateResponse(response);
|
|
||||||
|
|
||||||
if (isValidResponse) {
|
|
||||||
// @ts-expect-error: pageId can be undefined
|
|
||||||
yield updateCanvasWithDSL(response.data, pageId, layoutId);
|
|
||||||
yield put(updateWidgetNameSuccess());
|
|
||||||
// Add this to the page DSLs for entity explorer
|
|
||||||
yield put({
|
|
||||||
type: ReduxActionTypes.FETCH_PAGE_DSL_SUCCESS,
|
|
||||||
payload: {
|
|
||||||
pageId: pageId,
|
|
||||||
dsl: response.data.dsl,
|
|
||||||
layoutId,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
checkAndLogErrorsIfCyclicDependency(
|
|
||||||
(response.data as PageLayout).layoutOnLoadActionErrors,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
yield put({
|
yield put({
|
||||||
type: ReduxActionErrorTypes.UPDATE_WIDGET_NAME_ERROR,
|
type: ReduxActionErrorTypes.UPDATE_WIDGET_NAME_ERROR,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { composeWithDevTools } from "redux-devtools-extension/logOnlyInProductio
|
||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||||
import routeParamsMiddleware from "ee/middlewares/RouteParamsMiddleware";
|
import routeParamsMiddleware from "ee/middlewares/RouteParamsMiddleware";
|
||||||
|
import packageMiddleware from "ee/middlewares/PackageMiddleware";
|
||||||
|
|
||||||
const sagaMiddleware = createSagaMiddleware();
|
const sagaMiddleware = createSagaMiddleware();
|
||||||
const ignoredSentryActionTypes = [
|
const ignoredSentryActionTypes = [
|
||||||
|
|
@ -30,7 +31,7 @@ export default createStore(
|
||||||
appReducer,
|
appReducer,
|
||||||
composeWithDevTools(
|
composeWithDevTools(
|
||||||
reduxBatch,
|
reduxBatch,
|
||||||
applyMiddleware(sagaMiddleware, routeParamsMiddleware),
|
applyMiddleware(packageMiddleware, sagaMiddleware, routeParamsMiddleware),
|
||||||
reduxBatch,
|
reduxBatch,
|
||||||
sentryReduxEnhancer,
|
sentryReduxEnhancer,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user