chore: Refactor widgetselectionSagas to extract PartialImportExportSagas (#30295)
## Description This pull request refactors `WidgetSelectionSagas` and extracts partial import export logic. Adds the PartialImportExportSagas file and updates the imports in multiple files to use the new file. #### PR fixes following issue(s) Fixes # (issue number) > if no issue exists, please create an issue and ask the maintainers about this first > > #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced functionality for exporting and importing partial applications, including widgets, queries, datasources, and custom JavaScript libraries. - **Refactor** - Updated import statements to reflect the new structure for partial import and export functionality. - **Chores** - Performed code cleanup and reformatting in import and selection sagas. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
1949c79142
commit
1e50debe2a
|
|
@ -7,7 +7,7 @@ import type { ExecuteTriggerPayload } from "constants/AppsmithActionConstants/Ac
|
|||
import type { BatchAction } from "actions/batchActions";
|
||||
import { batchAction } from "actions/batchActions";
|
||||
import type { WidgetProps } from "widgets/BaseWidget";
|
||||
import type { PartialExportParams } from "sagas/WidgetSelectionSagas";
|
||||
import type { PartialExportParams } from "sagas/PartialImportExportSagas";
|
||||
|
||||
export const widgetInitialisationSuccess = () => {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import { useAppWideAndOtherDatasource } from "@appsmith/pages/Editor/Explorer/ho
|
|||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import type { CanvasStructure } from "reducers/uiReducers/pageCanvasStructureReducer";
|
||||
import type { PartialExportParams } from "sagas/WidgetSelectionSagas";
|
||||
import type { PartialExportParams } from "sagas/PartialImportExportSagas";
|
||||
import { getCurrentPageName } from "selectors/editorSelectors";
|
||||
import type { JSLibrary } from "workers/common/JSLibrary";
|
||||
import EntityCheckboxSelector from "./EntityCheckboxSelector";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
import ApplicationApi, {
|
||||
type exportApplicationRequest,
|
||||
} from "@appsmith/api/ApplicationApi";
|
||||
import type {
|
||||
ApplicationPayload,
|
||||
ReduxAction,
|
||||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import {
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionTypes,
|
||||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
|
||||
import { toast } from "design-system";
|
||||
import { getFlexLayersForSelectedWidgets } from "layoutSystems/autolayout/utils/AutoLayoutUtils";
|
||||
import type { FlexLayer } from "layoutSystems/autolayout/utils/types";
|
||||
import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import { all, call, put, select } from "redux-saga/effects";
|
||||
import {
|
||||
getCurrentApplicationId,
|
||||
getCurrentPageId,
|
||||
} from "selectors/editorSelectors";
|
||||
import { validateResponse } from "../ErrorSagas";
|
||||
import { createWidgetCopy } from "../WidgetOperationUtils";
|
||||
import { getWidgets } from "../selectors";
|
||||
|
||||
export interface PartialExportParams {
|
||||
jsObjects: string[];
|
||||
datasources: string[];
|
||||
customJSLibs: string[];
|
||||
widgets: string[];
|
||||
queries: string[];
|
||||
}
|
||||
|
||||
export function* partialExportSaga(action: ReduxAction<PartialExportParams>) {
|
||||
try {
|
||||
const canvasWidgets: unknown = yield partialExportWidgetSaga(
|
||||
action.payload.widgets,
|
||||
);
|
||||
const applicationId: string = yield select(getCurrentApplicationId);
|
||||
const currentPageId: string = yield select(getCurrentPageId);
|
||||
|
||||
const body: exportApplicationRequest = {
|
||||
actionList: action.payload.queries,
|
||||
actionCollectionList: action.payload.jsObjects,
|
||||
datasourceList: action.payload.datasources,
|
||||
customJsLib: action.payload.customJSLibs,
|
||||
widget: JSON.stringify(canvasWidgets),
|
||||
};
|
||||
|
||||
const response: unknown = yield call(
|
||||
ApplicationApi.exportPartialApplication,
|
||||
applicationId,
|
||||
currentPageId,
|
||||
body,
|
||||
);
|
||||
const isValid: boolean = yield validateResponse(response);
|
||||
if (isValid) {
|
||||
const application: ApplicationPayload = yield select(
|
||||
getCurrentApplication,
|
||||
);
|
||||
|
||||
(function downloadJSON(response: unknown) {
|
||||
const dataStr =
|
||||
"data:text/json;charset=utf-8," +
|
||||
encodeURIComponent(JSON.stringify(response));
|
||||
const downloadAnchorNode = document.createElement("a");
|
||||
downloadAnchorNode.setAttribute("href", dataStr);
|
||||
downloadAnchorNode.setAttribute("download", `${application.name}.json`);
|
||||
document.body.appendChild(downloadAnchorNode); // required for firefox
|
||||
downloadAnchorNode.click();
|
||||
downloadAnchorNode.remove();
|
||||
})((response as { data: unknown }).data);
|
||||
yield put({
|
||||
type: ReduxActionTypes.PARTIAL_EXPORT_SUCCESS,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
toast.show(`Error exporting application. Please try again.`, {
|
||||
kind: "error",
|
||||
});
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.PARTIAL_EXPORT_ERROR,
|
||||
payload: {
|
||||
error: "Error exporting application",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* partialExportWidgetSaga(widgetIds: string[]) {
|
||||
const canvasWidgets: {
|
||||
[widgetId: string]: FlattenedWidgetProps;
|
||||
} = yield select(getWidgets);
|
||||
const selectedWidgets = widgetIds.map((each) => canvasWidgets[each]);
|
||||
|
||||
if (!selectedWidgets || !selectedWidgets.length) return;
|
||||
|
||||
const widgetListsToStore: {
|
||||
widgetId: string;
|
||||
parentId: string;
|
||||
list: FlattenedWidgetProps[];
|
||||
}[] = yield all(
|
||||
selectedWidgets.map((widget) => call(createWidgetCopy, widget)),
|
||||
);
|
||||
|
||||
const canvasId = selectedWidgets?.[0]?.parentId || "";
|
||||
|
||||
const flexLayers: FlexLayer[] = getFlexLayersForSelectedWidgets(
|
||||
widgetIds,
|
||||
canvasId ? canvasWidgets[canvasId] : undefined,
|
||||
);
|
||||
const widgetsDSL = {
|
||||
widgets: widgetListsToStore,
|
||||
flexLayers,
|
||||
};
|
||||
return widgetsDSL;
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
import {
|
||||
importPartialApplicationSuccess,
|
||||
initDatasourceConnectionDuringImportRequest,
|
||||
} from "@appsmith/actions/applicationActions";
|
||||
import ApplicationApi from "@appsmith/api/ApplicationApi";
|
||||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import { ReduxActionErrorTypes } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import { areEnvironmentsFetched } from "@appsmith/selectors/environmentSelectors";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
|
||||
import { pasteWidget } from "actions/widgetActions";
|
||||
import { selectWidgetInitAction } from "actions/widgetSelectionActions";
|
||||
import type { ApiResponse } from "api/ApiResponses";
|
||||
import { toast } from "design-system";
|
||||
import { call, fork, put, select } from "redux-saga/effects";
|
||||
import { SelectionRequestType } from "sagas/WidgetSelectUtils";
|
||||
import {
|
||||
getCurrentApplicationId,
|
||||
getCurrentPageId,
|
||||
} from "selectors/editorSelectors";
|
||||
import { getCopiedWidgets, saveCopiedWidgets } from "utils/storage";
|
||||
import { validateResponse } from "../ErrorSagas";
|
||||
import { postPageAdditionSaga } from "../TemplatesSagas";
|
||||
|
||||
async function readJSONFile(file: File) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
try {
|
||||
const json = JSON.parse(reader.result as string);
|
||||
resolve(json);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
|
||||
function* partialImportWidgetsSaga(file: File) {
|
||||
const existingCopiedWidgets: unknown = yield call(getCopiedWidgets);
|
||||
try {
|
||||
// assume that action.payload.applicationFile is a JSON file. Parse it and extract widgets property
|
||||
const userUploadedJSON: { widgets: string } = yield call(
|
||||
readJSONFile,
|
||||
file,
|
||||
);
|
||||
if ("widgets" in userUploadedJSON && userUploadedJSON.widgets.length > 0) {
|
||||
yield saveCopiedWidgets(userUploadedJSON.widgets);
|
||||
yield put(selectWidgetInitAction(SelectionRequestType.Empty));
|
||||
yield put(pasteWidget(false, { x: 0, y: 0 }));
|
||||
}
|
||||
} finally {
|
||||
if (existingCopiedWidgets) {
|
||||
yield call(saveCopiedWidgets, JSON.stringify(existingCopiedWidgets));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function* partialImportSaga(
|
||||
action: ReduxAction<{ applicationFile: File }>,
|
||||
) {
|
||||
try {
|
||||
// Step1: Import widgets from file, in parallel
|
||||
yield fork(partialImportWidgetsSaga, action.payload.applicationFile);
|
||||
// Step2: Send backend request to import pending items.
|
||||
const workspaceId: string = yield select(getCurrentWorkspaceId);
|
||||
const pageId: string = yield select(getCurrentPageId);
|
||||
const applicationId: string = yield select(getCurrentApplicationId);
|
||||
const response: ApiResponse = yield call(
|
||||
ApplicationApi.importPartialApplication,
|
||||
{
|
||||
applicationFile: action.payload.applicationFile,
|
||||
workspaceId,
|
||||
pageId,
|
||||
applicationId,
|
||||
},
|
||||
);
|
||||
|
||||
const isValidResponse: boolean = yield validateResponse(response);
|
||||
|
||||
if (isValidResponse) {
|
||||
yield call(postPageAdditionSaga, applicationId);
|
||||
toast.show("Partial Application imported successfully", {
|
||||
kind: "success",
|
||||
});
|
||||
|
||||
const environmentsFetched: boolean = yield select((state: AppState) =>
|
||||
areEnvironmentsFetched(state, workspaceId),
|
||||
);
|
||||
|
||||
if (workspaceId && environmentsFetched) {
|
||||
yield put(
|
||||
initDatasourceConnectionDuringImportRequest({
|
||||
workspaceId: workspaceId as string,
|
||||
isPartialImport: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
yield put(importPartialApplicationSuccess());
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.PARTIAL_IMPORT_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
2
app/client/src/sagas/PartialImportExportSagas/index.ts
Normal file
2
app/client/src/sagas/PartialImportExportSagas/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./PartialExportSagas";
|
||||
export * from "./PartialImportSagas";
|
||||
|
|
@ -136,11 +136,11 @@ import {
|
|||
mergeDynamicPropertyPaths,
|
||||
purgeOrphanedDynamicPaths,
|
||||
} from "./WidgetOperationUtils";
|
||||
import { widgetSelectionSagas } from "./WidgetSelectionSagas";
|
||||
import {
|
||||
partialImportSaga,
|
||||
partialExportSaga,
|
||||
widgetSelectionSagas,
|
||||
} from "./WidgetSelectionSagas";
|
||||
partialImportSaga,
|
||||
} from "./PartialImportExportSagas";
|
||||
import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types";
|
||||
import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes";
|
||||
import { getCanvasSizeAfterWidgetMove } from "./CanvasSagas/DraggingCanvasSagas";
|
||||
|
|
|
|||
|
|
@ -1,54 +1,27 @@
|
|||
import { widgetURL } from "@appsmith/RouteBuilder";
|
||||
import {
|
||||
importPartialApplicationSuccess,
|
||||
initDatasourceConnectionDuringImportRequest,
|
||||
} from "@appsmith/actions/applicationActions";
|
||||
import ApplicationApi, {
|
||||
type exportApplicationRequest,
|
||||
} from "@appsmith/api/ApplicationApi";
|
||||
import type {
|
||||
ApplicationPayload,
|
||||
ReduxAction,
|
||||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import {
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionTypes,
|
||||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors";
|
||||
import {
|
||||
getAppMode,
|
||||
getCanvasWidgets,
|
||||
} from "@appsmith/selectors/entitiesSelector";
|
||||
import { pasteWidget, showModal } from "actions/widgetActions";
|
||||
import { showModal } from "actions/widgetActions";
|
||||
import type {
|
||||
SetSelectedWidgetsPayload,
|
||||
WidgetSelectionRequestPayload,
|
||||
} from "actions/widgetSelectionActions";
|
||||
import {
|
||||
selectWidgetInitAction,
|
||||
setEntityExplorerAncestry,
|
||||
setSelectedWidgetAncestry,
|
||||
setSelectedWidgets,
|
||||
} from "actions/widgetSelectionActions";
|
||||
import type { ApiResponse } from "api/ApiResponses";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
|
||||
import { toast } from "design-system";
|
||||
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
||||
import { APP_MODE } from "entities/App";
|
||||
import { getFlexLayersForSelectedWidgets } from "layoutSystems/autolayout/utils/AutoLayoutUtils";
|
||||
import type { FlexLayer } from "layoutSystems/autolayout/utils/types";
|
||||
import type {
|
||||
CanvasWidgetsReduxState,
|
||||
FlattenedWidgetProps,
|
||||
} from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import {
|
||||
all,
|
||||
call,
|
||||
fork,
|
||||
put,
|
||||
select,
|
||||
take,
|
||||
takeLatest,
|
||||
} from "redux-saga/effects";
|
||||
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import { all, call, put, select, take, takeLatest } from "redux-saga/effects";
|
||||
import type { SetSelectionResult } from "sagas/WidgetSelectUtils";
|
||||
import {
|
||||
SelectionRequestType,
|
||||
|
|
@ -63,7 +36,6 @@ import {
|
|||
unselectWidget,
|
||||
} from "sagas/WidgetSelectUtils";
|
||||
import {
|
||||
getCurrentApplicationId,
|
||||
getCurrentPageId,
|
||||
getIsEditorInitialized,
|
||||
getIsFetchingPage,
|
||||
|
|
@ -73,18 +45,11 @@ import { getLastSelectedWidget, getSelectedWidgets } from "selectors/ui";
|
|||
import { areArraysEqual } from "utils/AppsmithUtils";
|
||||
import { quickScrollToWidget } from "utils/helpers";
|
||||
import history, { NavigationMethod } from "utils/history";
|
||||
import { getCopiedWidgets, saveCopiedWidgets } from "utils/storage";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
import { postPageAdditionSaga } from "./TemplatesSagas";
|
||||
import { createWidgetCopy } from "./WidgetOperationUtils";
|
||||
import {
|
||||
getWidgetIdsByType,
|
||||
getWidgetImmediateChildren,
|
||||
getWidgets,
|
||||
} from "./selectors";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import { areEnvironmentsFetched } from "@appsmith/selectors/environmentSelectors";
|
||||
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
||||
|
||||
// The following is computed to be used in the entity explorer
|
||||
// Every time a widget is selected, we need to expand widget entities
|
||||
|
|
@ -365,184 +330,3 @@ export function* widgetSelectionSagas() {
|
|||
),
|
||||
]);
|
||||
}
|
||||
|
||||
export interface PartialExportParams {
|
||||
jsObjects: string[];
|
||||
datasources: string[];
|
||||
customJSLibs: string[];
|
||||
widgets: string[];
|
||||
queries: string[];
|
||||
}
|
||||
|
||||
export function* partialExportSaga(action: ReduxAction<PartialExportParams>) {
|
||||
try {
|
||||
const canvasWidgets: unknown = yield partialExportWidgetSaga(
|
||||
action.payload.widgets,
|
||||
);
|
||||
const applicationId: string = yield select(getCurrentApplicationId);
|
||||
const currentPageId: string = yield select(getCurrentPageId);
|
||||
|
||||
const body: exportApplicationRequest = {
|
||||
actionList: action.payload.queries,
|
||||
actionCollectionList: action.payload.jsObjects,
|
||||
datasourceList: action.payload.datasources,
|
||||
customJsLib: action.payload.customJSLibs,
|
||||
widget: JSON.stringify(canvasWidgets),
|
||||
};
|
||||
|
||||
const response: unknown = yield call(
|
||||
ApplicationApi.exportPartialApplication,
|
||||
applicationId,
|
||||
currentPageId,
|
||||
body,
|
||||
);
|
||||
const isValid: boolean = yield validateResponse(response);
|
||||
if (isValid) {
|
||||
const application: ApplicationPayload = yield select(
|
||||
getCurrentApplication,
|
||||
);
|
||||
|
||||
(function downloadJSON(response: unknown) {
|
||||
const dataStr =
|
||||
"data:text/json;charset=utf-8," +
|
||||
encodeURIComponent(JSON.stringify(response));
|
||||
const downloadAnchorNode = document.createElement("a");
|
||||
downloadAnchorNode.setAttribute("href", dataStr);
|
||||
downloadAnchorNode.setAttribute("download", `${application.name}.json`);
|
||||
document.body.appendChild(downloadAnchorNode); // required for firefox
|
||||
downloadAnchorNode.click();
|
||||
downloadAnchorNode.remove();
|
||||
})((response as { data: unknown }).data);
|
||||
yield put({
|
||||
type: ReduxActionTypes.PARTIAL_EXPORT_SUCCESS,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
toast.show(`Error exporting application. Please try again.`, {
|
||||
kind: "error",
|
||||
});
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.PARTIAL_EXPORT_ERROR,
|
||||
payload: {
|
||||
error: "Error exporting application",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* partialExportWidgetSaga(widgetIds: string[]) {
|
||||
const canvasWidgets: {
|
||||
[widgetId: string]: FlattenedWidgetProps;
|
||||
} = yield select(getWidgets);
|
||||
const selectedWidgets = widgetIds.map((each) => canvasWidgets[each]);
|
||||
|
||||
if (!selectedWidgets || !selectedWidgets.length) return;
|
||||
|
||||
const widgetListsToStore: {
|
||||
widgetId: string;
|
||||
parentId: string;
|
||||
list: FlattenedWidgetProps[];
|
||||
}[] = yield all(
|
||||
selectedWidgets.map((widget) => call(createWidgetCopy, widget)),
|
||||
);
|
||||
|
||||
const canvasId = selectedWidgets?.[0]?.parentId || "";
|
||||
|
||||
const flexLayers: FlexLayer[] = getFlexLayersForSelectedWidgets(
|
||||
widgetIds,
|
||||
canvasId ? canvasWidgets[canvasId] : undefined,
|
||||
);
|
||||
const widgetsDSL = {
|
||||
widgets: widgetListsToStore,
|
||||
flexLayers,
|
||||
};
|
||||
return widgetsDSL;
|
||||
}
|
||||
|
||||
async function readJSONFile(file: File) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
try {
|
||||
const json = JSON.parse(reader.result as string);
|
||||
resolve(json);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
|
||||
function* partialImportWidgetsSaga(file: File) {
|
||||
const existingCopiedWidgets: unknown = yield call(getCopiedWidgets);
|
||||
try {
|
||||
// assume that action.payload.applicationFile is a JSON file. Parse it and extract widgets property
|
||||
const userUploadedJSON: { widgets: string } = yield call(
|
||||
readJSONFile,
|
||||
file,
|
||||
);
|
||||
if ("widgets" in userUploadedJSON && userUploadedJSON.widgets.length > 0) {
|
||||
yield saveCopiedWidgets(userUploadedJSON.widgets);
|
||||
yield put(selectWidgetInitAction(SelectionRequestType.Empty));
|
||||
yield put(pasteWidget(false, { x: 0, y: 0 }));
|
||||
}
|
||||
} finally {
|
||||
if (existingCopiedWidgets) {
|
||||
yield call(saveCopiedWidgets, JSON.stringify(existingCopiedWidgets));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function* partialImportSaga(
|
||||
action: ReduxAction<{ applicationFile: File }>,
|
||||
) {
|
||||
try {
|
||||
// Step1: Import widgets from file, in parallel
|
||||
yield fork(partialImportWidgetsSaga, action.payload.applicationFile);
|
||||
// Step2: Send backend request to import pending items.
|
||||
const workspaceId: string = yield select(getCurrentWorkspaceId);
|
||||
const pageId: string = yield select(getCurrentPageId);
|
||||
const applicationId: string = yield select(getCurrentApplicationId);
|
||||
const response: ApiResponse = yield call(
|
||||
ApplicationApi.importPartialApplication,
|
||||
{
|
||||
applicationFile: action.payload.applicationFile,
|
||||
workspaceId,
|
||||
pageId,
|
||||
applicationId,
|
||||
},
|
||||
);
|
||||
|
||||
const isValidResponse: boolean = yield validateResponse(response);
|
||||
|
||||
if (isValidResponse) {
|
||||
yield call(postPageAdditionSaga, applicationId);
|
||||
toast.show("Partial Application imported successfully", {
|
||||
kind: "success",
|
||||
});
|
||||
|
||||
const environmentsFetched: boolean = yield select((state: AppState) =>
|
||||
areEnvironmentsFetched(state, workspaceId),
|
||||
);
|
||||
|
||||
if (workspaceId && environmentsFetched) {
|
||||
yield put(
|
||||
initDatasourceConnectionDuringImportRequest({
|
||||
workspaceId: workspaceId as string,
|
||||
isPartialImport: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
yield put(importPartialApplicationSuccess());
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.PARTIAL_IMPORT_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user