Skip to content

Commit

Permalink
Merge pull request #36337 from appsmithorg/release
Browse files Browse the repository at this point in the history
16/09 Daily Promotion
  • Loading branch information
btsgh authored Sep 16, 2024
2 parents 7c9dfc0 + 71261b1 commit d52aa53
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 53 deletions.
2 changes: 1 addition & 1 deletion app/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@
"node-forge": "^1.3.0",
"normalizr": "^3.3.0",
"object-hash": "^3.0.0",
"path-to-regexp": "^6.2.0",
"path-to-regexp": "^6.3.0",
"popper.js": "^1.15.0",
"prismjs": "^1.27.0",
"proxy-memoize": "^1.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from "react";
import React, { useCallback } from "react";
import { IDEToolbar } from "IDE";
import { Button, Menu, MenuContent, MenuTrigger, Tooltip } from "@appsmith/ads";
import { modText } from "utils/helpers";
import { usePluginActionContext } from "../PluginActionContext";
import { useDispatch } from "react-redux";
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
import { runAction } from "../../actions/pluginActionActions";

interface PluginActionToolbarProps {
runOptions?: React.ReactNode;
Expand All @@ -10,6 +14,25 @@ interface PluginActionToolbarProps {
}

const PluginActionToolbar = (props: PluginActionToolbarProps) => {
const { action, datasource, plugin } = usePluginActionContext();
const dispatch = useDispatch();
const handleRunClick = useCallback(() => {
AnalyticsUtil.logEvent("RUN_QUERY_CLICK", {
actionName: action.name,
actionId: action.id,
pluginName: plugin.name,
datasourceId: datasource?.id,
isMock: datasource?.isMock,
});
dispatch(runAction(action.id));
}, [
action.id,
action.name,
datasource?.id,
datasource?.isMock,
dispatch,
plugin.name,
]);
return (
<IDEToolbar>
<IDEToolbar.Left>{props.children}</IDEToolbar.Left>
Expand All @@ -20,7 +43,7 @@ const PluginActionToolbar = (props: PluginActionToolbarProps) => {
placement="topRight"
showArrow={false}
>
<Button kind="primary" size="sm">
<Button kind="primary" onClick={handleRunClick} size="sm">
Run
</Button>
</Tooltip>
Expand All @@ -30,7 +53,7 @@ const PluginActionToolbar = (props: PluginActionToolbarProps) => {
size="sm"
startIcon="settings-2-line"
/>
<Menu>
<Menu key={action.id}>
<MenuTrigger>
<Button
isIconButton
Expand All @@ -39,7 +62,12 @@ const PluginActionToolbar = (props: PluginActionToolbarProps) => {
startIcon="more-2-fill"
/>
</MenuTrigger>
<MenuContent loop style={{ zIndex: 100 }} width="200px">
<MenuContent
key={action.id}
loop
style={{ zIndex: 100 }}
width="200px"
>
{props.menuContent}
</MenuContent>
</Menu>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react";
import { PluginActionToolbar } from "PluginActionEditor";
import { ConvertToModuleCTA } from "./ConvertToModule";
import AppPluginActionMenu from "./PluginActionMoreActions";

const AppPluginActionToolbar = () => {
return <PluginActionToolbar menuContent={<ConvertToModuleCTA />} />;
return <PluginActionToolbar menuContent={<AppPluginActionMenu />} />;
};

export default AppPluginActionToolbar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import React, { useCallback, useMemo, useState } from "react";
import {
getHasDeleteActionPermission,
getHasManageActionPermission,
} from "ee/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import { usePluginActionContext } from "PluginActionEditor";
import {
MenuItem,
MenuSub,
MenuSubContent,
MenuSubTrigger,
} from "@appsmith/ads";
import {
CONFIRM_CONTEXT_DELETE,
CONTEXT_COPY,
CONTEXT_DELETE,
CONTEXT_MOVE,
createMessage,
} from "ee/constants/messages";
import { useDispatch, useSelector } from "react-redux";
import {
copyActionRequest,
deleteAction,
moveActionRequest,
} from "actions/pluginActionActions";
import { getCurrentPageId } from "selectors/editorSelectors";
import type { Page } from "entities/Page";
import { getPageList } from "ee/selectors/entitiesSelector";
import { ConvertToModuleCTA } from "./ConvertToModule";

const PageMenuItem = (props: {
page: Page;
onSelect: (id: string) => void;
}) => {
const handleOnSelect = useCallback(() => {
props.onSelect(props.page.pageId);
}, [props]);
return <MenuItem onSelect={handleOnSelect}>{props.page.pageName}</MenuItem>;
};

const Copy = () => {
const menuPages = useSelector(getPageList);
const { action } = usePluginActionContext();
const dispatch = useDispatch();

const copyActionToPage = useCallback(
(pageId: string) =>
dispatch(
copyActionRequest({
id: action.id,
destinationPageId: pageId,
name: action.name,
}),
),
[action.id, action.name, dispatch],
);

return (
<MenuSub>
<MenuSubTrigger startIcon="duplicate">
{createMessage(CONTEXT_COPY)}
</MenuSubTrigger>
<MenuSubContent>
{menuPages.map((page) => {
return (
<PageMenuItem
key={page.basePageId}
onSelect={copyActionToPage}
page={page}
/>
);
})}
</MenuSubContent>
</MenuSub>
);
};

const Move = () => {
const dispatch = useDispatch();
const { action } = usePluginActionContext();

const currentPageId = useSelector(getCurrentPageId);
const allPages = useSelector(getPageList);
const menuPages = useMemo(() => {
return allPages.filter((page) => page.pageId !== currentPageId);
}, [allPages, currentPageId]);

const moveActionToPage = useCallback(
(destinationPageId: string) =>
dispatch(
moveActionRequest({
id: action.id,
destinationPageId,
originalPageId: currentPageId,
name: action.name,
}),
),
[dispatch, action.id, action.name, currentPageId],
);

return (
<MenuSub>
<MenuSubTrigger startIcon="swap-horizontal">
{createMessage(CONTEXT_MOVE)}
</MenuSubTrigger>
<MenuSubContent>
{menuPages.length > 1 ? (
menuPages.map((page) => {
return (
<PageMenuItem
key={page.basePageId}
onSelect={moveActionToPage}
page={page}
/>
);
})
) : (
<MenuItem key="no-pages">No pages</MenuItem>
)}
</MenuSubContent>
</MenuSub>
);
};

const Delete = () => {
const dispatch = useDispatch();
const { action } = usePluginActionContext();

const [confirmDelete, setConfirmDelete] = useState(false);

const deleteActionFromPage = useCallback(() => {
dispatch(deleteAction({ id: action.id, name: action.name }));
}, [action.id, action.name, dispatch]);

const handleSelect = useCallback(() => {
confirmDelete ? deleteActionFromPage() : setConfirmDelete(true);
}, [confirmDelete, deleteActionFromPage]);

const menuLabel = confirmDelete
? createMessage(CONFIRM_CONTEXT_DELETE)
: createMessage(CONTEXT_DELETE);

return (
<MenuItem
className="t--apiFormDeleteBtn error-menuitem"
onSelect={handleSelect}
startIcon="trash"
>
{menuLabel}
</MenuItem>
);
};

const AppPluginActionMenu = () => {
const { action } = usePluginActionContext();

const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
const isChangePermitted = getHasManageActionPermission(
isFeatureEnabled,
action.userPermissions,
);
const isDeletePermitted = getHasDeleteActionPermission(
isFeatureEnabled,
action?.userPermissions,
);

return (
<>
<ConvertToModuleCTA />
{isChangePermitted && (
<>
<Copy />
<Move />
</>
)}
{isDeletePermitted && <Delete />}
</>
);
};

export default AppPluginActionMenu;
10 changes: 5 additions & 5 deletions app/client/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13391,7 +13391,7 @@ __metadata:
node-forge: ^1.3.0
normalizr: ^3.3.0
object-hash: ^3.0.0
path-to-regexp: ^6.2.0
path-to-regexp: ^6.3.0
pg: ^8.11.3
plop: ^3.1.1
popper.js: ^1.15.0
Expand Down Expand Up @@ -27112,10 +27112,10 @@ __metadata:
languageName: node
linkType: hard

"path-to-regexp@npm:^6.2.0":
version: 6.2.0
resolution: "path-to-regexp@npm:6.2.0"
checksum: a6aca74d2d6e2e7594d812f653cf85e9cb5054d3a8d80f099722a44ef6ad22639b02078e5ea83d11db16321c3e4359e3f1ab0274fa78dad0754a6e53f630b0fc
"path-to-regexp@npm:^6.3.0":
version: 6.3.0
resolution: "path-to-regexp@npm:6.3.0"
checksum: eca78602e6434a1b6799d511d375ec044e8d7e28f5a48aa5c28d57d8152fb52f3fc62fb1cfc5dfa2198e1f041c2a82ed14043d75740a2fe60e91b5089a153250
languageName: node
linkType: hard

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ public class DatasourceConfiguration implements AppsmithDomain {
@JsonView({Views.Public.class, FromRequest.class})
AuthenticationDTO authentication;

@JsonView({Views.Public.class, FromRequest.class})
SSHConnection sshProxy;

@JsonView({Views.Public.class, FromRequest.class})
Boolean sshProxyEnabled;

@JsonView({Views.Public.class, FromRequest.class, Git.class})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,28 +67,38 @@ public Mono<ApplicationJson> migrateApplicationJsonToLatestSchema(
// TODO: make import flow migration reactive
return Mono.just(migrateServerSchema(appJson))
.flatMap(migratedApplicationJson -> {
if (migratedApplicationJson.getServerSchemaVersion() == 9
&& Boolean.TRUE.equals(MigrationHelperMethods.doesRestApiRequireMigration(
migratedApplicationJson))) {
return jsonSchemaMigrationHelper
.addDatasourceConfigurationToDefaultRestApiActions(
baseApplicationId, branchName, migratedApplicationJson)
.map(applicationJsonWithMigration10 -> {
applicationJsonWithMigration10.setServerSchemaVersion(10);
return applicationJsonWithMigration10;
});
// In Server version 9, there was a bug where the Embedded REST API datasource URL
// was not being persisted correctly. Once the bug was fixed,
// any previously uncommitted changes started appearing as uncommitted modifications
// in the apps. To automatically commit these changes
// (which were now appearing as uncommitted), a migration process was needed.
// This migration fetches the datasource URL from the database
// and serializes it in Git if the URL exists.
// If the URL is missing, it copies the empty datasource configuration
// if the configuration is present in the database.
// Otherwise, it leaves the configuration unchanged.
// Due to an update in the migration logic after version 10 was shipped,
// the entire migration process was moved to version 11.
// This adjustment ensures that the same operation can be
// performed again for the changes introduced in version 10.
if (migratedApplicationJson.getServerSchemaVersion() == 9) {
migratedApplicationJson.setServerSchemaVersion(10);
}

if (migratedApplicationJson.getServerSchemaVersion() == 10) {
if (Boolean.TRUE.equals(MigrationHelperMethods.doesRestApiRequireMigration(
migratedApplicationJson))) {
return jsonSchemaMigrationHelper
.addDatasourceConfigurationToDefaultRestApiActions(
baseApplicationId, branchName, migratedApplicationJson);
}

migratedApplicationJson.setServerSchemaVersion(11);
}

migratedApplicationJson.setServerSchemaVersion(10);
return Mono.just(migratedApplicationJson);
})
.map(migratedAppJson -> {
if (applicationJson
.getServerSchemaVersion()
.equals(jsonSchemaVersions.getServerVersion())) {
return applicationJson;
}

applicationJson.setServerSchemaVersion(jsonSchemaVersions.getServerVersion());
return applicationJson;
});
Expand Down Expand Up @@ -193,16 +203,14 @@ private ApplicationJson nonReactiveServerMigrationForImport(ApplicationJson appl

switch (applicationJson.getServerSchemaVersion()) {
case 9:
applicationJson.setServerSchemaVersion(10);
case 10:
// this if for cases where we have empty datasource configs
MigrationHelperMethods.migrateApplicationJsonToVersionTen(applicationJson, Map.of());
applicationJson.setServerSchemaVersion(10);
applicationJson.setServerSchemaVersion(11);
default:
}

if (applicationJson.getServerSchemaVersion().equals(jsonSchemaVersions.getServerVersion())) {
return applicationJson;
}

applicationJson.setServerSchemaVersion(jsonSchemaVersions.getServerVersion());
return applicationJson;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

@Component
public class JsonSchemaVersionsFallback {
private static final Integer serverVersion = 10;
private static final Integer serverVersion = 11;
public static final Integer clientVersion = 1;

public Integer getServerVersion() {
Expand Down
Loading

0 comments on commit d52aa53

Please sign in to comment.