This commit is contained in:
parent
a94c75b868
commit
c8a132f88d
|
|
@ -84,3 +84,7 @@ export const fetchPluginFormConfig = ({
|
||||||
export const fetchDefaultPlugins = (): ReduxActionWithoutPayload => ({
|
export const fetchDefaultPlugins = (): ReduxActionWithoutPayload => ({
|
||||||
type: ReduxActionTypes.GET_DEFAULT_PLUGINS_REQUEST,
|
type: ReduxActionTypes.GET_DEFAULT_PLUGINS_REQUEST,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const fetchUpcomingPlugins = (): ReduxActionWithoutPayload => ({
|
||||||
|
type: ReduxActionTypes.GET_UPCOMING_PLUGINS_REQUEST,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,12 @@ import type { AxiosPromise } from "axios";
|
||||||
import type { ApiResponse } from "api/ApiResponses";
|
import type { ApiResponse } from "api/ApiResponses";
|
||||||
import type { DependencyMap } from "utils/DynamicBindingUtils";
|
import type { DependencyMap } from "utils/DynamicBindingUtils";
|
||||||
import { FILE_UPLOAD_TRIGGER_TIMEOUT_MS } from "ee/constants/ApiConstants";
|
import { FILE_UPLOAD_TRIGGER_TIMEOUT_MS } from "ee/constants/ApiConstants";
|
||||||
import type { DefaultPlugin, Plugin } from "entities/Plugin";
|
import type {
|
||||||
|
DefaultPlugin,
|
||||||
|
Plugin,
|
||||||
|
UpcomingIntegration,
|
||||||
|
} from "entities/Plugin";
|
||||||
|
import { objectKeys } from "@appsmith/utils";
|
||||||
|
|
||||||
export interface PluginFormPayload {
|
export interface PluginFormPayload {
|
||||||
// TODO: Fix this the next time the file is edited
|
// TODO: Fix this the next time the file is edited
|
||||||
|
|
@ -55,6 +60,12 @@ class PluginsApi extends Api {
|
||||||
return Api.get(PluginsApi.url + `/default/icons`);
|
return Api.get(PluginsApi.url + `/default/icons`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async fetchUpcomingIntegrations(): Promise<
|
||||||
|
AxiosPromise<ApiResponse<UpcomingIntegration[]>>
|
||||||
|
> {
|
||||||
|
return Api.get(PluginsApi.url + "/upcoming-integrations");
|
||||||
|
}
|
||||||
|
|
||||||
static async uploadFiles(
|
static async uploadFiles(
|
||||||
pluginId: string,
|
pluginId: string,
|
||||||
files: File[],
|
files: File[],
|
||||||
|
|
@ -70,7 +81,7 @@ class PluginsApi extends Api {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (params) {
|
if (params) {
|
||||||
Object.keys(params).forEach((key) => {
|
objectKeys(params).forEach((key) => {
|
||||||
formData.append(key, params[key]);
|
formData.append(key, params[key]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
73
app/client/src/api/__tests__/PluginApi.test.ts
Normal file
73
app/client/src/api/__tests__/PluginApi.test.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
import PluginsApi from "api/PluginApi";
|
||||||
|
import Api from "api/Api";
|
||||||
|
import type { UpcomingIntegration } from "entities/Plugin";
|
||||||
|
|
||||||
|
// Mock the Api module with a class that can be extended
|
||||||
|
jest.mock("api/Api", () => {
|
||||||
|
return {
|
||||||
|
// Export a class that can be extended
|
||||||
|
__esModule: true,
|
||||||
|
default: class MockApi {
|
||||||
|
static get: jest.Mock = jest.fn();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("PluginsApi", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("fetchUpcomingIntegrations", () => {
|
||||||
|
it("should call the correct API endpoint", async () => {
|
||||||
|
// Setup mock API response
|
||||||
|
const mockResponse = {
|
||||||
|
data: {
|
||||||
|
responseMeta: {
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
name: "Test Integration",
|
||||||
|
iconLocation: "test-icon-location",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Another Test",
|
||||||
|
iconLocation: "another-test-icon",
|
||||||
|
},
|
||||||
|
] as UpcomingIntegration[],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
(Api.get as jest.Mock).mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
// Call the function
|
||||||
|
const result = await PluginsApi.fetchUpcomingIntegrations();
|
||||||
|
|
||||||
|
// Verify API was called correctly
|
||||||
|
expect(Api.get).toHaveBeenCalledWith(
|
||||||
|
PluginsApi.url + "/upcoming-integrations",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify response matches mock
|
||||||
|
expect(result).toEqual(mockResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle API errors", async () => {
|
||||||
|
// Setup mock API to throw error
|
||||||
|
const mockError = new Error("API error");
|
||||||
|
|
||||||
|
(Api.get as jest.Mock).mockRejectedValue(mockError);
|
||||||
|
|
||||||
|
// Call the function and expect it to throw
|
||||||
|
await expect(PluginsApi.fetchUpcomingIntegrations()).rejects.toThrow(
|
||||||
|
mockError,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify API was called
|
||||||
|
expect(Api.get).toHaveBeenCalledWith(
|
||||||
|
PluginsApi.url + "/upcoming-integrations",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -751,12 +751,15 @@ const PluginActionTypes = {
|
||||||
GET_PLUGIN_FORM_CONFIG_INIT: "GET_PLUGIN_FORM_CONFIG_INIT",
|
GET_PLUGIN_FORM_CONFIG_INIT: "GET_PLUGIN_FORM_CONFIG_INIT",
|
||||||
GET_DEFAULT_PLUGINS_REQUEST: "GET_DEFAULT_PLUGINS_REQUEST",
|
GET_DEFAULT_PLUGINS_REQUEST: "GET_DEFAULT_PLUGINS_REQUEST",
|
||||||
GET_DEFAULT_PLUGINS_SUCCESS: "GET_DEFAULT_PLUGINS_SUCCESS",
|
GET_DEFAULT_PLUGINS_SUCCESS: "GET_DEFAULT_PLUGINS_SUCCESS",
|
||||||
|
GET_UPCOMING_PLUGINS_REQUEST: "GET_UPCOMING_PLUGINS_REQUEST",
|
||||||
|
GET_UPCOMING_PLUGINS_SUCCESS: "GET_UPCOMING_PLUGINS_SUCCESS",
|
||||||
};
|
};
|
||||||
const PluginActionErrorTypes = {
|
const PluginActionErrorTypes = {
|
||||||
FETCH_PLUGINS_ERROR: "FETCH_PLUGINS_ERROR",
|
FETCH_PLUGINS_ERROR: "FETCH_PLUGINS_ERROR",
|
||||||
FETCH_PLUGIN_FORM_CONFIGS_ERROR: "FETCH_PLUGIN_FORM_CONFIGS_ERROR",
|
FETCH_PLUGIN_FORM_CONFIGS_ERROR: "FETCH_PLUGIN_FORM_CONFIGS_ERROR",
|
||||||
FETCH_PLUGIN_FORM_ERROR: "FETCH_PLUGIN_FORM_ERROR",
|
FETCH_PLUGIN_FORM_ERROR: "FETCH_PLUGIN_FORM_ERROR",
|
||||||
GET_DEFAULT_PLUGINS_ERROR: "GET_DEFAULT_PLUGINS_ERROR",
|
GET_DEFAULT_PLUGINS_ERROR: "GET_DEFAULT_PLUGINS_ERROR",
|
||||||
|
GET_UPCOMING_PLUGINS_ERROR: "GET_UPCOMING_PLUGINS_ERROR",
|
||||||
};
|
};
|
||||||
|
|
||||||
const UQIFormActionTypes = {
|
const UQIFormActionTypes = {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import type { ExplorerURLParams } from "ee/pages/Editor/Explorer/helpers";
|
||||||
import type { DependentFeatureFlags } from "ee/selectors/engineSelectors";
|
import type { DependentFeatureFlags } from "ee/selectors/engineSelectors";
|
||||||
import { fetchDatasources } from "actions/datasourceActions";
|
import { fetchDatasources } from "actions/datasourceActions";
|
||||||
import { fetchPageDSLs } from "actions/pageActions";
|
import { fetchPageDSLs } from "actions/pageActions";
|
||||||
import { fetchPlugins } from "actions/pluginActions";
|
import { fetchPlugins, fetchUpcomingPlugins } from "actions/pluginActions";
|
||||||
import type { Plugin } from "entities/Plugin";
|
import type { Plugin } from "entities/Plugin";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useParams } from "react-router";
|
import { useParams } from "react-router";
|
||||||
|
|
@ -37,6 +37,7 @@ export const getPageDependencyActions = (
|
||||||
fetchPlugins({ plugins }),
|
fetchPlugins({ plugins }),
|
||||||
fetchDatasources({ datasources }),
|
fetchDatasources({ datasources }),
|
||||||
fetchPageDSLs({ pagesWithMigratedDsl }),
|
fetchPageDSLs({ pagesWithMigratedDsl }),
|
||||||
|
fetchUpcomingPlugins(), // Not adding success and error actions for this as it's not a blocker for the app to load
|
||||||
] as Array<ReduxAction<unknown>>;
|
] as Array<ReduxAction<unknown>>;
|
||||||
|
|
||||||
const successActions = [
|
const successActions = [
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@ const defaultStoreState = {
|
||||||
...unitTestBaseMockStore.entities,
|
...unitTestBaseMockStore.entities,
|
||||||
plugins: {
|
plugins: {
|
||||||
list: [],
|
list: [],
|
||||||
|
upcomingPlugins: {
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
datasources: {
|
datasources: {
|
||||||
list: [],
|
list: [],
|
||||||
|
|
|
||||||
|
|
@ -1799,3 +1799,8 @@ export const getJSCollectionActionSchemaDirtyState = createSelector(
|
||||||
return action.isDirtyMap?.SCHEMA_GENERATION;
|
return action.isDirtyMap?.SCHEMA_GENERATION;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getUpcomingPlugins = createSelector(
|
||||||
|
(state: AppState) => state.entities.plugins.upcomingPlugins,
|
||||||
|
(upcomingPlugins) => upcomingPlugins.list,
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -91,3 +91,8 @@ export interface DefaultPlugin {
|
||||||
iconLocation?: string;
|
iconLocation?: string;
|
||||||
allowUserDatasources?: boolean;
|
allowUserDatasources?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpcomingIntegration {
|
||||||
|
name: string;
|
||||||
|
iconLocation: string;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,13 @@ import {
|
||||||
type Plugin,
|
type Plugin,
|
||||||
PluginPackageName,
|
PluginPackageName,
|
||||||
PluginType,
|
PluginType,
|
||||||
|
type UpcomingIntegration,
|
||||||
} from "entities/Plugin";
|
} from "entities/Plugin";
|
||||||
import { getQueryParams } from "utils/URLUtils";
|
import { getQueryParams } from "utils/URLUtils";
|
||||||
import {
|
import {
|
||||||
getGenerateCRUDEnabledPluginMap,
|
getGenerateCRUDEnabledPluginMap,
|
||||||
getPlugins,
|
getPlugins,
|
||||||
|
getUpcomingPlugins,
|
||||||
} from "ee/selectors/entitiesSelector";
|
} from "ee/selectors/entitiesSelector";
|
||||||
import { getIsGeneratePageInitiator } from "utils/GenerateCrudUtil";
|
import { getIsGeneratePageInitiator } from "utils/GenerateCrudUtil";
|
||||||
import { getAssetUrl, isAirgapped } from "ee/utils/airgapHelpers";
|
import { getAssetUrl, isAirgapped } from "ee/utils/airgapHelpers";
|
||||||
|
|
@ -43,10 +45,7 @@ import {
|
||||||
import scrollIntoView from "scroll-into-view-if-needed";
|
import scrollIntoView from "scroll-into-view-if-needed";
|
||||||
import PremiumDatasources from "./PremiumDatasources";
|
import PremiumDatasources from "./PremiumDatasources";
|
||||||
import { pluginSearchSelector } from "./CreateNewDatasourceHeader";
|
import { pluginSearchSelector } from "./CreateNewDatasourceHeader";
|
||||||
import {
|
import { getFilteredUpcomingIntegrations } from "./PremiumDatasources/Constants";
|
||||||
getFilteredPremiumIntegrations,
|
|
||||||
type PremiumIntegration,
|
|
||||||
} from "./PremiumDatasources/Constants";
|
|
||||||
import { getDatasourcesLoadingState } from "selectors/datasourceSelectors";
|
import { getDatasourcesLoadingState } from "selectors/datasourceSelectors";
|
||||||
import { getIDETypeByUrl } from "ee/entities/IDE/utils";
|
import { getIDETypeByUrl } from "ee/entities/IDE/utils";
|
||||||
import type { IDEType } from "ee/IDE/Interfaces/IDETypes";
|
import type { IDEType } from "ee/IDE/Interfaces/IDETypes";
|
||||||
|
|
@ -75,7 +74,7 @@ interface CreateAPIOrSaasPluginsProps {
|
||||||
apiType: string,
|
apiType: string,
|
||||||
) => void;
|
) => void;
|
||||||
isPremiumDatasourcesViewEnabled?: boolean;
|
isPremiumDatasourcesViewEnabled?: boolean;
|
||||||
premiumPlugins: PremiumIntegration[];
|
upcomingIntegrations: UpcomingIntegration[];
|
||||||
authApiPlugin?: Plugin;
|
authApiPlugin?: Plugin;
|
||||||
restAPIVisible?: boolean;
|
restAPIVisible?: boolean;
|
||||||
graphQLAPIVisible?: boolean;
|
graphQLAPIVisible?: boolean;
|
||||||
|
|
@ -235,7 +234,7 @@ function APIOrSaasPlugins(props: CreateAPIOrSaasPluginsProps) {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{!props.isIntegrationsEnabledForPaid && (
|
{!props.isIntegrationsEnabledForPaid && (
|
||||||
<PremiumDatasources plugins={props.premiumPlugins} />
|
<PremiumDatasources plugins={props.upcomingIntegrations} />
|
||||||
)}
|
)}
|
||||||
</DatasourceContainer>
|
</DatasourceContainer>
|
||||||
);
|
);
|
||||||
|
|
@ -263,7 +262,7 @@ function CreateAPIOrSaasPlugins(props: CreateAPIOrSaasPluginsProps) {
|
||||||
if (isAirgappedInstance && props.showSaasAPIs) return null;
|
if (isAirgappedInstance && props.showSaasAPIs) return null;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
props.premiumPlugins.length === 0 &&
|
props.upcomingIntegrations.length === 0 &&
|
||||||
props.plugins.length === 0 &&
|
props.plugins.length === 0 &&
|
||||||
!props.restAPIVisible &&
|
!props.restAPIVisible &&
|
||||||
!props.graphQLAPIVisible
|
!props.graphQLAPIVisible
|
||||||
|
|
@ -281,7 +280,8 @@ function CreateAPIOrSaasPlugins(props: CreateAPIOrSaasPluginsProps) {
|
||||||
</DatasourceSectionHeading>
|
</DatasourceSectionHeading>
|
||||||
<APIOrSaasPlugins {...props} />
|
<APIOrSaasPlugins {...props} />
|
||||||
</DatasourceSection>
|
</DatasourceSection>
|
||||||
{props.premiumPlugins.length > 0 && props.isIntegrationsEnabledForPaid ? (
|
{props.upcomingIntegrations.length > 0 &&
|
||||||
|
props.isIntegrationsEnabledForPaid ? (
|
||||||
<DatasourceSection id="upcoming-saas-integrations">
|
<DatasourceSection id="upcoming-saas-integrations">
|
||||||
<DatasourceSectionHeading kind="heading-m">
|
<DatasourceSectionHeading kind="heading-m">
|
||||||
{createMessage(UPCOMING_SAAS_INTEGRATIONS)}
|
{createMessage(UPCOMING_SAAS_INTEGRATIONS)}
|
||||||
|
|
@ -289,7 +289,7 @@ function CreateAPIOrSaasPlugins(props: CreateAPIOrSaasPluginsProps) {
|
||||||
<DatasourceContainer data-testid="upcoming-datasource-card-container">
|
<DatasourceContainer data-testid="upcoming-datasource-card-container">
|
||||||
<PremiumDatasources
|
<PremiumDatasources
|
||||||
isIntegrationsEnabledForPaid
|
isIntegrationsEnabledForPaid
|
||||||
plugins={props.premiumPlugins}
|
plugins={props.upcomingIntegrations}
|
||||||
/>
|
/>
|
||||||
</DatasourceContainer>
|
</DatasourceContainer>
|
||||||
</DatasourceSection>
|
</DatasourceSection>
|
||||||
|
|
@ -310,6 +310,8 @@ const mapStateToProps = (
|
||||||
pluginSearchSelector(state, "search") || ""
|
pluginSearchSelector(state, "search") || ""
|
||||||
).toLocaleLowerCase();
|
).toLocaleLowerCase();
|
||||||
|
|
||||||
|
const upcomingPlugins = getUpcomingPlugins(state);
|
||||||
|
|
||||||
const allPlugins = getPlugins(state);
|
const allPlugins = getPlugins(state);
|
||||||
|
|
||||||
let plugins = allPlugins.filter((p) =>
|
let plugins = allPlugins.filter((p) =>
|
||||||
|
|
@ -354,15 +356,16 @@ const mapStateToProps = (
|
||||||
plugin.name.toLocaleLowerCase(),
|
plugin.name.toLocaleLowerCase(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const premiumPlugins =
|
const upcomingIntegrations =
|
||||||
props.showSaasAPIs && props.isPremiumDatasourcesViewEnabled
|
props.showSaasAPIs && props.isPremiumDatasourcesViewEnabled
|
||||||
? (filterSearch(
|
? (filterSearch(
|
||||||
getFilteredPremiumIntegrations(
|
getFilteredUpcomingIntegrations(
|
||||||
isExternalSaasEnabled || isIntegrationsEnabledForPaid,
|
isExternalSaasEnabled || isIntegrationsEnabledForPaid,
|
||||||
pluginNames,
|
pluginNames,
|
||||||
|
upcomingPlugins,
|
||||||
),
|
),
|
||||||
searchedPlugin,
|
searchedPlugin,
|
||||||
) as PremiumIntegration[])
|
) as UpcomingIntegration[])
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const restAPIVisible =
|
const restAPIVisible =
|
||||||
|
|
@ -380,7 +383,7 @@ const mapStateToProps = (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plugins,
|
plugins,
|
||||||
premiumPlugins,
|
upcomingIntegrations,
|
||||||
authApiPlugin,
|
authApiPlugin,
|
||||||
restAPIVisible,
|
restAPIVisible,
|
||||||
graphQLAPIVisible,
|
graphQLAPIVisible,
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import {
|
||||||
} from "ee/constants/messages";
|
} from "ee/constants/messages";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { pluginSearchSelector } from "./CreateNewDatasourceHeader";
|
import { pluginSearchSelector } from "./CreateNewDatasourceHeader";
|
||||||
import { getPlugins } from "ee/selectors/entitiesSelector";
|
import { getPlugins, getUpcomingPlugins } from "ee/selectors/entitiesSelector";
|
||||||
import { getFilteredPremiumIntegrations } from "./PremiumDatasources/Constants";
|
import { getFilteredUpcomingIntegrations } from "./PremiumDatasources/Constants";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { filterSearch } from "./util";
|
import { filterSearch } from "./util";
|
||||||
import type { MockDatasource } from "entities/Datasource";
|
import type { MockDatasource } from "entities/Datasource";
|
||||||
|
|
@ -34,6 +34,8 @@ export default function EmptySearchedPlugins({
|
||||||
pluginSearchSelector(state, "search"),
|
pluginSearchSelector(state, "search"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const upcomingPlugins = useSelector(getUpcomingPlugins);
|
||||||
|
|
||||||
searchedPlugin = (searchedPlugin || "").toLocaleLowerCase();
|
searchedPlugin = (searchedPlugin || "").toLocaleLowerCase();
|
||||||
const plugins = useSelector(getPlugins);
|
const plugins = useSelector(getPlugins);
|
||||||
|
|
||||||
|
|
@ -59,9 +61,10 @@ export default function EmptySearchedPlugins({
|
||||||
{ name: createMessage(CREATE_NEW_DATASOURCE_AUTHENTICATED_REST_API) },
|
{ name: createMessage(CREATE_NEW_DATASOURCE_AUTHENTICATED_REST_API) },
|
||||||
...mockDatasources,
|
...mockDatasources,
|
||||||
...(isPremiumDatasourcesViewEnabled
|
...(isPremiumDatasourcesViewEnabled
|
||||||
? getFilteredPremiumIntegrations(
|
? getFilteredUpcomingIntegrations(
|
||||||
isExternalSaasEnabled || isIntegrationsEnabledForPaid,
|
isExternalSaasEnabled || isIntegrationsEnabledForPaid,
|
||||||
pluginNames,
|
pluginNames,
|
||||||
|
upcomingPlugins,
|
||||||
)
|
)
|
||||||
: []),
|
: []),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,24 @@
|
||||||
import { getAssetUrl } from "ee/utils/airgapHelpers";
|
import type { UpcomingIntegration } from "entities/Plugin";
|
||||||
import { ASSETS_CDN_URL } from "../../../../constants/ThirdPartyConstants";
|
|
||||||
|
|
||||||
export interface PremiumIntegration {
|
/**
|
||||||
name: string;
|
* Filters upcoming integrations based on available plugins.
|
||||||
icon: string;
|
* Returns cached integrations synchronously.
|
||||||
}
|
*
|
||||||
|
* @param isExternalSaasEnabled Whether external SaaS integrations are enabled
|
||||||
const PREMIUM_INTEGRATIONS: PremiumIntegration[] = [
|
* @param pluginNames List of installed plugin names (lowercase)
|
||||||
{
|
* @returns Filtered list of upcoming integrations
|
||||||
name: "Zendesk",
|
*/
|
||||||
icon: getAssetUrl(`${ASSETS_CDN_URL}/zendesk-icon.png`),
|
export const getFilteredUpcomingIntegrations = (
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Salesforce",
|
|
||||||
icon: getAssetUrl(`${ASSETS_CDN_URL}/salesforce-image.png`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Slack",
|
|
||||||
icon: getAssetUrl(`${ASSETS_CDN_URL}/slack.png`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Jira",
|
|
||||||
icon: getAssetUrl(`${ASSETS_CDN_URL}/jira.png`),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const getFilteredPremiumIntegrations = (
|
|
||||||
isExternalSaasEnabled: boolean,
|
isExternalSaasEnabled: boolean,
|
||||||
pluginNames: string[],
|
pluginNames: string[],
|
||||||
) => {
|
upcomingPlugins: UpcomingIntegration[],
|
||||||
|
): UpcomingIntegration[] => {
|
||||||
return isExternalSaasEnabled
|
return isExternalSaasEnabled
|
||||||
? PREMIUM_INTEGRATIONS.filter(
|
? upcomingPlugins.filter(
|
||||||
(integration) =>
|
(integration) =>
|
||||||
!pluginNames.includes(integration.name.toLocaleLowerCase()),
|
!pluginNames.includes(integration.name.toLocaleLowerCase()),
|
||||||
)
|
)
|
||||||
: PREMIUM_INTEGRATIONS;
|
: upcomingPlugins;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PREMIUM_INTEGRATION_CONTACT_FORM =
|
export const PREMIUM_INTEGRATION_CONTACT_FORM =
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import styled from "styled-components";
|
||||||
import ContactForm from "./ContactForm";
|
import ContactForm from "./ContactForm";
|
||||||
import { handlePremiumDatasourceClick } from "./Helpers";
|
import { handlePremiumDatasourceClick } from "./Helpers";
|
||||||
import DatasourceItem from "../DatasourceItem";
|
import DatasourceItem from "../DatasourceItem";
|
||||||
import type { PremiumIntegration } from "./Constants";
|
|
||||||
import { createMessage } from "ee/constants/messages";
|
import { createMessage } from "ee/constants/messages";
|
||||||
import { PREMIUM_DATASOURCES } from "ee/constants/messages";
|
import { PREMIUM_DATASOURCES } from "ee/constants/messages";
|
||||||
|
import type { UpcomingIntegration } from "entities/Plugin";
|
||||||
|
|
||||||
const ModalContentWrapper = styled(ModalContent)`
|
const ModalContentWrapper = styled(ModalContent)`
|
||||||
max-width: 518px;
|
max-width: 518px;
|
||||||
|
|
@ -26,7 +26,7 @@ const PremiumTag = styled(Tag)`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default function PremiumDatasources(props: {
|
export default function PremiumDatasources(props: {
|
||||||
plugins: PremiumIntegration[];
|
plugins: UpcomingIntegration[];
|
||||||
isIntegrationsEnabledForPaid?: boolean;
|
isIntegrationsEnabledForPaid?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const [selectedIntegration, setSelectedIntegration] = useState<string>("");
|
const [selectedIntegration, setSelectedIntegration] = useState<string>("");
|
||||||
|
|
@ -49,7 +49,7 @@ export default function PremiumDatasources(props: {
|
||||||
handleOnClick={() => {
|
handleOnClick={() => {
|
||||||
handleOnClick(integration.name);
|
handleOnClick(integration.name);
|
||||||
}}
|
}}
|
||||||
icon={getAssetUrl(integration.icon)}
|
icon={getAssetUrl(integration.iconLocation)}
|
||||||
key={integration.name}
|
key={integration.name}
|
||||||
name={integration.name}
|
name={integration.name}
|
||||||
rightSibling={
|
rightSibling={
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,11 @@ import {
|
||||||
ReduxActionTypes,
|
ReduxActionTypes,
|
||||||
ReduxActionErrorTypes,
|
ReduxActionErrorTypes,
|
||||||
} from "ee/constants/ReduxActionConstants";
|
} from "ee/constants/ReduxActionConstants";
|
||||||
import type { DefaultPlugin, Plugin } from "entities/Plugin";
|
import type {
|
||||||
|
DefaultPlugin,
|
||||||
|
Plugin,
|
||||||
|
UpcomingIntegration,
|
||||||
|
} from "entities/Plugin";
|
||||||
import type {
|
import type {
|
||||||
PluginFormPayloadWithId,
|
PluginFormPayloadWithId,
|
||||||
PluginFormsPayload,
|
PluginFormsPayload,
|
||||||
|
|
@ -30,6 +34,10 @@ export interface PluginDataState {
|
||||||
datasourceFormButtonConfigs: FormDatasourceButtonConfigs;
|
datasourceFormButtonConfigs: FormDatasourceButtonConfigs;
|
||||||
fetchingSinglePluginForm: Record<string, boolean>;
|
fetchingSinglePluginForm: Record<string, boolean>;
|
||||||
fetchingDefaultPlugins: boolean;
|
fetchingDefaultPlugins: boolean;
|
||||||
|
upcomingPlugins: {
|
||||||
|
list: UpcomingIntegration[];
|
||||||
|
loading: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: PluginDataState = {
|
const initialState: PluginDataState = {
|
||||||
|
|
@ -43,6 +51,10 @@ const initialState: PluginDataState = {
|
||||||
dependencies: {},
|
dependencies: {},
|
||||||
fetchingSinglePluginForm: {},
|
fetchingSinglePluginForm: {},
|
||||||
fetchingDefaultPlugins: false,
|
fetchingDefaultPlugins: false,
|
||||||
|
upcomingPlugins: {
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const pluginsReducer = createReducer(initialState, {
|
const pluginsReducer = createReducer(initialState, {
|
||||||
|
|
@ -142,6 +154,33 @@ const pluginsReducer = createReducer(initialState, {
|
||||||
defaultPluginList: action.payload,
|
defaultPluginList: action.payload,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
[ReduxActionTypes.GET_UPCOMING_PLUGINS_REQUEST]: (state: PluginDataState) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
upcomingPlugins: { ...state.upcomingPlugins, loading: true },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[ReduxActionTypes.GET_UPCOMING_PLUGINS_SUCCESS]: (
|
||||||
|
state: PluginDataState,
|
||||||
|
action: ReduxAction<UpcomingIntegration[]>,
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
upcomingPlugins: {
|
||||||
|
...state.upcomingPlugins,
|
||||||
|
loading: false,
|
||||||
|
list: action.payload,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[ReduxActionErrorTypes.GET_UPCOMING_PLUGINS_ERROR]: (
|
||||||
|
state: PluginDataState,
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
upcomingPlugins: { ...state.upcomingPlugins, loading: false },
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default pluginsReducer;
|
export default pluginsReducer;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,12 @@ import type { ApiResponse } from "api/ApiResponses";
|
||||||
import PluginApi from "api/PluginApi";
|
import PluginApi from "api/PluginApi";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import { getAppsmithAIPlugin, getGraphQLPlugin } from "entities/Action";
|
import { getAppsmithAIPlugin, getGraphQLPlugin } from "entities/Action";
|
||||||
import { type DefaultPlugin, type Plugin, PluginType } from "entities/Plugin";
|
import {
|
||||||
|
type DefaultPlugin,
|
||||||
|
type Plugin,
|
||||||
|
PluginType,
|
||||||
|
type UpcomingIntegration,
|
||||||
|
} from "entities/Plugin";
|
||||||
import type {
|
import type {
|
||||||
FormEditorConfigs,
|
FormEditorConfigs,
|
||||||
FormSettingsConfigs,
|
FormSettingsConfigs,
|
||||||
|
|
@ -305,6 +310,24 @@ function* getDefaultPluginsSaga() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* getUpcomingPluginsSaga() {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse<UpcomingIntegration[]> = yield call(
|
||||||
|
PluginsApi.fetchUpcomingIntegrations,
|
||||||
|
);
|
||||||
|
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionTypes.GET_UPCOMING_PLUGINS_SUCCESS,
|
||||||
|
payload: response.data || [],
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionErrorTypes.GET_UPCOMING_PLUGINS_ERROR,
|
||||||
|
payload: { error },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function* root() {
|
function* root() {
|
||||||
yield all([
|
yield all([
|
||||||
takeEvery(ReduxActionTypes.FETCH_PLUGINS_REQUEST, fetchPluginsSaga),
|
takeEvery(ReduxActionTypes.FETCH_PLUGINS_REQUEST, fetchPluginsSaga),
|
||||||
|
|
@ -320,6 +343,10 @@ function* root() {
|
||||||
ReduxActionTypes.GET_DEFAULT_PLUGINS_REQUEST,
|
ReduxActionTypes.GET_DEFAULT_PLUGINS_REQUEST,
|
||||||
getDefaultPluginsSaga,
|
getDefaultPluginsSaga,
|
||||||
),
|
),
|
||||||
|
takeEvery(
|
||||||
|
ReduxActionTypes.GET_UPCOMING_PLUGINS_REQUEST,
|
||||||
|
getUpcomingPluginsSaga,
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user