2022-03-03 10:56:53 +00:00
|
|
|
import {
|
|
|
|
|
ApplicationPayload,
|
2022-09-22 03:49:18 +00:00
|
|
|
Page,
|
2022-03-03 10:56:53 +00:00
|
|
|
ReduxAction,
|
|
|
|
|
ReduxActionErrorTypes,
|
|
|
|
|
ReduxActionTypes,
|
2022-04-12 10:50:01 +00:00
|
|
|
} from "@appsmith/constants/ReduxActionConstants";
|
2022-09-22 03:49:18 +00:00
|
|
|
import { all, put, takeEvery, call, select, take } from "redux-saga/effects";
|
|
|
|
|
import { differenceBy } from "lodash";
|
2022-06-21 13:57:34 +00:00
|
|
|
import TemplatesAPI, {
|
|
|
|
|
ImportTemplateResponse,
|
2022-09-22 03:49:18 +00:00
|
|
|
FetchTemplateResponse,
|
|
|
|
|
TemplateFiltersResponse,
|
2022-06-21 13:57:34 +00:00
|
|
|
} from "api/TemplatesApi";
|
2022-03-03 10:56:53 +00:00
|
|
|
import history from "utils/history";
|
|
|
|
|
import { getDefaultPageId } from "./ApplicationSagas";
|
2022-09-22 03:49:18 +00:00
|
|
|
import {
|
|
|
|
|
getAllTemplates,
|
|
|
|
|
setTemplateNotificationSeenAction,
|
|
|
|
|
showTemplatesModal,
|
|
|
|
|
} from "actions/templateActions";
|
2022-03-03 10:56:53 +00:00
|
|
|
import {
|
|
|
|
|
getTemplateNotificationSeen,
|
|
|
|
|
setTemplateNotificationSeen,
|
|
|
|
|
} from "utils/storage";
|
|
|
|
|
import { validateResponse } from "./ErrorSagas";
|
2022-03-25 10:43:26 +00:00
|
|
|
import { builderURL } from "RouteBuilder";
|
2022-09-22 03:49:18 +00:00
|
|
|
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
|
|
|
|
import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
|
|
|
|
|
import { fetchApplication } from "actions/applicationActions";
|
|
|
|
|
import { APP_MODE } from "entities/App";
|
|
|
|
|
import { getPageList } from "selectors/entitiesSelector";
|
|
|
|
|
import {
|
|
|
|
|
executePageLoadActions,
|
|
|
|
|
fetchActionsForPage,
|
|
|
|
|
fetchActionsForPageError,
|
|
|
|
|
fetchActionsForPageSuccess,
|
|
|
|
|
} from "actions/pluginActionActions";
|
|
|
|
|
import {
|
|
|
|
|
fetchJSCollectionsForPage,
|
|
|
|
|
fetchJSCollectionsForPageError,
|
|
|
|
|
fetchJSCollectionsForPageSuccess,
|
|
|
|
|
} from "actions/jsActionActions";
|
|
|
|
|
import { failFastApiCalls } from "./InitSagas";
|
|
|
|
|
import { Toaster } from "components/ads/Toast";
|
|
|
|
|
import { Variant } from "components/ads/common";
|
|
|
|
|
import { fetchDatasources } from "actions/datasourceActions";
|
|
|
|
|
import { fetchPluginFormConfigs } from "actions/pluginActions";
|
|
|
|
|
import { fetchAllPageEntityCompletion, saveLayout } from "actions/pageActions";
|
2022-08-04 04:20:54 +00:00
|
|
|
import { showReconnectDatasourceModal } from "actions/applicationActions";
|
2022-03-03 10:56:53 +00:00
|
|
|
|
|
|
|
|
function* getAllTemplatesSaga() {
|
|
|
|
|
try {
|
2022-06-21 13:57:34 +00:00
|
|
|
const response: FetchTemplateResponse = yield call(
|
|
|
|
|
TemplatesAPI.getAllTemplates,
|
|
|
|
|
);
|
|
|
|
|
const isValid: boolean = yield validateResponse(response);
|
2022-03-03 10:56:53 +00:00
|
|
|
if (isValid) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.GET_ALL_TEMPLATES_SUCCESS,
|
|
|
|
|
payload: response.data,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.GET_ALL_TEMPLATES_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-15 15:37:41 +00:00
|
|
|
function* importTemplateToWorkspaceSaga(
|
|
|
|
|
action: ReduxAction<{ templateId: string; workspaceId: string }>,
|
2022-03-03 10:56:53 +00:00
|
|
|
) {
|
|
|
|
|
try {
|
2022-03-18 12:08:10 +00:00
|
|
|
const response: ImportTemplateResponse = yield call(
|
2022-03-03 10:56:53 +00:00
|
|
|
TemplatesAPI.importTemplate,
|
|
|
|
|
action.payload.templateId,
|
2022-06-15 15:37:41 +00:00
|
|
|
action.payload.workspaceId,
|
2022-03-03 10:56:53 +00:00
|
|
|
);
|
2022-03-25 10:43:26 +00:00
|
|
|
const isValid: boolean = yield validateResponse(response);
|
2022-03-18 12:08:10 +00:00
|
|
|
if (isValid) {
|
|
|
|
|
const application: ApplicationPayload = {
|
2022-08-04 04:20:54 +00:00
|
|
|
...response.data.application,
|
|
|
|
|
defaultPageId: getDefaultPageId(
|
|
|
|
|
response.data.application.pages,
|
|
|
|
|
) as string,
|
2022-03-18 12:08:10 +00:00
|
|
|
};
|
|
|
|
|
yield put({
|
2022-06-15 15:37:41 +00:00
|
|
|
type: ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_SUCCESS,
|
2022-08-04 04:20:54 +00:00
|
|
|
payload: response.data.application,
|
2022-07-11 04:06:29 +00:00
|
|
|
});
|
2022-08-04 04:20:54 +00:00
|
|
|
|
|
|
|
|
if (response.data.isPartialImport) {
|
|
|
|
|
yield put(
|
|
|
|
|
showReconnectDatasourceModal({
|
|
|
|
|
application: response.data.application,
|
|
|
|
|
unConfiguredDatasourceList:
|
|
|
|
|
response.data.unConfiguredDatasourceList,
|
|
|
|
|
workspaceId: action.payload.workspaceId,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
const pageURL = builderURL({
|
|
|
|
|
pageId: application.defaultPageId,
|
|
|
|
|
});
|
|
|
|
|
history.push(pageURL);
|
|
|
|
|
}
|
2022-09-22 03:49:18 +00:00
|
|
|
yield put(getAllTemplates());
|
2022-03-18 12:08:10 +00:00
|
|
|
}
|
2022-03-03 10:56:53 +00:00
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
2022-06-15 15:37:41 +00:00
|
|
|
type: ReduxActionErrorTypes.IMPORT_TEMPLATE_TO_WORKSPACE_ERROR,
|
2022-03-03 10:56:53 +00:00
|
|
|
payload: {
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* getSimilarTemplatesSaga(action: ReduxAction<string>) {
|
|
|
|
|
try {
|
2022-06-21 13:57:34 +00:00
|
|
|
const response: FetchTemplateResponse = yield call(
|
2022-03-03 10:56:53 +00:00
|
|
|
TemplatesAPI.getSimilarTemplates,
|
|
|
|
|
action.payload,
|
|
|
|
|
);
|
2022-06-21 13:57:34 +00:00
|
|
|
const isValid: boolean = yield validateResponse(response);
|
2022-03-03 10:56:53 +00:00
|
|
|
if (isValid) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.GET_SIMILAR_TEMPLATES_SUCCESS,
|
|
|
|
|
payload: response.data,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.GET_SIMILAR_TEMPLATES_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* setTemplateNotificationSeenSaga(action: ReduxAction<boolean>) {
|
|
|
|
|
yield setTemplateNotificationSeen(action.payload);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* getTemplateNotificationSeenSaga() {
|
2022-06-21 13:57:34 +00:00
|
|
|
const showTemplateNotification: unknown = yield getTemplateNotificationSeen();
|
2022-03-03 10:56:53 +00:00
|
|
|
|
|
|
|
|
if (showTemplateNotification) {
|
|
|
|
|
yield put(setTemplateNotificationSeenAction(true));
|
|
|
|
|
} else {
|
|
|
|
|
yield put(setTemplateNotificationSeenAction(false));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-31 05:16:04 +00:00
|
|
|
function* getTemplateSaga(action: ReduxAction<string>) {
|
|
|
|
|
try {
|
2022-06-21 13:57:34 +00:00
|
|
|
const response: FetchTemplateResponse = yield call(
|
2022-03-31 05:16:04 +00:00
|
|
|
TemplatesAPI.getTemplateInformation,
|
|
|
|
|
action.payload,
|
|
|
|
|
);
|
2022-06-21 13:57:34 +00:00
|
|
|
const isValid: boolean = yield validateResponse(response);
|
2022-03-31 05:16:04 +00:00
|
|
|
if (isValid) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.GET_TEMPLATE_SUCCESS,
|
|
|
|
|
payload: response.data,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.GET_TEMPLATE_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-22 03:49:18 +00:00
|
|
|
function* postPageAdditionSaga(pageId: string) {
|
|
|
|
|
const afterActionsFetch: boolean = yield failFastApiCalls(
|
|
|
|
|
[
|
|
|
|
|
fetchActionsForPage(pageId),
|
|
|
|
|
fetchJSCollectionsForPage(pageId),
|
|
|
|
|
fetchDatasources(),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
fetchActionsForPageSuccess([]).type,
|
|
|
|
|
fetchJSCollectionsForPageSuccess([]).type,
|
|
|
|
|
ReduxActionTypes.FETCH_DATASOURCES_SUCCESS,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
fetchActionsForPageError().type,
|
|
|
|
|
fetchJSCollectionsForPageError().type,
|
|
|
|
|
ReduxActionErrorTypes.FETCH_DATASOURCES_ERROR,
|
|
|
|
|
],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!afterActionsFetch) {
|
|
|
|
|
throw new Error("Failed importing template");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const afterPluginFormsFetch: boolean = yield failFastApiCalls(
|
|
|
|
|
[fetchPluginFormConfigs()],
|
|
|
|
|
[ReduxActionTypes.FETCH_PLUGIN_FORM_CONFIGS_SUCCESS],
|
|
|
|
|
[ReduxActionErrorTypes.FETCH_PLUGIN_FORM_CONFIGS_ERROR],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!afterPluginFormsFetch) {
|
|
|
|
|
throw new Error("Failed importing template");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* forkTemplateToApplicationSaga(
|
|
|
|
|
action: ReduxAction<{
|
|
|
|
|
templateId: string;
|
|
|
|
|
templateName: string;
|
|
|
|
|
pageNames?: string[];
|
|
|
|
|
}>,
|
|
|
|
|
) {
|
|
|
|
|
try {
|
|
|
|
|
const pagesToImport = action.payload.pageNames
|
|
|
|
|
? action.payload.pageNames
|
|
|
|
|
: undefined;
|
|
|
|
|
const applicationId: string = yield select(getCurrentApplicationId);
|
|
|
|
|
const workspaceId: string = yield select(getCurrentWorkspaceId);
|
|
|
|
|
const response: ImportTemplateResponse = yield call(
|
|
|
|
|
TemplatesAPI.importTemplateToApplication,
|
|
|
|
|
action.payload.templateId,
|
|
|
|
|
applicationId,
|
|
|
|
|
workspaceId,
|
|
|
|
|
pagesToImport,
|
|
|
|
|
);
|
|
|
|
|
const currentListOfPages: Page[] = yield select(getPageList);
|
|
|
|
|
// To fetch the new set of pages after merging the template into the existing application
|
|
|
|
|
yield put(
|
|
|
|
|
fetchApplication({
|
|
|
|
|
mode: APP_MODE.EDIT,
|
|
|
|
|
applicationId,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
const isValid: boolean = yield validateResponse(response);
|
|
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
|
const postImportPageList = response.data.application.pages.map((page) => {
|
|
|
|
|
return { pageId: page.id, ...page };
|
|
|
|
|
});
|
|
|
|
|
const newPages = differenceBy(
|
|
|
|
|
postImportPageList,
|
|
|
|
|
currentListOfPages,
|
|
|
|
|
"pageId",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Fetch the actions/jsobjects of the new set of pages that have been added
|
|
|
|
|
for (const i in newPages) {
|
|
|
|
|
if (newPages.hasOwnProperty(i)) {
|
|
|
|
|
yield call(postPageAdditionSaga, newPages[i].pageId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (response.data.isPartialImport) {
|
|
|
|
|
yield put(
|
|
|
|
|
showReconnectDatasourceModal({
|
|
|
|
|
application: response.data.application,
|
|
|
|
|
unConfiguredDatasourceList:
|
|
|
|
|
response.data.unConfiguredDatasourceList,
|
|
|
|
|
workspaceId,
|
|
|
|
|
pageId: newPages[0].pageId,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
history.push(
|
|
|
|
|
builderURL({
|
|
|
|
|
pageId: newPages[0].pageId,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
yield put(showTemplatesModal(false));
|
|
|
|
|
|
|
|
|
|
yield take(ReduxActionTypes.UPDATE_CANVAS_STRUCTURE);
|
|
|
|
|
yield put(saveLayout());
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.IMPORT_TEMPLATE_TO_APPLICATION_SUCCESS,
|
|
|
|
|
payload: response.data.application,
|
|
|
|
|
});
|
|
|
|
|
yield put(getAllTemplates());
|
|
|
|
|
|
|
|
|
|
Toaster.show({
|
|
|
|
|
text: `Pages from '${action.payload.templateName}' template added successfully`,
|
|
|
|
|
variant: Variant.success,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.IMPORT_TEMPLATE_TO_APPLICATION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* getTemplateFiltersSaga() {
|
|
|
|
|
try {
|
|
|
|
|
const response: TemplateFiltersResponse = yield call(
|
|
|
|
|
TemplatesAPI.getTemplateFilters,
|
|
|
|
|
);
|
|
|
|
|
const isValid: boolean = yield validateResponse(response);
|
|
|
|
|
if (isValid) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.GET_TEMPLATE_FILTERS_SUCCESS,
|
|
|
|
|
payload: response.data,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.GET_TEMPLATE_FILTERS_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
e,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-03 10:56:53 +00:00
|
|
|
export default function* watchActionSagas() {
|
|
|
|
|
yield all([
|
|
|
|
|
takeEvery(ReduxActionTypes.GET_ALL_TEMPLATES_INIT, getAllTemplatesSaga),
|
2022-03-31 05:16:04 +00:00
|
|
|
takeEvery(ReduxActionTypes.GET_TEMPLATE_INIT, getTemplateSaga),
|
2022-03-03 10:56:53 +00:00
|
|
|
takeEvery(
|
|
|
|
|
ReduxActionTypes.GET_SIMILAR_TEMPLATES_INIT,
|
|
|
|
|
getSimilarTemplatesSaga,
|
|
|
|
|
),
|
|
|
|
|
takeEvery(
|
2022-06-15 15:37:41 +00:00
|
|
|
ReduxActionTypes.IMPORT_TEMPLATE_TO_WORKSPACE_INIT,
|
|
|
|
|
importTemplateToWorkspaceSaga,
|
2022-03-03 10:56:53 +00:00
|
|
|
),
|
|
|
|
|
takeEvery(
|
|
|
|
|
ReduxActionTypes.GET_TEMPLATE_NOTIFICATION_SEEN,
|
|
|
|
|
getTemplateNotificationSeenSaga,
|
|
|
|
|
),
|
|
|
|
|
takeEvery(
|
|
|
|
|
ReduxActionTypes.SET_TEMPLATE_NOTIFICATION_SEEN,
|
|
|
|
|
setTemplateNotificationSeenSaga,
|
|
|
|
|
),
|
2022-09-22 03:49:18 +00:00
|
|
|
takeEvery(
|
|
|
|
|
ReduxActionTypes.IMPORT_TEMPLATE_TO_APPLICATION_INIT,
|
|
|
|
|
forkTemplateToApplicationSaga,
|
|
|
|
|
),
|
|
|
|
|
takeEvery(
|
|
|
|
|
ReduxActionTypes.GET_TEMPLATE_FILTERS_INIT,
|
|
|
|
|
getTemplateFiltersSaga,
|
|
|
|
|
),
|
2022-03-03 10:56:53 +00:00
|
|
|
]);
|
|
|
|
|
}
|