feat: paragon frontend ds creation implementation added (#38456)

## Description

This PR adds CE changes for the paragon integrations, with this whenever
anybody is using CE version, paragon integrations will be visible but
once they click on it, it will ask for them to put in email id and
request access.

It's counterpart EE PR handles the paragon integration creation and
authorisation in appsmith.

EE PR: https://github.com/appsmithorg/appsmith-ee/pull/5859
EE PR which has both CE and EE changes to ensure all things are working
smoothly: https://github.com/appsmithorg/appsmith-ee/pull/5866


Fixes #`38406`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags="@tag.Datasource"

### 🔍 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/12627633263>
> Commit: 9c1e06b557bc8d5d0d59e7bad3e70df6582900fa
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12627633263&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Datasource`
> Spec:
> <hr>Mon, 06 Jan 2025 07:10:57 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
  - Added support for External SaaS datasources and plugins.
- Introduced new actions and configurations for External SaaS
integration.

- **Refactor**
  - Restructured datasource-related sagas and import paths.
  - Updated selectors and constants to support new plugin type.

- **Code Improvements**
  - Enhanced datasource management and integration capabilities.
  - Improved modularity of saga functions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: “sneha122” <“sneha@appsmith.com”>
This commit is contained in:
sneha122 2025-01-07 11:51:08 +05:30 committed by GitHub
parent a4163f8bb0
commit 3626b93b53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 221 additions and 156 deletions

View File

@ -1,14 +1,5 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {
all,
call,
fork,
put,
select,
take,
takeEvery,
takeLatest,
} from "redux-saga/effects";
import { all, call, fork, put, select, take } from "redux-saga/effects";
import {
change,
getFormInitialValues,
@ -26,7 +17,6 @@ import type {
import {
ReduxActionErrorTypes,
ReduxActionTypes,
ReduxFormActionTypes,
} from "ee/constants/ReduxActionConstants";
import {
getCurrentApplicationId,
@ -97,10 +87,10 @@ import {
DATASOURCE_REST_API_FORM,
} from "ee/constants/forms";
import type { ActionDataState } from "ee/reducers/entityReducers/actionsReducer";
import { setIdeEditorViewMode } from "../actions/ideActions";
import { setIdeEditorViewMode } from "../../actions/ideActions";
import { EditorViewMode } from "ee/entities/IDE/constants";
import { createActionRequestSaga } from "./ActionSagas";
import { validateResponse } from "./ErrorSagas";
import { createActionRequestSaga } from "../../sagas/ActionSagas";
import { validateResponse } from "../../sagas/ErrorSagas";
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
import type { GetFormData } from "selectors/formSelectors";
import { getFormData } from "selectors/formSelectors";
@ -176,21 +166,21 @@ import {
} from "ee/selectors/environmentSelectors";
import { waitForFetchEnvironments } from "ee/sagas/EnvironmentSagas";
import { getCurrentGitBranch } from "selectors/gitSyncSelectors";
import FocusRetention from "./FocusRetentionSaga";
import { identifyEntityFromPath } from "../navigation/FocusEntity";
import FocusRetention from "../../sagas/FocusRetentionSaga";
import { identifyEntityFromPath } from "../../navigation/FocusEntity";
import { MAX_DATASOURCE_SUGGESTIONS } from "constants/DatasourceEditorConstants";
import {
getFromServerWhenNoPrefetchedResult,
getInitialActionPayload,
getInitialDatasourcePayload,
} from "./helper";
import { executeGoogleApi } from "./loadGoogleApi";
} from "../../sagas/helper";
import { executeGoogleApi } from "../../sagas/loadGoogleApi";
import type { ActionParentEntityTypeInterface } from "ee/entities/Engine/actionHelpers";
import { getCurrentModuleId } from "ee/selectors/modulesSelector";
import type { ApplicationPayload } from "entities/Application";
import { openGeneratePageModalWithSelectedDS } from "../utils/GeneratePageUtils";
import { openGeneratePageModalWithSelectedDS } from "../../utils/GeneratePageUtils";
function* fetchDatasourcesSaga(
export function* fetchDatasourcesSaga(
action: ReduxAction<
| { workspaceId?: string; datasources?: ApiResponse<Datasource[]> }
| undefined
@ -224,7 +214,7 @@ function* fetchDatasourcesSaga(
}
}
function* handleFetchDatasourceStructureOnLoad() {
export function* handleFetchDatasourceStructureOnLoad() {
try {
// we fork to prevent the call from blocking
yield fork(fetchDatasourceStructureOnLoad);
@ -257,7 +247,7 @@ function* fetchDatasourceStructureOnLoad() {
} catch (error) {}
}
function* fetchMockDatasourcesSaga(action?: {
export function* fetchMockDatasourcesSaga(action?: {
payload?: { mockDatasources?: ApiResponse };
}) {
const mockDatasources = action?.payload?.mockDatasources;
@ -527,7 +517,7 @@ const getConnectionMethod = (
}
};
function* updateDatasourceSaga(
export function* updateDatasourceSaga(
actionPayload: ReduxActionWithCallbacks<
Datasource & { isInsideReconnectModal: boolean; currEditingEnvId?: string },
unknown,
@ -703,7 +693,7 @@ function* updateDatasourceSaga(
}
}
function* redirectAuthorizationCodeSaga(
export function* redirectAuthorizationCodeSaga(
actionPayload: ReduxAction<{
contextId: string;
contextType: ActionParentEntityTypeInterface;
@ -757,7 +747,7 @@ function* redirectAuthorizationCodeSaga(
}
}
function* getOAuthAccessTokenSaga(
export function* getOAuthAccessTokenSaga(
actionPayload: ReduxAction<{ datasourceId: string }>,
) {
const { datasourceId } = actionPayload.payload;
@ -854,7 +844,7 @@ function* getOAuthAccessTokenSaga(
}
}
function* updateDatasourceNameSaga(
export function* updateDatasourceNameSaga(
actionPayload: ReduxAction<{ id: string; name: string }>,
) {
try {
@ -889,13 +879,13 @@ function* updateDatasourceNameSaga(
}
}
function* handleDatasourceNameChangeFailureSaga(
export function* handleDatasourceNameChangeFailureSaga(
action: ReduxAction<{ oldName: string }>,
) {
yield put(change(DATASOURCE_DB_FORM, "name", action.payload.oldName));
}
function* testDatasourceSaga(actionPayload: ReduxAction<Datasource>) {
export function* testDatasourceSaga(actionPayload: ReduxAction<Datasource>) {
let workspaceId: string = yield select(getCurrentWorkspaceId);
// test button within the import modal
@ -1053,7 +1043,7 @@ function* testDatasourceSaga(actionPayload: ReduxAction<Datasource>) {
}
}
function* createTempDatasourceFromFormSaga(
export function* createTempDatasourceFromFormSaga(
actionPayload: ReduxAction<CreateDatasourceConfig | Datasource>,
) {
yield call(checkAndGetPluginFormConfigsSaga, actionPayload.payload.pluginId);
@ -1169,7 +1159,11 @@ export function* createOrUpdateDataSourceWithAction(
}
export function* createDatasourceFromFormSaga(
actionPayload: ReduxActionWithCallbacks<Datasource, unknown, unknown>,
actionPayload: ReduxActionWithCallbacks<
Datasource | CreateDatasourceConfig,
unknown,
unknown
>,
) {
try {
const workspaceId: string = yield select(getCurrentWorkspaceId);
@ -1323,7 +1317,7 @@ export function* createDatasourceFromFormSaga(
}
}
function* changeDatasourceSaga(
export function* changeDatasourceSaga(
actionPayload: ReduxAction<{
datasource: Datasource;
shouldNotRedirect?: boolean;
@ -1382,7 +1376,7 @@ function* changeDatasourceSaga(
);
}
function* switchDatasourceSaga(
export function* switchDatasourceSaga(
action: ReduxAction<{
datasourceId: string;
shouldNotRedirect: boolean;
@ -1396,7 +1390,7 @@ function* switchDatasourceSaga(
}
}
function* formValueChangeSaga(
export function* formValueChangeSaga(
actionPayload: ReduxActionWithMeta<string, { field: string; form: string }>,
) {
const { field, form } = actionPayload.meta;
@ -1435,7 +1429,7 @@ function* updateDraftsSaga(form: string) {
}
}
function* storeAsDatasourceSaga() {
export function* storeAsDatasourceSaga() {
const { values } = yield select(getFormData, API_EDITOR_FORM_NAME);
// const applicationId: string = yield select(getCurrentApplicationId);
const application: ApplicationPayload = yield select(getCurrentApplication);
@ -1509,7 +1503,9 @@ function* storeAsDatasourceSaga() {
yield put(changeDatasource({ datasource: createdDatasource }));
}
function* updateDatasourceSuccessSaga(action: UpdateDatasourceSuccessAction) {
export function* updateDatasourceSuccessSaga(
action: UpdateDatasourceSuccessAction,
) {
const state: AppState = yield select();
const actionRouteInfo = get(state, "ui.datasourcePane.actionRouteInfo");
const generateCRUDSupportedPlugin: GenerateCRUDEnabledPluginMap =
@ -1549,7 +1545,7 @@ function* updateDatasourceSuccessSaga(action: UpdateDatasourceSuccessAction) {
});
}
function* fetchDatasourceStructureSaga(
export function* fetchDatasourceStructureSaga(
action: ReduxAction<{
id: string;
ignoreCache: boolean;
@ -1668,7 +1664,7 @@ function* fetchDatasourceStructureSaga(
}
}
function* addAndFetchDatasourceStructureSaga(
export function* addAndFetchDatasourceStructureSaga(
action: ReduxAction<MockDatasource>,
) {
const plugin: Plugin = yield select((state: AppState) =>
@ -1698,7 +1694,7 @@ function* addAndFetchDatasourceStructureSaga(
}
}
function* refreshDatasourceStructure(
export function* refreshDatasourceStructure(
action: ReduxAction<{
id: string;
schemaRefreshContext: DatasourceStructureContext;
@ -1796,7 +1792,7 @@ function* refreshDatasourceStructure(
});
}
function* executeDatasourceQuerySaga(
export function* executeDatasourceQuerySaga(
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
action: executeDatasourceQueryReduxAction<any>,
@ -1850,7 +1846,7 @@ function* executeDatasourceQuerySaga(
}
}
function* initializeFormWithDefaults(
export function* initializeFormWithDefaults(
action: ReduxAction<{ pluginType: string }>,
) {
const formName =
@ -1888,7 +1884,7 @@ function* initializeFormWithDefaults(
}
}
function* filePickerActionCallbackSaga(
export function* filePickerActionCallbackSaga(
actionPayload: ReduxAction<{
action: FilePickerActionStatus;
datasourceId: string;
@ -1975,7 +1971,7 @@ function* filePickerActionCallbackSaga(
}
}
function* fetchGsheetSpreadhsheets(
export function* fetchGsheetSpreadhsheets(
action: ReduxAction<{
datasourceId: string;
pluginId: string;
@ -2075,7 +2071,7 @@ function* fetchGsheetSpreadhsheets(
}
}
function* fetchGsheetSheets(
export function* fetchGsheetSheets(
action: ReduxAction<{
datasourceId: string;
pluginId: string;
@ -2123,7 +2119,7 @@ function* fetchGsheetSheets(
}
}
function* fetchGsheetColumns(
export function* fetchGsheetColumns(
action: ReduxAction<{
datasourceId: string;
pluginId: string;
@ -2175,7 +2171,7 @@ function* fetchGsheetColumns(
}
}
function* loadFilePickerSaga() {
export function* loadFilePickerSaga() {
// This adds overlay on document body
// This is done for google sheets file picker, as file picker needs to be shown on blank page
// when overlay needs to be shown, we get showPicker search param in redirect url
@ -2199,7 +2195,7 @@ function* loadFilePickerSaga() {
}
}
function* updateDatasourceAuthStateSaga(
export function* updateDatasourceAuthStateSaga(
actionPayload: ReduxAction<{
authStatus: AuthenticationStatus;
datasource: Datasource;
@ -2250,7 +2246,7 @@ function* updateDatasourceAuthStateSaga(
}
}
function* datasourceDiscardActionSaga(
export function* datasourceDiscardActionSaga(
actionPayload: ReduxAction<{
pluginId: string;
}>,
@ -2270,7 +2266,7 @@ function* datasourceDiscardActionSaga(
});
}
function* setDatasourceViewModeSaga(
export function* setDatasourceViewModeSaga(
action: ReduxAction<{ datasourceId: string; viewMode: boolean }>,
) {
//Set the view mode flag in store
@ -2281,103 +2277,3 @@ function* setDatasourceViewModeSaga(
payload: action.payload.datasourceId,
});
}
export function* watchDatasourcesSagas() {
yield all([
takeEvery(ReduxActionTypes.FETCH_DATASOURCES_INIT, fetchDatasourcesSaga),
takeEvery(
ReduxActionTypes.FETCH_MOCK_DATASOURCES_INIT,
fetchMockDatasourcesSaga,
),
takeEvery(
ReduxActionTypes.ADD_MOCK_DATASOURCES_INIT,
addMockDbToDatasources,
),
takeEvery(
ReduxActionTypes.CREATE_DATASOURCE_FROM_FORM_INIT,
createDatasourceFromFormSaga,
),
takeEvery(
ReduxActionTypes.CREATE_TEMP_DATASOURCE_FROM_FORM_SUCCESS,
createTempDatasourceFromFormSaga,
),
takeEvery(ReduxActionTypes.UPDATE_DATASOURCE_INIT, updateDatasourceSaga),
takeEvery(
ReduxActionTypes.UPDATE_DATASOURCE_NAME,
updateDatasourceNameSaga,
),
takeEvery(
ReduxActionErrorTypes.UPDATE_DATASOURCE_NAME_ERROR,
handleDatasourceNameChangeFailureSaga,
),
takeEvery(ReduxActionTypes.TEST_DATASOURCE_INIT, testDatasourceSaga),
takeEvery(ReduxActionTypes.DELETE_DATASOURCE_INIT, deleteDatasourceSaga),
takeEvery(ReduxActionTypes.CHANGE_DATASOURCE, changeDatasourceSaga),
takeLatest(ReduxActionTypes.SWITCH_DATASOURCE, switchDatasourceSaga),
takeEvery(ReduxActionTypes.STORE_AS_DATASOURCE_INIT, storeAsDatasourceSaga),
takeEvery(
ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
updateDatasourceSuccessSaga,
),
takeEvery(
ReduxActionTypes.REDIRECT_AUTHORIZATION_CODE,
redirectAuthorizationCodeSaga,
),
takeEvery(ReduxActionTypes.GET_OAUTH_ACCESS_TOKEN, getOAuthAccessTokenSaga),
takeEvery(
ReduxActionTypes.FETCH_DATASOURCE_STRUCTURE_INIT,
fetchDatasourceStructureSaga,
),
takeEvery(
ReduxActionTypes.REFRESH_DATASOURCE_STRUCTURE_INIT,
refreshDatasourceStructure,
),
takeEvery(
ReduxActionTypes.EXECUTE_DATASOURCE_QUERY_INIT,
executeDatasourceQuerySaga,
),
takeEvery(
ReduxActionTypes.INITIALIZE_DATASOURCE_FORM_WITH_DEFAULTS,
initializeFormWithDefaults,
),
// Intercepting the redux-form change actionType to update drafts and track change history
takeEvery(ReduxFormActionTypes.VALUE_CHANGE, formValueChangeSaga),
takeEvery(ReduxFormActionTypes.ARRAY_PUSH, formValueChangeSaga),
takeEvery(ReduxFormActionTypes.ARRAY_REMOVE, formValueChangeSaga),
takeEvery(
ReduxActionTypes.FILE_PICKER_CALLBACK_ACTION,
filePickerActionCallbackSaga,
),
takeLatest(
ReduxActionTypes.FETCH_GSHEET_SPREADSHEETS,
fetchGsheetSpreadhsheets,
),
takeLatest(ReduxActionTypes.FETCH_GSHEET_SHEETS, fetchGsheetSheets),
takeLatest(ReduxActionTypes.FETCH_GSHEET_COLUMNS, fetchGsheetColumns),
takeEvery(ReduxActionTypes.LOAD_FILE_PICKER_ACTION, loadFilePickerSaga),
takeEvery(
ReduxActionTypes.UPDATE_DATASOURCE_AUTH_STATE,
updateDatasourceAuthStateSaga,
),
takeEvery(
ReduxActionTypes.DATASOURCE_DISCARD_ACTION,
datasourceDiscardActionSaga,
),
takeEvery(
ReduxActionTypes.ADD_AND_FETCH_MOCK_DATASOURCE_STRUCTURE_INIT,
addAndFetchDatasourceStructureSaga,
),
takeEvery(
ReduxActionTypes.FETCH_DATASOURCES_SUCCESS,
handleFetchDatasourceStructureOnLoad,
),
takeEvery(
ReduxActionTypes.SOFT_REFRESH_DATASOURCE_STRUCTURE,
handleFetchDatasourceStructureOnLoad,
),
takeEvery(
ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE,
setDatasourceViewModeSaga,
),
]);
}

View File

@ -16,7 +16,7 @@ import autoLayoutDraggingSagas from "sagas/CanvasSagas/AutoLayoutDraggingSagas";
import draggingCanvasSagas from "sagas/CanvasSagas/DraggingCanvasSagas";
import selectionCanvasSagas from "sagas/CanvasSagas/SelectionCanvasSagas";
import curlImportSagas from "sagas/CurlImportSagas";
import { watchDatasourcesSagas } from "sagas/DatasourcesSagas";
import { watchDatasourcesSagas } from "ee/sagas/DatasourcesSagas";
import debuggerSagas from "sagas/DebuggerSagas";
import editorContextSagas from "sagas/editorContextSagas";
import errorSagas from "sagas/ErrorSagas";

View File

@ -127,7 +127,8 @@ export const getDatasourcesGroupedByPluginCategory = createSelector(
if (
plugin.type === PluginType.SAAS ||
plugin.type === PluginType.REMOTE
plugin.type === PluginType.REMOTE ||
plugin.type === PluginType.EXTERNAL_SAAS
) {
return PluginCategory.SAAS;
}

View File

@ -177,6 +177,7 @@ export const defaultActionSettings: Record<PluginType, any> = {
[PluginType.JS]: [],
[PluginType.AI]: saasActionSettingsConfig,
[PluginType.INTERNAL]: saasActionSettingsConfig,
[PluginType.EXTERNAL_SAAS]: saasActionSettingsConfig,
};
// TODO: Fix this the next time the file is edited
@ -189,6 +190,7 @@ export const defaultActionEditorConfigs: Record<PluginType, any> = {
[PluginType.JS]: [],
[PluginType.AI]: [],
[PluginType.INTERNAL]: [],
[PluginType.EXTERNAL_SAAS]: [],
};
export const defaultActionDependenciesConfig: Record<
@ -202,6 +204,7 @@ export const defaultActionDependenciesConfig: Record<
[PluginType.JS]: {},
[PluginType.AI]: {},
[PluginType.INTERNAL]: {},
[PluginType.EXTERNAL_SAAS]: {},
};
export const defaultDatasourceFormButtonConfig: Record<PluginType, string[]> = {
@ -212,4 +215,5 @@ export const defaultDatasourceFormButtonConfig: Record<PluginType, string[]> = {
[PluginType.JS]: [],
[PluginType.AI]: apiActionDatasourceFormButtonConfig.AI,
[PluginType.INTERNAL]: [],
[PluginType.EXTERNAL_SAAS]: apiActionDatasourceFormButtonConfig.EXTERNAL_SAAS,
};

View File

@ -4,4 +4,5 @@ export default {
SAAS: ["CANCEL", "SAVE_AND_AUTHORIZE"],
REMOTE: ["CANCEL", "SAVE"],
AI: ["TEST", "CANCEL", "SAVE"],
EXTERNAL_SAAS: ["CANCEL", "SAVE_AND_AUTHORIZE"],
};

View File

@ -0,0 +1,140 @@
export { createOrUpdateDataSourceWithAction } from "ce/sagas/DatasourcesSagas";
import {
ReduxActionErrorTypes,
ReduxActionTypes,
ReduxFormActionTypes,
} from "ee/constants/ReduxActionConstants";
import { all, takeEvery, takeLatest } from "redux-saga/effects";
import {
addAndFetchDatasourceStructureSaga,
addMockDbToDatasources,
changeDatasourceSaga,
createDatasourceFromFormSaga,
datasourceDiscardActionSaga,
deleteDatasourceSaga,
executeDatasourceQuerySaga,
fetchDatasourcesSaga,
fetchDatasourceStructureSaga,
fetchGsheetColumns,
fetchGsheetSheets,
fetchGsheetSpreadhsheets,
fetchMockDatasourcesSaga,
filePickerActionCallbackSaga,
formValueChangeSaga,
getOAuthAccessTokenSaga,
handleDatasourceNameChangeFailureSaga,
handleFetchDatasourceStructureOnLoad,
initializeFormWithDefaults,
loadFilePickerSaga,
redirectAuthorizationCodeSaga,
refreshDatasourceStructure,
setDatasourceViewModeSaga,
storeAsDatasourceSaga,
switchDatasourceSaga,
testDatasourceSaga,
updateDatasourceAuthStateSaga,
updateDatasourceNameSaga,
updateDatasourceSaga,
updateDatasourceSuccessSaga,
createTempDatasourceFromFormSaga as CE_createTempDatasourceFromFormSaga,
} from "ce/sagas/DatasourcesSagas";
export function* watchDatasourcesSagas() {
yield all([
takeEvery(ReduxActionTypes.FETCH_DATASOURCES_INIT, fetchDatasourcesSaga),
takeEvery(
ReduxActionTypes.FETCH_MOCK_DATASOURCES_INIT,
fetchMockDatasourcesSaga,
),
takeEvery(
ReduxActionTypes.ADD_MOCK_DATASOURCES_INIT,
addMockDbToDatasources,
),
takeEvery(
ReduxActionTypes.CREATE_DATASOURCE_FROM_FORM_INIT,
createDatasourceFromFormSaga,
),
takeEvery(
ReduxActionTypes.CREATE_TEMP_DATASOURCE_FROM_FORM_SUCCESS,
CE_createTempDatasourceFromFormSaga,
),
takeEvery(ReduxActionTypes.UPDATE_DATASOURCE_INIT, updateDatasourceSaga),
takeEvery(
ReduxActionTypes.UPDATE_DATASOURCE_NAME,
updateDatasourceNameSaga,
),
takeEvery(
ReduxActionErrorTypes.UPDATE_DATASOURCE_NAME_ERROR,
handleDatasourceNameChangeFailureSaga,
),
takeEvery(ReduxActionTypes.TEST_DATASOURCE_INIT, testDatasourceSaga),
takeEvery(ReduxActionTypes.DELETE_DATASOURCE_INIT, deleteDatasourceSaga),
takeEvery(ReduxActionTypes.CHANGE_DATASOURCE, changeDatasourceSaga),
takeLatest(ReduxActionTypes.SWITCH_DATASOURCE, switchDatasourceSaga),
takeEvery(ReduxActionTypes.STORE_AS_DATASOURCE_INIT, storeAsDatasourceSaga),
takeEvery(
ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
updateDatasourceSuccessSaga,
),
takeEvery(
ReduxActionTypes.REDIRECT_AUTHORIZATION_CODE,
redirectAuthorizationCodeSaga,
),
takeEvery(ReduxActionTypes.GET_OAUTH_ACCESS_TOKEN, getOAuthAccessTokenSaga),
takeEvery(
ReduxActionTypes.FETCH_DATASOURCE_STRUCTURE_INIT,
fetchDatasourceStructureSaga,
),
takeEvery(
ReduxActionTypes.REFRESH_DATASOURCE_STRUCTURE_INIT,
refreshDatasourceStructure,
),
takeEvery(
ReduxActionTypes.EXECUTE_DATASOURCE_QUERY_INIT,
executeDatasourceQuerySaga,
),
takeEvery(
ReduxActionTypes.INITIALIZE_DATASOURCE_FORM_WITH_DEFAULTS,
initializeFormWithDefaults,
),
// Intercepting the redux-form change actionType to update drafts and track change history
takeEvery(ReduxFormActionTypes.VALUE_CHANGE, formValueChangeSaga),
takeEvery(ReduxFormActionTypes.ARRAY_PUSH, formValueChangeSaga),
takeEvery(ReduxFormActionTypes.ARRAY_REMOVE, formValueChangeSaga),
takeEvery(
ReduxActionTypes.FILE_PICKER_CALLBACK_ACTION,
filePickerActionCallbackSaga,
),
takeLatest(
ReduxActionTypes.FETCH_GSHEET_SPREADSHEETS,
fetchGsheetSpreadhsheets,
),
takeLatest(ReduxActionTypes.FETCH_GSHEET_SHEETS, fetchGsheetSheets),
takeLatest(ReduxActionTypes.FETCH_GSHEET_COLUMNS, fetchGsheetColumns),
takeEvery(ReduxActionTypes.LOAD_FILE_PICKER_ACTION, loadFilePickerSaga),
takeEvery(
ReduxActionTypes.UPDATE_DATASOURCE_AUTH_STATE,
updateDatasourceAuthStateSaga,
),
takeEvery(
ReduxActionTypes.DATASOURCE_DISCARD_ACTION,
datasourceDiscardActionSaga,
),
takeEvery(
ReduxActionTypes.ADD_AND_FETCH_MOCK_DATASOURCE_STRUCTURE_INIT,
addAndFetchDatasourceStructureSaga,
),
takeEvery(
ReduxActionTypes.FETCH_DATASOURCES_SUCCESS,
handleFetchDatasourceStructureOnLoad,
),
takeEvery(
ReduxActionTypes.SOFT_REFRESH_DATASOURCE_STRUCTURE,
handleFetchDatasourceStructureOnLoad,
),
takeEvery(
ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE,
setDatasourceViewModeSaga,
),
]);
}

View File

@ -15,6 +15,7 @@ export enum PluginType {
REMOTE = "REMOTE",
AI = "AI",
INTERNAL = "INTERNAL",
EXTERNAL_SAAS = "EXTERNAL_SAAS",
}
export enum PluginPackageName {
@ -260,13 +261,22 @@ export interface ActionViewMode {
timeoutInMillisecond?: number;
}
export interface ExternalSaasAction extends BaseAction {
pluginType: PluginType.EXTERNAL_SAAS;
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
actionConfiguration: any;
datasource: StoredDatasource;
}
export type Action =
| ApiAction
| QueryAction
| SaaSAction
| RemoteAction
| AIAction
| InternalAction;
| InternalAction
| ExternalSaasAction;
export enum SlashCommand {
NEW_API,

View File

@ -140,7 +140,7 @@ export enum DatasourceConnectionMode {
export interface DatasourceConfiguration {
url: string;
authentication?: DatasourceAuthentication;
authentication?: ExternalSaasDSAuthentication | DatasourceAuthentication;
properties?: Property[];
headers?: Property[];
queryParameters?: Property[];
@ -206,3 +206,13 @@ export enum DatasourceStructureContext {
// this does not exist yet, but in case it does in the future.
API_EDITOR = "api-editor",
}
export interface ExternalSaasDSAuthentication extends DatasourceAuthentication {
integrationId: string;
credentialId: string;
integrationType: string;
}
export enum AuthenticationType {
EXTERNAL_SAAS_AUTHENTICATION = "externalSaasAuth",
}

View File

@ -1,4 +1,4 @@
import type { BaseAction } from "../Action";
import type { BaseAction } from "../../entities/Action";
import type { PluginType } from "entities/Action";
import type { LayoutOnLoadActionErrors } from "constants/AppsmithActionConstants/ActionConstants";
import type { ActionParentEntityTypeInterface } from "ee/entities/Engine/actionHelpers";

View File

@ -20,6 +20,7 @@ export default class ActionPaneNavigationFactory {
case PluginType.DB:
case PluginType.SAAS:
case PluginType.REMOTE:
case PluginType.EXTERNAL_SAAS:
case PluginType.AI:
return new QueryPaneNavigation(entityInfo);
default:

View File

@ -250,7 +250,9 @@ function NewApiScreen(props: Props) {
const API_PLUGINS = plugins.filter((p) =>
!showSaasAPIs
? p.packageName === PluginPackageName.GRAPHQL
: p.type === PluginType.SAAS || p.type === PluginType.REMOTE,
: p.type === PluginType.SAAS ||
p.type === PluginType.REMOTE ||
p.type === PluginType.EXTERNAL_SAAS,
);
return (

View File

@ -18,7 +18,7 @@ import { toast } from "@appsmith/ads";
import type { LayoutSystemTypes } from "layoutSystems/types";
import { getLayoutSystemType } from "selectors/layoutSystemSelectors";
import type { Action, PluginPackageName } from "../entities/Action";
import { createOrUpdateDataSourceWithAction } from "./DatasourcesSagas";
import { createOrUpdateDataSourceWithAction } from "../ee/sagas/DatasourcesSagas";
function buildView(view: WidgetBlueprint["view"], widgetId: string) {
const children = [];

View File

@ -3,7 +3,7 @@ import userSagas from "ee/sagas/userSagas";
import workspaceSagas from "ee/sagas/WorkspaceSagas";
import { watchActionSagas } from "sagas/ActionSagas";
import layoutUpdateSagas from "sagas/AutoLayoutUpdateSagas";
import { watchDatasourcesSagas } from "sagas/DatasourcesSagas";
import { watchDatasourcesSagas } from "ee/sagas/DatasourcesSagas";
import { watchJSActionSagas } from "ee/sagas/JSActionSagas";
import apiPaneSagas from "../src/sagas/ApiPaneSagas";
import applicationSagas from "ee/sagas/ApplicationSagas";