From 13ca80e91d56a4d4804bf755b9f9b6f5ea17a627 Mon Sep 17 00:00:00 2001 From: Manish Kumar <107841575+sondermanish@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:02:22 +0530 Subject: [PATCH 01/18] chore: flaky git test fix (#32606) --- .../ServerSchemaMigrationEnforcerTest.java | 63 +++++++++++++------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java index 670901de55..dca30bd65a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java @@ -13,6 +13,7 @@ import com.appsmith.server.helpers.PluginExecutorHelper; import com.appsmith.server.imports.internal.ImportService; import com.appsmith.server.services.WorkspaceService; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; @@ -105,7 +106,24 @@ public class ServerSchemaMigrationEnforcerTest { Mockito.when(pluginExecutorHelper.getPluginExecutor(any())).thenReturn(Mono.just(new MockPluginExecutor())); } - public static void verifyAssertions( + /** + * Each entity in the map is a separate file in git file-system, it's imperative that we compare them separately + * If the comparison fails then it would essentially mean that users would see the diff, + * hence it should not be ignored + * @param target + * @param source + */ + public void verifyMapAssertions(JsonObject target, JsonObject source) { + for (String key : source.keySet()) { + assertThat(convertElementToString(source.get(key))).isEqualTo(convertElementToString(target.get(key))); + } + } + + public String convertElementToString(JsonElement element) { + return gson.toJson(element); + } + + public void verifyAssertions( JsonObject exportedApplicationJsonObject, JsonObject importApplicationGitReferenceObject) { assertThat(exportedApplicationJsonObject.get(EXPORTED_APPLICATION).getAsJsonObject()) @@ -119,31 +137,36 @@ public class ServerSchemaMigrationEnforcerTest { assertThat(exportedApplicationJsonObject.get("theme").getAsJsonObject()) .isEqualTo(importApplicationGitReferenceObject.get("theme").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("actions").getAsJsonObject()) - .isEqualTo(importApplicationGitReferenceObject.get("actions").getAsJsonObject()); + /** + * This piece of assertion is commented out because of the flakiness + */ + // verifyMapAssertions( + // exportedApplicationJsonObject.get("actions").getAsJsonObject(), + // importApplicationGitReferenceObject.get("actions").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("actionBody").getAsJsonObject()) - .isEqualTo(importApplicationGitReferenceObject.get("actionBody").getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("actionBody").getAsJsonObject(), + importApplicationGitReferenceObject.get("actionBody").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("actionCollections").getAsJsonObject()) - .isEqualTo(importApplicationGitReferenceObject - .get("actionCollections") - .getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("actionCollections").getAsJsonObject(), + importApplicationGitReferenceObject.get("actionCollections").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("actionCollectionBody").getAsJsonObject()) - .isEqualTo(importApplicationGitReferenceObject - .get("actionCollectionBody") - .getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("actionCollectionBody").getAsJsonObject(), + importApplicationGitReferenceObject.get("actionCollectionBody").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("pages").getAsJsonObject()) - .isEqualTo(importApplicationGitReferenceObject.get("pages").getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("pages").getAsJsonObject(), + importApplicationGitReferenceObject.get("pages").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("pageDsl").getAsJsonObject()) - .isEqualTo(importApplicationGitReferenceObject.get("pageDsl").getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("pageDsl").getAsJsonObject(), + importApplicationGitReferenceObject.get("pageDsl").getAsJsonObject()); - assertThat(exportedApplicationJsonObject.get("datasources").getAsJsonObject()) - .isEqualTo( - importApplicationGitReferenceObject.get("datasources").getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("datasources").getAsJsonObject(), + importApplicationGitReferenceObject.get("datasources").getAsJsonObject()); } @Test From 795db148da712f00a0e1b5e0dce7e8dfa54bd60f Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Mon, 15 Apr 2024 13:46:37 +0530 Subject: [PATCH 02/18] chore: Fix warnings on `@EqualsAndHashCode` (#32667) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes build warnings like these: ``` Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type. ``` Why is this important? 1. Warnings are always a worse thing than errors, because they only fail at runtime. And this is quite a significant warning, so should be fixed. 2. This _incorrect_ `equals` method screws up Hibernate's dirty checking when working with Postgres. /ok-to-test tags="@tag.Sanity" > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 4f697fc3f9431fcfd35fc0f9814fce763382d06c > Cypress dashboard url: Click here! ## Summary by CodeRabbit - **Refactor** - Enhanced data consistency across various models by ensuring that equality and hash code calculations now consider superclass fields. --- .../main/java/com/external/plugins/models/UserImageContent.java | 2 ++ .../main/java/com/external/plugins/models/UserTextContent.java | 2 ++ .../main/java/com/appsmith/server/domains/GitDeployKeys.java | 2 ++ .../src/main/java/com/appsmith/server/domains/License.java | 2 ++ .../java/com/appsmith/server/dtos/UpdatePermissionGroupDTO.java | 2 ++ .../src/main/java/com/appsmith/server/dtos/UserProfileDTO.java | 2 ++ .../src/main/java/com/appsmith/server/dtos/UserUpdateDTO.java | 2 ++ 7 files changed, 14 insertions(+) diff --git a/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserImageContent.java b/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserImageContent.java index 9defcf7cdd..414ad6ceaa 100644 --- a/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserImageContent.java +++ b/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserImageContent.java @@ -4,8 +4,10 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class UserImageContent extends UserContent { ImageUrl imageUrl; diff --git a/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserTextContent.java b/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserTextContent.java index 76032bd0e1..9cd9d7b881 100644 --- a/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserTextContent.java +++ b/app/server/appsmith-plugins/openAiPlugin/src/main/java/com/external/plugins/models/UserTextContent.java @@ -1,8 +1,10 @@ package com.external.plugins.models; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public class UserTextContent extends UserContent { String text; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitDeployKeys.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitDeployKeys.java index 72fd75786d..e3dad3c554 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitDeployKeys.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/GitDeployKeys.java @@ -2,8 +2,10 @@ package com.appsmith.server.domains; import com.appsmith.external.models.BaseDomain; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public class GitDeployKeys extends BaseDomain { String email; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/License.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/License.java index 47094fb735..92a831149c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/License.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/License.java @@ -2,6 +2,8 @@ package com.appsmith.server.domains; import com.appsmith.server.domains.ce.LicenseCE; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public class License extends LicenseCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UpdatePermissionGroupDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UpdatePermissionGroupDTO.java index be10a9b204..2b3336e92f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UpdatePermissionGroupDTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UpdatePermissionGroupDTO.java @@ -2,8 +2,10 @@ package com.appsmith.server.dtos; import com.appsmith.server.dtos.ce.UpdatePermissionGroupCE_DTO; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @Data +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor public class UpdatePermissionGroupDTO extends UpdatePermissionGroupCE_DTO {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java index 8b77e8d126..9e26f95a30 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserProfileDTO.java @@ -2,6 +2,8 @@ package com.appsmith.server.dtos; import com.appsmith.server.dtos.ce.UserProfileCE_DTO; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) public class UserProfileDTO extends UserProfileCE_DTO {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserUpdateDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserUpdateDTO.java index c66d89ba14..d2657bb152 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserUpdateDTO.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/UserUpdateDTO.java @@ -2,9 +2,11 @@ package com.appsmith.server.dtos; import com.appsmith.server.dtos.ce.UserUpdateCE_DTO; import lombok.Data; +import lombok.EqualsAndHashCode; /** * Includes **only** those fields that can be updated for a user, via an API call. */ @Data +@EqualsAndHashCode(callSuper = true) public class UserUpdateDTO extends UserUpdateCE_DTO {} From 60790e2dc47ad94308a4f6dd49e928aae80b4b49 Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Mon, 15 Apr 2024 15:15:54 +0530 Subject: [PATCH 03/18] chore: Remove unused API route (#32676) --- .../server/controllers/ce/PageControllerCE.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java index 617ba98967..a16c31cb0b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/PageControllerCE.java @@ -9,8 +9,6 @@ import com.appsmith.server.dtos.CRUDPageResourceDTO; import com.appsmith.server.dtos.CRUDPageResponseDTO; import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.dtos.ResponseDTO; -import com.appsmith.server.exceptions.AppsmithError; -import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.solutions.CreateDBTablePageSolution; @@ -30,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @RequestMapping(Url.PAGE_URL) @@ -56,9 +53,7 @@ public class PageControllerCE { @ResponseStatus(HttpStatus.CREATED) public Mono> createPage( @Valid @RequestBody PageDTO resource, - @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName, - @RequestHeader(name = "Origin", required = false) String originHeader, - ServerWebExchange exchange) { + @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { log.debug("Going to create resource {}", resource.getClass().getName()); return applicationPageService .createPageWithBranchName(resource, branchName) @@ -136,13 +131,6 @@ public class PageControllerCE { .map(page -> new ResponseDTO<>(HttpStatus.OK.value(), page, null)); } - @JsonView(Views.Public.class) - @GetMapping("{pageName}/application/{applicationName}/view") - public Mono> getPageViewByName( - @PathVariable String applicationName, @PathVariable String pageName) { - return Mono.error(new AppsmithException(AppsmithError.DEPRECATED_API)); - } - /** * This only deletes the unpublished version of the page. * In case the page has never been published, the page gets deleted. From f2013bd386df32b3c56a0cc82fc3f01e7959153f Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Mon, 15 Apr 2024 17:00:40 +0530 Subject: [PATCH 04/18] chore: Remove `@Document` on non-entity classes (#32571) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These few classes have the `@Document` annotation, but aren't mapped to collections in the database, and don't have corresponding `*Repository` interfaces either. They're not database entities, and shouldn't have this annotation. Sanity passed on both CE and EE. /ok-to-test tags="@tag.Sanity" > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 52db7bdf8fba1cdd4cbd9141169854a32b32ca42 > Cypress dashboard url: Click here! --- .../java/com/appsmith/external/models/ActionConfiguration.java | 2 -- .../src/main/java/com/appsmith/external/models/Connection.java | 2 -- .../com/appsmith/external/models/DatasourceConfiguration.java | 2 -- .../src/main/java/com/appsmith/external/models/Endpoint.java | 2 -- .../main/java/com/appsmith/external/models/PEMCertificate.java | 2 -- 5 files changed, 10 deletions(-) diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java index 878770f179..5a35dd1f76 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java @@ -12,7 +12,6 @@ import lombok.experimental.FieldNameConstants; import lombok.extern.slf4j.Slf4j; import org.hibernate.validator.constraints.Range; import org.springframework.data.annotation.Transient; -import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.http.HttpMethod; import reactor.netty.http.HttpProtocol; @@ -28,7 +27,6 @@ import static com.appsmith.external.constants.ActionConstants.DEFAULT_ACTION_EXE @ToString @Slf4j @NoArgsConstructor -@Document @FieldNameConstants public class ActionConfiguration implements AppsmithDomain, ExecutableConfiguration { private static final int MIN_TIMEOUT_VALUE = 0; // in Milliseconds diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Connection.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Connection.java index 4ca418b24a..3c51016b14 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Connection.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Connection.java @@ -6,7 +6,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; -import org.springframework.data.mongodb.core.mapping.Document; @Getter @Setter @@ -14,7 +13,6 @@ import org.springframework.data.mongodb.core.mapping.Document; @EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor -@Document public class Connection implements AppsmithDomain { public enum Mode { diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceConfiguration.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceConfiguration.java index d9b783a766..a053c87a77 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceConfiguration.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceConfiguration.java @@ -8,7 +8,6 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import lombok.experimental.FieldNameConstants; -import org.springframework.data.mongodb.core.mapping.Document; import java.util.List; @@ -19,7 +18,6 @@ import java.util.List; @EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor -@Document @FieldNameConstants public class DatasourceConfiguration implements AppsmithDomain { diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Endpoint.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Endpoint.java index 0dcdcd1c43..de0962d027 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Endpoint.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Endpoint.java @@ -6,7 +6,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; -import org.springframework.data.mongodb.core.mapping.Document; @Getter @Setter @@ -14,7 +13,6 @@ import org.springframework.data.mongodb.core.mapping.Document; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode -@Document public class Endpoint { String host; diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/PEMCertificate.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/PEMCertificate.java index c14319aeaf..6c475002f7 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/PEMCertificate.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/PEMCertificate.java @@ -8,7 +8,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; -import org.springframework.data.mongodb.core.mapping.Document; @Getter @Setter @@ -16,7 +15,6 @@ import org.springframework.data.mongodb.core.mapping.Document; @EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor -@Document public class PEMCertificate implements AppsmithDomain { UploadedFile file; From a268337608387f1e710c578a6d703f576151e204 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Mon, 15 Apr 2024 17:50:26 +0530 Subject: [PATCH 05/18] fix: Typo in error codes (#32680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description An typo in the Error Code check on the client was causing failed error handling. This result was that no appropriate error page was shown. The typo was found because `AE-SCL-4004` was not a valid error code that was found anywhere on the codebase and the server was sending a very similar `AE-ACL-4004` for this particular error https://github.com/appsmithorg/appsmith/blob/release/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithErrorCode.java#L9 Fixes #32679 ## Automation /ok-to-test tags="@tag.Sanity" ### :mag: Cypress test results > [!IMPORTANT] > 🟣 🟣 🟣 Your tests are running. > Tests running at: > Commit: 3079a91e0b917833c4e9798da7b73abc15b1bc6c > Workflow: `PR Automation test suite` > Tags: `@tag.Sanity` ## Summary by CodeRabbit - **Refactor** - Updated an error code definition to enhance accuracy in system messages. --- app/client/src/ce/constants/ApiConstants.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/ce/constants/ApiConstants.tsx b/app/client/src/ce/constants/ApiConstants.tsx index beae6d8383..ea6dd956af 100644 --- a/app/client/src/ce/constants/ApiConstants.tsx +++ b/app/client/src/ce/constants/ApiConstants.tsx @@ -16,7 +16,7 @@ export enum API_STATUS_CODES { export const SERVER_ERROR_CODES = { INCORRECT_BINDING_LIST_OF_WIDGET: ["AE-JSN-4001", "AE-APP-4022"], RESOURCE_NOT_FOUND: [ - "AE-SCL-4004", + "AE-ACL-4004", "AE-BAD-4000", "AE-APP-4028", "AE-APP-4013", From e63b390e021fbe8580f93fdfbb0204ea74ca2a29 Mon Sep 17 00:00:00 2001 From: Ashok Kumar M <35134347+marks0351@users.noreply.github.com> Date: Mon, 15 Apr 2024 20:00:11 +0530 Subject: [PATCH 06/18] fix: move useFeatureFlagOverride to routes instead of app router (#32685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![workerB](https://img.shields.io/endpoint?url=https%3A%2F%2Fworkerb.linearb.io%2Fv2%2Fbadge%2Fprivate%2FU2FsdGVkX14GHmfZYDq4deKu54qT3FqPW13473c%2Fcollaboration.svg%3FcacheSeconds%3D60)](https://workerb.linearb.io/v2/badge/collaboration-page?magicLinkId=FaUTV9u) ## Description Moving useFeatureFlagOverride from app router to ce routes to make sure it is available for all environments. Fixes #`Issue Number` _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.MobileResponsive" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 19cabc927d62cd0216fd37c5d2c1738937544a15 > Cypress dashboard url: Click here! ## Summary by CodeRabbit - **Refactor** - Improved the timing of feature flag checks by adjusting where they are invoked in the application routing process. --- app/client/src/ce/AppRouter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/ce/AppRouter.tsx b/app/client/src/ce/AppRouter.tsx index 53b1d6525b..84ac386866 100644 --- a/app/client/src/ce/AppRouter.tsx +++ b/app/client/src/ce/AppRouter.tsx @@ -73,6 +73,7 @@ export function Routes() { const user = useSelector(getCurrentUserSelector); const tenantPermissions = useSelector(getTenantPermissions); const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); + useFeatureFlagOverride(); return ( @@ -150,7 +151,6 @@ export default function AppRouter() { const safeCrashCode: ERROR_CODES | undefined = useSelector(getSafeCrashCode); const isConsolidatedPageLoading = useSelector(getIsConsolidatedPageLoading); const dispatch = useDispatch(); - useFeatureFlagOverride(); useEffect(() => { dispatch(initCurrentPage()); From 11ef1fcf70d8ca78c20d3d420ab54b2ee5cc4580 Mon Sep 17 00:00:00 2001 From: Nilansh Bansal Date: Tue, 16 Apr 2024 11:45:06 +0530 Subject: [PATCH 07/18] feat: added updatedAt in actions (#32650) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description > This PR introduces the updatedAt field in the consolidated api response, `unpublishedActions` list. The value of updatedAt will be consumed by the client to sort the actions based on the recently updated ones in the suggested fetch queries for widgets learnability task. Fixes #32553 ## Automation /ok-to-test tags="@tag.ImportExport, @tag.Datasource, @tag.Fork, @tag.Git" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 45d7516ccf2b245bf93d66c767306732262ab131 > Cypress dashboard url: Click here! ## Summary by CodeRabbit - **New Features** - Updated the display of the "Last Updated" timestamp with a specific format and timezone across the application. - **Bug Fixes** - Ensured the "Last Updated" timestamp is accurately updated and displayed when actions are modified. - **Tests** - Added and modified tests to verify the correct handling and display of the "Last Updated" timestamp for actions. --- .../external/models/ce/ActionCE_DTO.java | 4 +- .../base/NewActionServiceCEImpl.java | 6 ++ .../ConsolidatedAPIServiceImplTest.java | 14 ++++ .../services/ce/ActionServiceCE_Test.java | 79 +++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java index 2951450eaa..ea1e1cfe97 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java @@ -169,7 +169,8 @@ public class ActionCE_DTO implements Identifiable, Executable { @JsonView(Views.Internal.class) protected Instant createdAt; - @JsonView(Views.Internal.class) + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC") + @JsonView(Views.Public.class) protected Instant updatedAt; // Defines what triggered action creation, could be self (user explicitly created action) / generate crud / one @@ -220,6 +221,7 @@ public class ActionCE_DTO implements Identifiable, Executable { this.resetTransientFields(); this.setEventData(null); this.setDefaultResources(null); + this.setUpdatedAt(null); this.setCacheResponse(null); if (this.getDatasource() != null) { this.getDatasource().setCreatedAt(null); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java index c5f640bdcf..720c75942b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java @@ -560,6 +560,12 @@ public class NewActionServiceCEImpl extends BaseService storages = new HashMap<>(); + storages.put( + defaultEnvironmentId, new DatasourceStorageDTO(null, defaultEnvironmentId, datasourceConfiguration)); + externalDatasource.setDatasourceStorages(storages); + Datasource savedDs = datasourceService.create(externalDatasource).block(); + + ActionDTO action = new ActionDTO(); + action.setName("updateActionShouldSetUpdatedAtField"); + action.setPageId(testPage.getId()); + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setHttpMethod(HttpMethod.GET); + action.setActionConfiguration(actionConfiguration); + action.setDatasource(savedDs); + + Mono newActionMono = + layoutActionService.createSingleAction(action, Boolean.FALSE).cache(); + + Mono updateActionMono = newActionMono.flatMap(preUpdateAction -> { + ActionDTO actionUpdate = action; + actionUpdate.getActionConfiguration().setBody("New Body"); + return layoutActionService + .updateSingleAction(preUpdateAction.getId(), actionUpdate) + .flatMap(updatedAction -> updateLayoutService + .updatePageLayoutsByPageId(updatedAction.getPageId()) + .thenReturn(updatedAction)); + }); + + StepVerifier.create(updateActionMono) + .assertNext(updatedAction -> { + assertThat(updatedAction).isNotNull(); + assertThat(updatedAction.getUpdatedAt()).isNotNull(); + assertThat(updatedAction.getActionConfiguration().getBody()).isEqualTo("New Body"); + }) + .verifyComplete(); + } + @Test @WithUserDetails(value = "api_user") public void testActionWithGraphQLDatasourceMoustacheBinding() { @@ -1489,6 +1540,34 @@ public class ActionServiceCE_Test { datasource = datasourceRepository.save(datasource).block(); } + @Test + @WithUserDetails("api_user") + public void validateAndSaveActionToRepository_ActionDTOHasCreatedAtUpdatedAtFieldsPresent() { + Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())) + .thenReturn(Mono.just(new MockPluginExecutor())); + Mockito.when(pluginService.getEditorConfigLabelMap(Mockito.anyString())).thenReturn(Mono.just(new HashMap<>())); + Mockito.when(pluginExecutor.getHintMessages(Mockito.any(), Mockito.any())) + .thenReturn(Mono.zip(Mono.just(new HashSet<>()), Mono.just(new HashSet<>()))); + ActionDTO action = new ActionDTO(); + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setHttpMethod(HttpMethod.POST); + actionConfiguration.setBody("random-request-body"); + actionConfiguration.setHeaders(List.of(new Property("random-header-key", "random-header-value"))); + action.setActionConfiguration(actionConfiguration); + action.setPageId(testPage.getId()); + action.setName("testActionFields"); + action.setDatasource(datasource); + ActionDTO createdAction = + layoutActionService.createSingleAction(action, Boolean.FALSE).block(); + + NewAction newAction = newActionService.findById(createdAction.getId()).block(); + ActionDTO savedAction = + newActionService.validateAndSaveActionToRepository(newAction).block(); + assertThat(savedAction.getIsValid()).isTrue(); + assertThat(savedAction.getCreatedAt()).isNotNull(); + assertThat(savedAction.getUpdatedAt()).isNotNull(); + } + @Test @WithUserDetails(value = "api_user") public void createCopyActionWithAnalyticsData_validateAnalyticsDataPersistsInResponse() { From f910a528e3ca7f58ac35693fd4d3c4d1eb41d33d Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Tue, 16 Apr 2024 12:47:16 +0530 Subject: [PATCH 08/18] chore: Add separate request/response views (#32448) This PR gets finer control into what fields are allowed in request-body-only, vs what's allowed in response-body-only. This leaves the fields to separately controlled regarding what can go into the database and what can't. [Slack thread](https://theappsmith.slack.com/archives/CPQNLFHTN/p1710125307810949). --- .../external/models/AnalyticsInfo.java | 4 ++ .../appsmith/external/models/BaseDomain.java | 3 +- .../appsmith/external/models/Datasource.java | 24 ++++----- .../external/models/ce/ActionCE_DTO.java | 53 +++++++++---------- .../appsmith/external/views/FromRequest.java | 7 +++ .../server/controllers/ActionController.java | 8 +-- .../controllers/ce/ActionControllerCE.java | 31 +++-------- 7 files changed, 56 insertions(+), 74 deletions(-) create mode 100644 app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/FromRequest.java diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/AnalyticsInfo.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/AnalyticsInfo.java index 7a62fe063f..f942844d93 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/AnalyticsInfo.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/AnalyticsInfo.java @@ -1,5 +1,8 @@ package com.appsmith.external.models; +import com.appsmith.external.views.FromRequest; +import com.appsmith.external.views.Views; +import com.fasterxml.jackson.annotation.JsonView; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -12,5 +15,6 @@ import java.util.Map; @ToString @NoArgsConstructor public class AnalyticsInfo { + @JsonView({Views.Public.class, FromRequest.class}) private Map analyticsData; } diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java index 3d6bf102f5..76aa95f321 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java @@ -1,6 +1,7 @@ package com.appsmith.external.models; import com.appsmith.external.helpers.Identifiable; +import com.appsmith.external.views.FromRequest; import com.appsmith.external.views.Views; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; @@ -37,7 +38,7 @@ public abstract class BaseDomain implements Persistable, AppsmithDomain, private static final long serialVersionUID = 7459916000501322517L; @Id - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) private String id; @JsonView(Views.Internal.class) diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java index 782ebd4ac3..884758d157 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java @@ -1,7 +1,7 @@ package com.appsmith.external.models; +import com.appsmith.external.views.FromRequest; import com.appsmith.external.views.Views; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import lombok.Getter; import lombok.NoArgsConstructor; @@ -29,38 +29,37 @@ public class Datasource extends BranchAwareDomain { @Transient public static final String DEFAULT_NAME_PREFIX = "Untitled datasource"; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String name; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String pluginId; // name of the plugin. used to log analytics events where pluginName is a required attribute // It'll be null if not set @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String pluginName; // Organizations migrated to workspaces, kept the field as deprecated to support the old migration @Deprecated - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String organizationId; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String workspaceId; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String templateName; // This is only kept public for embedded datasource - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) DatasourceConfiguration datasourceConfiguration; @Transient @JsonView(Views.Public.class) Map datasourceStorages = new HashMap<>(); - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonView(Views.Public.class) Set invalids; @@ -69,7 +68,6 @@ public class Datasource extends BranchAwareDomain { * - These messages are generated by the API server based on the other datasource attributes. */ @Transient - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonView(Views.Public.class) Set messages = new HashSet<>(); @@ -90,7 +88,7 @@ public class Datasource extends BranchAwareDomain { Boolean isConfigured; @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Boolean isRecentlyCreated; /* @@ -98,14 +96,14 @@ public class Datasource extends BranchAwareDomain { * The field is not used anywhere in the codebase because templates are created directly in the DB, and the field * serves only as a DTO property. */ - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Boolean isTemplate; /* * This field is meant to indicate whether the datasource is part of a mock DB, or a copy of the same. * The field is set during the creation of the mock db */ - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Boolean isMock; @JsonView(Views.Internal.class) diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java index ea1e1cfe97..64d7d0dfc7 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java @@ -17,9 +17,9 @@ import com.appsmith.external.models.Executable; import com.appsmith.external.models.PluginType; import com.appsmith.external.models.Policy; import com.appsmith.external.models.Property; +import com.appsmith.external.views.FromRequest; import com.appsmith.external.views.Views; import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonView; import lombok.Getter; import lombok.NoArgsConstructor; @@ -41,88 +41,83 @@ import java.util.Set; public class ActionCE_DTO implements Identifiable, Executable { @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) private String id; @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String applicationId; @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String workspaceId; @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) PluginType pluginType; // name of the plugin. used to log analytics events where pluginName is a required attribute // It'll be null if not set @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String pluginName; @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String pluginId; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String name; // The FQN for an action will also include any collection it is a part of as collectionName.actionName - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String fullyQualifiedName; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Datasource datasource; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String pageId; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) CreatorContextType contextType; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) String collectionId; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) ActionConfiguration actionConfiguration; // this attribute carries error messages while processing the actionCollection - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @Transient @JsonView(Views.Public.class) List errorReports; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Boolean executeOnLoad; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Boolean clientSideExecution; /* * This is a list of fields specified by the client to signify which fields have dynamic bindings in them. * TODO: The server can use this field to simplify our Mustache substitutions in the future */ - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) List dynamicBindingPathList; - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonView(Views.Public.class) Boolean isValid; - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonView(Views.Public.class) Set invalids; @Transient - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonView(Views.Public.class) Set messages = new HashSet<>(); // This is a list of keys that the client whose values the client needs to send during action execution. // These are the Mustache keys that the server will replace before invoking the API - @JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonView(Views.Public.class) Set jsonPathKeys; @@ -132,20 +127,20 @@ public class ActionCE_DTO implements Identifiable, Executable { @JsonView(Views.Internal.class) Boolean userSetOnLoad = false; - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Boolean confirmBeforeExecute = false; @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Documentation documentation; @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC") - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Instant deletedAt = null; @Deprecated @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC") - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) Instant archivedAt = null; @Transient @@ -153,7 +148,7 @@ public class ActionCE_DTO implements Identifiable, Executable { protected Set policies = new HashSet<>(); @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) public Set userPermissions = new HashSet<>(); // This field will be used to store the default/root actionId and applicationId for actions generated for git @@ -163,7 +158,7 @@ public class ActionCE_DTO implements Identifiable, Executable { // This field will be used to store analytics data related to this specific domain object. It's been introduced in // order to track success metrics of modules. Learn more on GitHub issue#24734 - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) AnalyticsInfo eventData; @JsonView(Views.Internal.class) @@ -177,7 +172,7 @@ public class ActionCE_DTO implements Identifiable, Executable { // click binding etc // Used in logging create action event @Transient - @JsonView(Views.Public.class) + @JsonView({Views.Public.class, FromRequest.class}) ActionCreationSourceTypeEnum source; @Transient diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/FromRequest.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/FromRequest.java new file mode 100644 index 0000000000..ecdda5af79 --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/FromRequest.java @@ -0,0 +1,7 @@ +package com.appsmith.external.views; + +/** + * Intended to annotate fields that can be set by HTTP request payloads, but should NOT be included + * in HTTP responses sent back to the client. + */ +public interface FromRequest {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ActionController.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ActionController.java index 62d9ec7d33..ccff2b83be 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ActionController.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ActionController.java @@ -6,23 +6,19 @@ import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.refactors.applications.RefactoringService; import com.appsmith.server.services.LayoutActionService; import com.appsmith.server.solutions.ActionExecutionSolution; -import io.micrometer.observation.ObservationRegistry; -import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(Url.ACTION_URL) -@Slf4j public class ActionController extends ActionControllerCE { public ActionController( LayoutActionService layoutActionService, NewActionService newActionService, RefactoringService refactoringService, - ActionExecutionSolution actionExecutionSolution, - ObservationRegistry observationRegistry) { + ActionExecutionSolution actionExecutionSolution) { - super(layoutActionService, newActionService, refactoringService, actionExecutionSolution, observationRegistry); + super(layoutActionService, newActionService, refactoringService, actionExecutionSolution); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java index 6dc5d69ae2..e4c1089626 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ActionControllerCE.java @@ -2,6 +2,7 @@ package com.appsmith.server.controllers.ce; import com.appsmith.external.models.ActionDTO; import com.appsmith.external.models.ActionExecutionResult; +import com.appsmith.external.views.FromRequest; import com.appsmith.external.views.Views; import com.appsmith.server.constants.FieldName; import com.appsmith.server.constants.Url; @@ -16,10 +17,9 @@ import com.appsmith.server.refactors.applications.RefactoringService; import com.appsmith.server.services.LayoutActionService; import com.appsmith.server.solutions.ActionExecutionSolution; import com.fasterxml.jackson.annotation.JsonView; -import io.micrometer.observation.ObservationRegistry; import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.codec.multipart.Part; @@ -42,36 +42,20 @@ import java.util.List; @Slf4j @RequestMapping(Url.ACTION_URL) +@RequiredArgsConstructor public class ActionControllerCE { private final LayoutActionService layoutActionService; private final NewActionService newActionService; private final RefactoringService refactoringService; private final ActionExecutionSolution actionExecutionSolution; - private final ObservationRegistry observationRegistry; - - @Autowired - public ActionControllerCE( - LayoutActionService layoutActionService, - NewActionService newActionService, - RefactoringService refactoringService, - ActionExecutionSolution actionExecutionSolution, - ObservationRegistry observationRegistry) { - this.layoutActionService = layoutActionService; - this.newActionService = newActionService; - this.refactoringService = refactoringService; - this.actionExecutionSolution = actionExecutionSolution; - this.observationRegistry = observationRegistry; - } @JsonView(Views.Public.class) @PostMapping @ResponseStatus(HttpStatus.CREATED) public Mono> createAction( - @Valid @RequestBody ActionDTO resource, - @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName, - @RequestHeader(name = "Origin", required = false) String originHeader, - ServerWebExchange exchange) { + @Valid @RequestBody @JsonView(FromRequest.class) ActionDTO resource, + @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { log.debug("Going to create resource {}", resource.getClass().getName()); return layoutActionService .createSingleActionWithBranch(resource, branchName) @@ -82,7 +66,7 @@ public class ActionControllerCE { @PutMapping("/{defaultActionId}") public Mono> updateAction( @PathVariable String defaultActionId, - @Valid @RequestBody ActionDTO resource, + @Valid @RequestBody @JsonView(FromRequest.class) ActionDTO resource, @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { log.debug("Going to update resource with defaultActionId: {}, branch: {}", defaultActionId, branchName); return layoutActionService @@ -178,9 +162,6 @@ public class ActionControllerCE { *

* The controller function is primarily used with param applicationId by the client to fetch the actions in edit * mode. - * - * @param params - * @return */ @JsonView(Views.Public.class) @GetMapping("") From e6c9efce5015edeb0ffd261a57fab02e832ebd94 Mon Sep 17 00:00:00 2001 From: Nidhi Date: Tue, 16 Apr 2024 13:15:53 +0530 Subject: [PATCH 09/18] chore: Move feature flag annotation and enum to interfaces (#32694) --- .../appsmith/external}/annotations/FeatureFlagged.java | 4 ++-- .../com/appsmith/external/enums}/FeatureFlagEnum.java | 2 +- .../aspect/FeatureFlaggedMethodInvokerAspect.java | 10 +++++----- .../datasources/base/DatasourceServiceCEImpl.java | 2 +- .../server/domains/ce/TenantConfigurationCE.java | 2 +- .../helpers/ce/FeatureFlagMigrationHelperCE.java | 2 +- .../helpers/ce/FeatureFlagMigrationHelperCEImpl.java | 2 +- .../server/helpers/ce/GitAutoCommitHelperImpl.java | 2 +- .../server/services/ce/FeatureFlagServiceCE.java | 2 +- .../server/services/ce/FeatureFlagServiceCEImpl.java | 2 +- .../server/services/ce/TenantServiceCEImpl.java | 2 +- .../aspect/FeatureFlaggedMethodInvokerAspectTest.java | 2 +- .../server/aspect/component/TestComponentImpl.java | 4 ++-- .../server/helpers/FeatureFlagMigrationHelperTest.java | 4 ++-- .../server/helpers/MockCacheableFeatureFlagHelper.java | 6 +++--- .../server/helpers/ce/GitAutoCommitHelperImplTest.java | 2 +- .../server/services/ce/FeatureFlagServiceCETest.java | 4 ++-- .../server/services/ce/TenantServiceCETest.java | 6 +++--- 18 files changed, 30 insertions(+), 30 deletions(-) rename app/server/{appsmith-server/src/main/java/com/appsmith/server => appsmith-interfaces/src/main/java/com/appsmith/external}/annotations/FeatureFlagged.java (89%) rename app/server/{appsmith-server/src/main/java/com/appsmith/server/featureflags => appsmith-interfaces/src/main/java/com/appsmith/external/enums}/FeatureFlagEnum.java (95%) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/FeatureFlagged.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/annotations/FeatureFlagged.java similarity index 89% rename from app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/FeatureFlagged.java rename to app/server/appsmith-interfaces/src/main/java/com/appsmith/external/annotations/FeatureFlagged.java index 0414804df7..71b69a7d56 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/annotations/FeatureFlagged.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/annotations/FeatureFlagged.java @@ -1,6 +1,6 @@ -package com.appsmith.server.annotations; +package com.appsmith.external.annotations; -import com.appsmith.server.featureflags.FeatureFlagEnum; +import com.appsmith.external.enums.FeatureFlagEnum; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java similarity index 95% rename from app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java rename to app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java index 385786b68d..0c4ef68d6b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java @@ -1,4 +1,4 @@ -package com.appsmith.server.featureflags; +package com.appsmith.external.enums; public enum FeatureFlagEnum { // ------------------- These features are only for JUnit testing. DO NOT use these features in your code path.--- // diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java index 63576b3ea4..2216f66e8c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java @@ -1,10 +1,10 @@ package com.appsmith.server.aspect; -import com.appsmith.server.annotations.FeatureFlagged; +import com.appsmith.external.annotations.FeatureFlagged; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.featureflags.CachedFeatures; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.services.FeatureFlagService; import lombok.RequiredArgsConstructor; @@ -32,16 +32,16 @@ public class FeatureFlaggedMethodInvokerAspect { private final ApplicationContext applicationContext; /** - * Intercepts method calls that are annotated with {@link com.appsmith.server.annotations.FeatureFlagged}. + * Intercepts method calls that are annotated with {@link FeatureFlagged}. * This advice method wraps the intercepted method call, allowing conditional execution based on the state * of the specified feature flag. * * @param joinPoint The join point representing the intercepted method call. * @return The result of the intercepted method call * - * @see com.appsmith.server.annotations.FeatureFlagged + * @see FeatureFlagged */ - @Around("execution(public * *(..)) && @annotation(com.appsmith.server.annotations.FeatureFlagged)") + @Around("execution(public * *(..)) && @annotation(com.appsmith.external.annotations.FeatureFlagged)") public Object invokeMethodAtMethodLevelAnnotation(ProceedingJoinPoint joinPoint) throws IllegalAccessException { Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); FeatureFlagged annotation = method.getAnnotation(FeatureFlagged.class); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java index 291ebe1fa3..1678b7aca3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java @@ -1,6 +1,7 @@ package com.appsmith.server.datasources.base; import com.appsmith.external.constants.AnalyticsEvents; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.external.models.Datasource; import com.appsmith.external.models.DatasourceConfiguration; import com.appsmith.external.models.DatasourceStorage; @@ -20,7 +21,6 @@ import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.PluginExecutorHelper; import com.appsmith.server.plugins.base.PluginService; import com.appsmith.server.ratelimiting.RateLimitService; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java index 853da0fffa..4d11d668be 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/TenantConfigurationCE.java @@ -1,11 +1,11 @@ package com.appsmith.server.domains.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; import com.appsmith.server.constants.LicensePlan; import com.appsmith.server.constants.MigrationStatus; import com.appsmith.server.domains.License; import com.appsmith.server.domains.TenantConfiguration; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Data; import org.apache.commons.lang3.ObjectUtils; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java index 1e4489d0fa..0a89a9c81f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCE.java @@ -1,8 +1,8 @@ package com.appsmith.server.helpers.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; import com.appsmith.server.domains.Tenant; -import com.appsmith.server.featureflags.FeatureFlagEnum; import reactor.core.publisher.Mono; import java.util.Map; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java index 658c9390cc..6c1ccda3f8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/FeatureFlagMigrationHelperCEImpl.java @@ -1,10 +1,10 @@ package com.appsmith.server.helpers.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.featureflags.CachedFeatures; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.services.CacheableFeatureFlagHelper; import com.appsmith.server.solutions.ce.ScheduledTaskCEImpl; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImpl.java index 6a3e2578d4..5ce338791c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImpl.java @@ -1,5 +1,6 @@ package com.appsmith.server.helpers.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.GitArtifactMetadata; @@ -8,7 +9,6 @@ import com.appsmith.server.dtos.AutoCommitProgressDTO; import com.appsmith.server.events.AutoCommitEvent; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.GitPrivateRepoHelper; import com.appsmith.server.helpers.GitUtils; import com.appsmith.server.helpers.RedisUtils; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java index f617e92971..c10ba8c383 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java @@ -1,8 +1,8 @@ package com.appsmith.server.services.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.domains.Tenant; import com.appsmith.server.featureflags.CachedFeatures; -import com.appsmith.server.featureflags.FeatureFlagEnum; import reactor.core.publisher.Mono; import java.util.Map; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java index d73a419d60..fda8d2da37 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java @@ -1,12 +1,12 @@ package com.appsmith.server.services.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.MigrationStatus; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.featureflags.CachedFlags; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.services.CacheableFeatureFlagHelper; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java index 454915363c..04e22c1ac6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/TenantServiceCEImpl.java @@ -1,5 +1,6 @@ package com.appsmith.server.services.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.external.helpers.AppsmithBeanUtils; import com.appsmith.server.acl.AclPermission; import com.appsmith.server.constants.FeatureMigrationType; @@ -9,7 +10,6 @@ import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.CollectionUtils; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.repositories.TenantRepository; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java index 655c5d98ea..f6aff5b9b2 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java @@ -1,10 +1,10 @@ package com.appsmith.server.aspect; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.aspect.component.TestComponent; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.featureflags.CachedFeatures; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.services.FeatureFlagService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java index 702ea3754c..3da1b574d1 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java @@ -1,10 +1,10 @@ package com.appsmith.server.aspect.component; -import com.appsmith.server.annotations.FeatureFlagged; +import com.appsmith.external.annotations.FeatureFlagged; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.aspect.component.ce_compatible.TestComponentCECompatibleImpl; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.featureflags.FeatureFlagEnum; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java index 55779d78c9..5cfcd9318c 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/FeatureFlagMigrationHelperTest.java @@ -1,10 +1,10 @@ package com.appsmith.server.helpers; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.featureflags.CachedFeatures; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.services.CacheableFeatureFlagHelper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -23,10 +23,10 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; import static com.appsmith.server.constants.FeatureMigrationType.DISABLE; import static com.appsmith.server.constants.FeatureMigrationType.ENABLE; import static com.appsmith.server.constants.MigrationStatus.PENDING; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TENANT_TEST_FEATURE; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.mockito.ArgumentMatchers.any; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java index 1e045796f5..8e4199ba0b 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/MockCacheableFeatureFlagHelper.java @@ -17,9 +17,9 @@ import java.time.Instant; import java.util.HashMap; import java.util.Map; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TENANT_TEST_FEATURE; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TEST_FEATURE_1; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TEST_FEATURE_2; +import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; +import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_1; +import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_2; @Profile("test") @Primary diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImplTest.java index 78c78a61d9..f49b8a3b3b 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/GitAutoCommitHelperImplTest.java @@ -1,5 +1,6 @@ package com.appsmith.server.helpers.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.acl.AclPermission; import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.domains.Application; @@ -9,7 +10,6 @@ import com.appsmith.server.domains.GitAuth; import com.appsmith.server.domains.GitProfile; import com.appsmith.server.dtos.AutoCommitProgressDTO; import com.appsmith.server.events.AutoCommitEvent; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.GitPrivateRepoHelper; import com.appsmith.server.helpers.RedisUtils; import com.appsmith.server.services.CommonGitService; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java index 483c458b27..88244f2efc 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java @@ -1,11 +1,11 @@ package com.appsmith.server.services.ce; import com.appsmith.caching.components.CacheManager; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.domains.User; import com.appsmith.server.dtos.FeaturesResponseDTO; import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.featureflags.CachedFlags; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.services.CacheableFeatureFlagHelper; import com.appsmith.server.services.FeatureFlagService; @@ -33,11 +33,11 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; import static com.appsmith.server.constants.FeatureMigrationType.DISABLE; import static com.appsmith.server.constants.FeatureMigrationType.ENABLE; import static com.appsmith.server.constants.MigrationStatus.COMPLETED; import static com.appsmith.server.constants.MigrationStatus.PENDING; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TENANT_TEST_FEATURE; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java index 3f7408fa5f..4710801319 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/TenantServiceCETest.java @@ -1,11 +1,11 @@ package com.appsmith.server.services.ce; +import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.constants.FeatureMigrationType; import com.appsmith.server.constants.LicensePlan; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.exceptions.AppsmithException; -import com.appsmith.server.featureflags.FeatureFlagEnum; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.helpers.ce.bridge.Bridge; @@ -33,11 +33,11 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import static com.appsmith.external.enums.FeatureFlagEnum.TENANT_TEST_FEATURE; +import static com.appsmith.external.enums.FeatureFlagEnum.TEST_FEATURE_2; import static com.appsmith.server.constants.MigrationStatus.COMPLETED; import static com.appsmith.server.constants.MigrationStatus.IN_PROGRESS; import static com.appsmith.server.exceptions.AppsmithErrorCode.FEATURE_FLAG_MIGRATION_FAILURE; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TENANT_TEST_FEATURE; -import static com.appsmith.server.featureflags.FeatureFlagEnum.TEST_FEATURE_2; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static org.assertj.core.api.Assertions.assertThat; From ed1bb9273a1e58bfbd4fa80ebc5452d1967392d8 Mon Sep 17 00:00:00 2001 From: Aman Agarwal Date: Tue, 16 Apr 2024 13:29:04 +0530 Subject: [PATCH 10/18] fix: default port numbers for the datasources (#32592) --- .../Datasources/ConnectionErrors_Spec.ts | 12 ++++++--- .../ServerSide/Datasources/Oracle_Spec.ts | 3 ++- .../Datasources/Redis_Basic_Spec.ts | 19 +++++++------- .../QueryPane/EmptyDataSource_spec.js | 2 +- .../Datasources/ArangoDataSourceStub_spec.js | 7 +++++ .../ElasticSearchDatasource_spec.js | 9 ++++++- .../Datasources/MongoDatasourceURI_spec.ts | 7 +++++ .../Sanity/Datasources/MsSQL_Basic_Spec.ts | 7 +++++ .../e2e/Sanity/Datasources/MySQL_spec.js | 7 +++++ .../Datasources/PostgresDatasource_spec.js | 7 +++++ .../RedshiftDataSourceStub_spec.js | 8 ++++++ .../Sanity/Datasources/SMTPDatasource_spec.js | 7 +++++ .../cypress/support/dataSourceCommands.js | 26 ++++++++++++++----- app/client/test/factories/MockPluginsState.ts | 1 + .../src/main/resources/form.json | 1 + .../src/main/resources/form.json | 1 + .../mongoPlugin/src/main/resources/form.json | 1 + .../mssqlPlugin/src/main/resources/form.json | 1 + .../mysqlPlugin/src/main/resources/form.json | 1 + .../oraclePlugin/src/main/resources/form.json | 1 + .../src/main/resources/form.json | 1 + .../redisPlugin/src/main/resources/form.json | 1 + .../src/main/resources/form.json | 1 + .../smtpPlugin/src/main/resources/form.json | 1 + 24 files changed, 108 insertions(+), 24 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/Datasources/ConnectionErrors_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Datasources/ConnectionErrors_Spec.ts index f792022482..65c8e2f64a 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Datasources/ConnectionErrors_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Datasources/ConnectionErrors_Spec.ts @@ -25,8 +25,8 @@ describe( agHelper.RenameWithInPane(dataSourceName, false); dataSources.TestDatasource(false); - agHelper.ValidateToastMessage("Missing endpoint."); agHelper.ValidateToastMessage("Missing username for authentication."); + agHelper.ValidateToastMessage("Missing hostname."); agHelper.ClearTextField(dataSources._databaseName); dataSources.TestDatasource(false); agHelper.ValidateToastMessage("Missing database name."); @@ -81,7 +81,7 @@ describe( agHelper.RenameWithInPane(dataSourceName, false); dataSources.TestDatasource(false); - agHelper.ValidateToastMessage("Missing endpoint and url"); + agHelper.ValidateToastMessage("Host value cannot be empty"); agHelper.ValidateToastMessage("Missing username for authentication."); agHelper.ValidateToastMessage("Missing password for authentication."); agHelper.ClearTextField(dataSources._databaseName); @@ -135,7 +135,9 @@ describe( agHelper.RenameWithInPane(dataSourceName, false); dataSources.TestDatasource(false); - agHelper.ValidateToastMessage("Missing endpoint(s)"); + agHelper.ValidateToastMessage( + "Connection timed out. Please check if the datasource configuration fields have been filled correctly.", + ); dataSources.ValidateNSelectDropdown( "Use mongo connection string URI", "No", @@ -166,7 +168,9 @@ describe( "Replica set", ); dataSources.TestDatasource(false); - agHelper.ValidateToastMessage("Missing endpoint(s)"); + agHelper.ValidateToastMessage( + "REPLICA_SET connections should not be given a port. If you are trying to specify all the shards, please add more than one.", + ); agHelper.UpdateInputValue( dataSources._host(), dataManager.dsValues[dataManager.defaultEnviorment].mongo_host, diff --git a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Oracle_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Oracle_Spec.ts index 15065d4d10..fffbcc65e3 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Oracle_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Oracle_Spec.ts @@ -30,7 +30,7 @@ describe("Validate Oracle DS", { tags: ["@tag.Datasource"] }, () => { }); }); - it("1. Tc #2354, #2204 - Oracle placeholder & mandatory mark verification", () => { + it("1. Tc #2354, #2204 - Oracle placeholder, port default value & mandatory mark verification", () => { dataSources.NavigateToDSCreateNew(); dataSources.CreatePlugIn("Oracle"); agHelper.GetNAssertContains(locators._dsName, "Untitled datasource"); @@ -45,6 +45,7 @@ describe("Validate Oracle DS", { tags: ["@tag.Datasource"] }, () => { "placeholder", "myapp.abcde.oracle.net", ); + agHelper.AssertAttribute(dataSources._port, "value", "1521"); agHelper.AssertAttribute( dataSources._databaseName, "placeholder", diff --git a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts index 586e07d7b9..2745330884 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Datasources/Redis_Basic_Spec.ts @@ -14,7 +14,7 @@ describe("Validate Redis DS", { tags: ["@tag.Datasource"] }, () => { }); }); - it("Create HAST set (Multiple key value pair under single key name) in redis DB, Read, Delete", () => { + it("1. Create HAST set (Multiple key value pair under single key name) in redis DB, Read, Delete", () => { let hSetReceipe = `HSET recipe:1 name "Vegetable Stir Fry" ingredients "2 cups mixed vegetables (broccoli, carrots, bell peppers, mushrooms, snow peas), 2 cloves garlic, minced" instructions "1. Heat vegetable oil in a large skillet over medium-high heat. 2. Add mixed vegetables and garlic to the skillet and cook for 3-4 minutes. 3. In a small bowl, whisk together soy sauce and cornstarch. 4. Pour the soy sauce mixture over the vegetables and stir until the vegetables are coated. 5. Cook for an additional 1-2 minutes. 6. Serve hot." difficulty "easy"`; let hGetKeys = "HGET recipe:1 name"; let hMGet = "HMGET recipe:1 difficulty name"; // getting multiple keys @@ -90,20 +90,19 @@ describe("Validate Redis DS", { tags: ["@tag.Datasource"] }, () => { dataSources.EnterQuery(hGetKeys); dataSources.RunQueryNVerifyResponseViews(); //5 keys, 5 values dataSources.AssertQueryTableResponse(0, "null"); - }); - after("Delete the query & datasource", () => { + // Delete the query & datasource agHelper.ActionContextMenuWithInPane({ action: "Delete", entityType: entityItems.Query, }); dataSources.DeleteDatasourceFromWithinDS(dsName); - //commenting below since after query delete, we run into risk of not seeing the datasource in EntityExplorer - // EditorNavigation.SelectEntityByName(dsName, EntityType.Datasource); - // entityExplorer.ActionContextMenuByEntityName({ - // entityNameinLeftSidebar: dsName, - // action: "Delete", - // entityType: entityItems.Datasource, - // }); + }); + + it("2. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("Redis"); + + agHelper.AssertAttribute(dataSources._port, "value", "6379"); }); }); diff --git a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/EmptyDataSource_spec.js b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/EmptyDataSource_spec.js index 44d4129505..89a387b62a 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/QueryPane/EmptyDataSource_spec.js +++ b/app/client/cypress/e2e/Regression/ServerSide/QueryPane/EmptyDataSource_spec.js @@ -23,7 +23,7 @@ describe( dataSources.RunQuery({ toValidateResponse: false }); cy.wait(500); cy.get("[data-testid=t--query-error]").contains( - "[Missing endpoint., Missing username for authentication.]", + "[Missing username for authentication., Missing hostname.]", ); agHelper.ActionContextMenuWithInPane({ action: "Delete", diff --git a/app/client/cypress/e2e/Sanity/Datasources/ArangoDataSourceStub_spec.js b/app/client/cypress/e2e/Sanity/Datasources/ArangoDataSourceStub_spec.js index c745197d53..a87849fdd3 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/ArangoDataSourceStub_spec.js +++ b/app/client/cypress/e2e/Sanity/Datasources/ArangoDataSourceStub_spec.js @@ -47,5 +47,12 @@ describe( .then(($dbName) => expect($dbName).to.eq("_system")); dataSources.SaveDSFromDialog(false); }); + + it("5. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("ArangoDB"); + + agHelper.AssertAttribute(dataSources._port, "value", "8529"); + }); }, ); diff --git a/app/client/cypress/e2e/Sanity/Datasources/ElasticSearchDatasource_spec.js b/app/client/cypress/e2e/Sanity/Datasources/ElasticSearchDatasource_spec.js index d213eebea2..7a95ee2f39 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/ElasticSearchDatasource_spec.js +++ b/app/client/cypress/e2e/Sanity/Datasources/ElasticSearchDatasource_spec.js @@ -1,6 +1,6 @@ const datasource = require("../../../locators/DatasourcesEditor.json"); -import { dataSources } from "../../../support/Objects/ObjectsCore"; +import { agHelper, dataSources } from "../../../support/Objects/ObjectsCore"; let elasticSearchName; @@ -31,5 +31,12 @@ describe( dataSources.SaveDSFromDialog(false); }); + + it("2. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("Elasticsearch"); + + agHelper.AssertAttribute(dataSources._port, "value", "9200"); + }); }, ); diff --git a/app/client/cypress/e2e/Sanity/Datasources/MongoDatasourceURI_spec.ts b/app/client/cypress/e2e/Sanity/Datasources/MongoDatasourceURI_spec.ts index d0168eba7b..356d71264c 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/MongoDatasourceURI_spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/MongoDatasourceURI_spec.ts @@ -43,5 +43,12 @@ describe( dataSources.DeleteDatasourceFromWithinDS(dsName); }); }); + + it("4. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("MongoDB"); + + agHelper.AssertAttribute(dataSources._port, "value", "27017"); + }); }, ); diff --git a/app/client/cypress/e2e/Sanity/Datasources/MsSQL_Basic_Spec.ts b/app/client/cypress/e2e/Sanity/Datasources/MsSQL_Basic_Spec.ts index 18fba758aa..1fb99aff2e 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/MsSQL_Basic_Spec.ts +++ b/app/client/cypress/e2e/Sanity/Datasources/MsSQL_Basic_Spec.ts @@ -343,6 +343,13 @@ describe( table.WaitUntilTableLoad(); }); + it("7. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("Microsoft SQL Server"); + + agHelper.AssertAttribute(dataSources._port, "value", "1433"); + }); + after("Verify Deletion of the datasource", () => { cy.intercept("DELETE", "/api/v1/datasources/*").as("deleteDatasource"); //Since intercept from before is not working dataSources.DeleteDatasourceFromWithinDS(dsName, 409); //since CRUD pages are still active diff --git a/app/client/cypress/e2e/Sanity/Datasources/MySQL_spec.js b/app/client/cypress/e2e/Sanity/Datasources/MySQL_spec.js index 6d92465b06..aae11a813a 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/MySQL_spec.js +++ b/app/client/cypress/e2e/Sanity/Datasources/MySQL_spec.js @@ -45,5 +45,12 @@ describe( cy.deleteQueryUsingContext(); cy.deleteDatasource(datasourceName); }); + + it("4. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("MySQL"); + + agHelper.AssertAttribute(dataSources._port, "value", "3306"); + }); }, ); diff --git a/app/client/cypress/e2e/Sanity/Datasources/PostgresDatasource_spec.js b/app/client/cypress/e2e/Sanity/Datasources/PostgresDatasource_spec.js index f46834586d..d9140f5ad0 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/PostgresDatasource_spec.js +++ b/app/client/cypress/e2e/Sanity/Datasources/PostgresDatasource_spec.js @@ -42,5 +42,12 @@ describe( cy.deleteQueryUsingContext(); cy.deleteDatasource(datasourceName); }); + + it("4. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("PostgreSQL"); + + agHelper.AssertAttribute(dataSources._port, "value", "5432"); + }); }, ); diff --git a/app/client/cypress/e2e/Sanity/Datasources/RedshiftDataSourceStub_spec.js b/app/client/cypress/e2e/Sanity/Datasources/RedshiftDataSourceStub_spec.js index 24b74f15a4..1a757cbb02 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/RedshiftDataSourceStub_spec.js +++ b/app/client/cypress/e2e/Sanity/Datasources/RedshiftDataSourceStub_spec.js @@ -1,5 +1,6 @@ const datasource = require("../../../locators/DatasourcesEditor.json"); let datasourceName; +import { agHelper, dataSources } from "../../../support/Objects/ObjectsCore"; import { ObjectsRegistry } from "../../../support/Objects/Registry"; describe( @@ -49,5 +50,12 @@ describe( cy.deleteQueryUsingContext(); cy.deleteDatasource(datasourceName); }); + + it("4. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("Redshift"); + + agHelper.AssertAttribute(dataSources._port, "value", "5439"); + }); }, ); diff --git a/app/client/cypress/e2e/Sanity/Datasources/SMTPDatasource_spec.js b/app/client/cypress/e2e/Sanity/Datasources/SMTPDatasource_spec.js index 863809a1a8..9576cca08a 100644 --- a/app/client/cypress/e2e/Sanity/Datasources/SMTPDatasource_spec.js +++ b/app/client/cypress/e2e/Sanity/Datasources/SMTPDatasource_spec.js @@ -126,5 +126,12 @@ describe( expect(thisTestEmail.attachments.length).equal(1); }); }); + + it("4. Verify the default port for the datasource", function () { + dataSources.NavigateToDSCreateNew(); + dataSources.CreatePlugIn("SMTP"); + + agHelper.AssertAttribute(dataSources._port, "value", "25"); + }); }, ); diff --git a/app/client/cypress/support/dataSourceCommands.js b/app/client/cypress/support/dataSourceCommands.js index de7c760c87..4d7ba23f5f 100644 --- a/app/client/cypress/support/dataSourceCommands.js +++ b/app/client/cypress/support/dataSourceCommands.js @@ -93,7 +93,9 @@ Cypress.Commands.add( : datasourceFormData["postgres-databaseName"]; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["postgres-port"]); + cy.get(datasourceEditor.port) + .clear() + .type(datasourceFormData["postgres-port"]); cy.get(datasourceEditor.databaseName).clear().type(databaseName); cy.get(datasourceEditor.username).type( datasourceFormData["postgres-username"], @@ -113,7 +115,9 @@ Cypress.Commands.add( const headerValue = "Bearer token"; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["postgres-port"]); + cy.get(datasourceEditor.port) + .clear() + .type(datasourceFormData["postgres-port"]); cy.get(datasourceEditor.sectionAuthentication).click(); cy.get(datasourceEditor.username).type( datasourceFormData["postgres-username"], @@ -136,7 +140,9 @@ Cypress.Commands.add( : datasourceFormData["mysql-databaseName"]; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["mysql-port"]); + cy.get(datasourceEditor.port) + .clear() + .type(datasourceFormData["mysql-port"]); cy.get(datasourceEditor.databaseName).clear().type(databaseName); cy.get(datasourceEditor.username).type( datasourceFormData["mysql-username"], @@ -158,7 +164,9 @@ Cypress.Commands.add( : datasourceFormData["mssql-databaseName"]; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["mssql-port"]); + cy.get(datasourceEditor.port) + .clear() + .type(datasourceFormData["mssql-port"]); cy.get(datasourceEditor.databaseName).clear().type(databaseName); cy.get(datasourceEditor.username).type( datasourceFormData["mssql-username"], @@ -180,7 +188,9 @@ Cypress.Commands.add( : datasourceFormData["arango-databaseName"]; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["arango-port"]); + cy.get(datasourceEditor.port) + .clear() + .type(datasourceFormData["arango-port"]); cy.get(datasourceEditor.databaseName).clear().type(databaseName); cy.get(datasourceEditor.username).type( @@ -203,7 +213,9 @@ Cypress.Commands.add( : datasourceFormData["redshift-databaseName"]; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["redshift-port"]); + cy.get(datasourceEditor.port) + .clear() + .type(datasourceFormData["redshift-port"]); cy.get(datasourceEditor.databaseName).clear().type(databaseName); cy.get(datasourceEditor.username).type( datasourceFormData["redshift-username"], @@ -250,7 +262,7 @@ Cypress.Commands.add( ? datasourceFormData["smtp-host"] + " " : datasourceFormData["smtp-host"]; cy.get(datasourceEditor.host).type(hostAddress); - cy.get(datasourceEditor.port).type(datasourceFormData["smtp-port"]); + cy.get(datasourceEditor.port).clear().type(datasourceFormData["smtp-port"]); cy.get(datasourceEditor.sectionAuthentication).click(); cy.get(datasourceEditor.username).type(datasourceFormData["smtp-username"]); cy.get(datasourceEditor.password).type(datasourceFormData["smtp-password"]); diff --git a/app/client/test/factories/MockPluginsState.ts b/app/client/test/factories/MockPluginsState.ts index 33fadf1625..d61c450886 100644 --- a/app/client/test/factories/MockPluginsState.ts +++ b/app/client/test/factories/MockPluginsState.ts @@ -5954,6 +5954,7 @@ export default { label: "Port", configProperty: "datasourceConfiguration.endpoints[*].port", dataType: "NUMBER", + initialValue: ["5432"], controlType: "KEYVALUE_ARRAY", placeholderText: "5432", }, diff --git a/app/server/appsmith-plugins/arangoDBPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/arangoDBPlugin/src/main/resources/form.json index ad11e16f22..2a823f3aa3 100644 --- a/app/server/appsmith-plugins/arangoDBPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/arangoDBPlugin/src/main/resources/form.json @@ -19,6 +19,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["8529"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "8529" } diff --git a/app/server/appsmith-plugins/elasticSearchPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/elasticSearchPlugin/src/main/resources/form.json index d6dd3a2b12..e204216b72 100644 --- a/app/server/appsmith-plugins/elasticSearchPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/elasticSearchPlugin/src/main/resources/form.json @@ -18,6 +18,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["9200"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "9200" } diff --git a/app/server/appsmith-plugins/mongoPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/mongoPlugin/src/main/resources/form.json index 1cb0408f71..9911fe8838 100644 --- a/app/server/appsmith-plugins/mongoPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/mongoPlugin/src/main/resources/form.json @@ -107,6 +107,7 @@ "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", "controlType": "KEYVALUE_ARRAY", + "initialValue": ["27017"], "hidden": { "path": "datasourceConfiguration.properties[0].value", "comparison": "EQUALS", diff --git a/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json index a0eb7d851d..3480fedcf1 100644 --- a/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/mssqlPlugin/src/main/resources/form.json @@ -36,6 +36,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["1433"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "1433" } diff --git a/app/server/appsmith-plugins/mysqlPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/mysqlPlugin/src/main/resources/form.json index 9e7aef76a9..c720c4faff 100644 --- a/app/server/appsmith-plugins/mysqlPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/mysqlPlugin/src/main/resources/form.json @@ -62,6 +62,7 @@ "label": "MySQL port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["3306"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "3306" } diff --git a/app/server/appsmith-plugins/oraclePlugin/src/main/resources/form.json b/app/server/appsmith-plugins/oraclePlugin/src/main/resources/form.json index 6750eccf18..c5de59887a 100755 --- a/app/server/appsmith-plugins/oraclePlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/oraclePlugin/src/main/resources/form.json @@ -20,6 +20,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["1521"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "1521" } diff --git a/app/server/appsmith-plugins/postgresPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/postgresPlugin/src/main/resources/form.json index 4ae416e63a..5c12b3c893 100644 --- a/app/server/appsmith-plugins/postgresPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/postgresPlugin/src/main/resources/form.json @@ -29,6 +29,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["5432"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "5432" } diff --git a/app/server/appsmith-plugins/redisPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/redisPlugin/src/main/resources/form.json index f9324389d8..d2e12db10d 100644 --- a/app/server/appsmith-plugins/redisPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/redisPlugin/src/main/resources/form.json @@ -19,6 +19,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["6379"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "6379" } diff --git a/app/server/appsmith-plugins/redshiftPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/redshiftPlugin/src/main/resources/form.json index e4fafa48da..7c0151fdae 100644 --- a/app/server/appsmith-plugins/redshiftPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/redshiftPlugin/src/main/resources/form.json @@ -36,6 +36,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["5439"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "5439" } diff --git a/app/server/appsmith-plugins/smtpPlugin/src/main/resources/form.json b/app/server/appsmith-plugins/smtpPlugin/src/main/resources/form.json index 08878f60a1..5e0115e4fc 100644 --- a/app/server/appsmith-plugins/smtpPlugin/src/main/resources/form.json +++ b/app/server/appsmith-plugins/smtpPlugin/src/main/resources/form.json @@ -19,6 +19,7 @@ "label": "Port", "configProperty": "datasourceConfiguration.endpoints[*].port", "dataType": "NUMBER", + "initialValue": ["25"], "controlType": "KEYVALUE_ARRAY", "placeholderText": "25" } From 01180513016262d47ab2163bad7c543c7de1b2cc Mon Sep 17 00:00:00 2001 From: Jacques Ikot Date: Tue, 16 Apr 2024 09:41:09 +0100 Subject: [PATCH 11/18] feat: implement dropping building blocks on canvas (#31857) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description > [!TIP] **Goal** To drag any building blocks from the explorer and drop at any position on the users canvas with full implementation. **Implementation** - Show skeleton widget when building block is initially dragged unto the canvas. - Make API call to add datasources, queries, and JS to existing page of users app - Get returned widget DSL and use existing copy paste logic to display widgets on the canvas - Remove loading state, handle clean up for copy paste - Run all queries newly created by the dropped building block **Limitations** - There is a loading state and the process is not instant like dropping a widget This PR is followed by this one [here](https://github.com/appsmithorg/appsmith/pull/31406), which displays the loading state when a building block is dragged unto the canvas. Fixes #31856 ## Automation /ok-to-test tags="@tag.Templates, @tag.MainContainer, @tag.Visual, @tag.Widget" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 456a7a0a322e76974a7f5c41a6c1e274ef82e4ea > Cypress dashboard url: Click here! ## Summary by CodeRabbit - **New Features** - Introduced a new "Building Blocks" category in the widget sidebar for enhanced organization and accessibility. - Added functionality to resize building blocks with new horizontal and vertical limits. - Implemented a "see more" button for "Building Blocks" to display all associated widgets. - Enhanced drag and drop functionality for building blocks on the canvas. - **Enhancements** - Improved sorting logic for widgets, prioritizing "Building Blocks". - Enhanced widget search functionality within the sidebar. - **Bug Fixes** - Adjusted default rows and columns settings for explorer building blocks to improve layout and usability. - **Documentation** - Updated messages and constants related to new features for clarity and consistency. - **Refactor** - Refactored drag and drop handling logic to support new building block constraints and features. - Updated application state management to include building blocks related data. --------- Co-authored-by: Anagh Hegde Co-authored-by: Rahul Barwal --- .../ExplorerTests/Widgets_Sidebar.ts | 16 +- .../cypress/support/Pages/EntityExplorer.ts | 2 + app/client/src/api/TemplatesApi.ts | 2 + ...lding-block-explorer-drop-target-arrow.svg | 3 + ...ilding-block-explorer-drop-target-icon.svg | 15 + app/client/src/ce/api/ApplicationApi.tsx | 10 +- .../src/ce/constants/ReduxActionConstants.tsx | 9 +- app/client/src/ce/constants/messages.ts | 1 + app/client/src/ce/reducers/index.tsx | 2 + .../src/ce/reducers/uiReducers/index.tsx | 2 + app/client/src/constants/WidgetConstants.tsx | 8 +- .../common/dropTarget/DropTargetComponent.tsx | 37 +- .../buildingBlockExplorerDropTarget/index.tsx | 71 ++++ .../common/utils/canvasDraggingUtils.ts | 20 +- .../hooks/useCanvasDragging.ts | 20 +- .../Editor/widgetSidebar/SeeMoreButton.tsx | 4 +- .../Editor/widgetSidebar/UIEntityTagGroup.tsx | 22 +- .../src/pages/Editor/widgetSidebar/hooks.ts | 23 +- .../uiReducers/buildingBlockReducer.ts | 42 ++ .../sagas/CanvasSagas/DraggingCanvasSagas.ts | 95 ++++- app/client/src/sagas/WidgetAdditionSagas.ts | 359 +++++++++++++++--- app/client/src/sagas/WidgetOperationUtils.ts | 142 ++++--- .../src/selectors/buildingBlocksSelectors.ts | 4 + .../src/selectors/layoutSystemSelectors.ts | 3 + .../src/selectors/templatesSelectors.tsx | 8 +- app/client/src/widgets/SkeletonWidget.tsx | 15 +- .../server/dtos/BuildingBlockImportDTO.java | 4 + .../partial/PartialImportServiceCEImpl.java | 11 + 28 files changed, 790 insertions(+), 160 deletions(-) create mode 100644 app/client/src/assets/icons/templates/building-block-explorer-drop-target-arrow.svg create mode 100644 app/client/src/assets/icons/templates/building-block-explorer-drop-target-icon.svg create mode 100644 app/client/src/layoutSystems/common/dropTarget/buildingBlockExplorerDropTarget/index.tsx create mode 100644 app/client/src/reducers/uiReducers/buildingBlockReducer.ts create mode 100644 app/client/src/selectors/buildingBlocksSelectors.ts diff --git a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts index 8cb94c4995..11b13c9da6 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts @@ -3,7 +3,6 @@ import { agHelper, locators, } from "../../../../support/Objects/ObjectsCore"; -import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags"; describe( "Entity explorer tests related to widgets and validation", @@ -111,6 +110,11 @@ describe( // check that all widgets are present within their tags const widgetsInThisTag: string[] = []; + // click the see more button for building blocks first to show all widgets + cy.wrap($widgetTag) + .find(entityExplorer._widgetSeeMoreButton) + .click({ force: true }); + cy.wrap($widgetTag) .find(entityExplorer._widgetCardTitle) .each(($widgetName) => { @@ -134,10 +138,10 @@ describe( }); }); - it("3. All widgets should be ordered alphabetically within their tags, except Essential widgets, which should be sorted by their static rank.", () => { + it("3. All widgets other than building blocks should be ordered alphabetically within their tags, except Essential widgets, which should be sorted by their static rank.", () => { agHelper .GetElement( - `${entityExplorer._widgetTagsList}:not(${entityExplorer._widgetTagSuggestedWidgets})`, + `${entityExplorer._widgetTagsList}:not(${entityExplorer._widgetTagSuggestedWidgets}):not(${entityExplorer._widgetTagBuildingBlocks})`, ) .each(($widgetTag) => { const widgetsInThisTag: string[] = []; @@ -192,6 +196,12 @@ describe( agHelper.AssertElementExist(".t--widget-card-draggable-customwidget"); agHelper.ClearTextField(entityExplorer._widgetSearchInput); + // click to show all building blocks + agHelper.GetElement(entityExplorer._widgetTagsList).each(($widgetTag) => { + cy.wrap($widgetTag) + .find(entityExplorer._widgetSeeMoreButton) + .click({ force: true }); + }); agHelper.AssertElementLength( entityExplorer._widgetCards, diff --git a/app/client/cypress/support/Pages/EntityExplorer.ts b/app/client/cypress/support/Pages/EntityExplorer.ts index b96c9dd114..b8760c1d13 100644 --- a/app/client/cypress/support/Pages/EntityExplorer.ts +++ b/app/client/cypress/support/Pages/EntityExplorer.ts @@ -69,6 +69,8 @@ export class EntityExplorer { _widgetSearchInput = "#entity-explorer-search"; _widgetCardTitle = ".t--widget-card-draggable span.ads-v2-text"; _widgetTagSuggestedWidgets = ".widget-tag-collapisble-suggested"; + _widgetTagBuildingBlocks = ".widget-tag-collapisble-building-blocks"; + _widgetSeeMoreButton = "[data-testid='t--explorer-ui-entity-tag-see-more']"; public ActionContextMenuByEntityName({ action = "Delete", diff --git a/app/client/src/api/TemplatesApi.ts b/app/client/src/api/TemplatesApi.ts index bdadb44fde..d7750e89a7 100644 --- a/app/client/src/api/TemplatesApi.ts +++ b/app/client/src/api/TemplatesApi.ts @@ -22,6 +22,8 @@ export interface Template { datasources: string[]; pages: ApplicationPagePayload[]; allowPageImport: boolean; + templateGridColumnSize?: number; + templateGridRowSize?: number; } export type FetchTemplatesResponse = ApiResponse; diff --git a/app/client/src/assets/icons/templates/building-block-explorer-drop-target-arrow.svg b/app/client/src/assets/icons/templates/building-block-explorer-drop-target-arrow.svg new file mode 100644 index 0000000000..0c7860a552 --- /dev/null +++ b/app/client/src/assets/icons/templates/building-block-explorer-drop-target-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/client/src/assets/icons/templates/building-block-explorer-drop-target-icon.svg b/app/client/src/assets/icons/templates/building-block-explorer-drop-target-icon.svg new file mode 100644 index 0000000000..f88168aef6 --- /dev/null +++ b/app/client/src/assets/icons/templates/building-block-explorer-drop-target-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/app/client/src/ce/api/ApplicationApi.tsx b/app/client/src/ce/api/ApplicationApi.tsx index ef1f72ce58..14eea015f5 100644 --- a/app/client/src/ce/api/ApplicationApi.tsx +++ b/app/client/src/ce/api/ApplicationApi.tsx @@ -13,6 +13,7 @@ import type { LayoutSystemTypeConfig, LayoutSystemTypes, } from "layoutSystems/types"; +import type { ActionViewMode } from "entities/Action"; export type EvaluationVersion = number; @@ -267,6 +268,11 @@ export interface ImportBuildingBlockToApplicationRequest { templateId: string; } +export interface ImportBuildingBlockToApplicationResponse { + widgetDsl: string; + onPageLoadActions: Omit[]; +} + export class ApplicationApi extends Api { static baseURL = "v1/applications"; static publishURLPath = (applicationId: string) => @@ -489,7 +495,9 @@ export class ApplicationApi extends Api { static async importBuildingBlockToApplication( request: ImportBuildingBlockToApplicationRequest, - ) { + ): Promise< + AxiosPromise> + > { return Api.post(`${ApplicationApi.baseURL}/import/partial/block`, request); } } diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 6bd845cfce..95dafbb317 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -700,9 +700,10 @@ const ActionTypes = { RESET_TEMPLATE_FILTERS: "RESET_TEMPLATE_FILTERS", SET_TEMPLATE_SEARCH_QUERY: "SET_TEMPLATE_SEARCH_QUERY", IMPORT_TEMPLATE_TO_APPLICATION_INIT: "IMPORT_TEMPLATE_TO_APPLICATION_INIT", - DRAG_BUILDING_BLOCK_TO_CANVAS_INIT: "DRAG_BUILDING_BLOCK_TO_CANVAS_INIT", - DRAG_BUILDING_BLOCK_TO_CANVAS_SUCCESS: - "DRAG_BUILDING_BLOCK_TO_CANVAS_SUCCESS", + DRAGGING_BUILDING_BLOCK_TO_CANVAS_INIT: + "DRAGGING_BUILDING_BLOCK_TO_CANVAS_INIT", + DRAGGING_BUILDING_BLOCK_TO_CANVAS_SUCCESS: + "DRAGGING_BUILDING_BLOCK_TO_CANVAS_SUCCESS", IMPORT_STARTER_BUILDING_BLOCK_TO_APPLICATION_INIT: "IMPORT_STARTER_BUILDING_BLOCK_TO_APPLICATION_INIT", IMPORT_STARTER_TEMPLATE_TO_APPLICATION_SUCCESS: @@ -1094,6 +1095,8 @@ export const ReduxActionErrorTypes = { IMPORT_TEMPLATE_TO_WORKSPACE_ERROR: "IMPORT_TEMPLATE_TO_WORKSPACE_ERROR", IMPORT_STARTER_BUILDING_BLOCK_TO_APPLICATION_ERROR: "IMPORT_STARTER_BUILDING_BLOCK_TO_APPLICATION_ERROR", + DRAGGING_BUILDING_BLOCK_TO_CANVAS_ERROR: + "DRAGGING_BUILDING_BLOCK_TO_CANVAS_ERROR", GET_DEFAULT_PLUGINS_ERROR: "GET_DEFAULT_PLUGINS_ERROR", GET_TEMPLATE_ERROR: "GET_TEMPLATE_ERROR", GET_TEMPLATE_FILTERS_ERROR: "GET_TEMPLATE_FILTERS_ERROR", diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 581af18cd4..16b15c884b 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -2314,6 +2314,7 @@ export const EDITOR_PANE_TEXTS = { js_create_tab_title: () => "Create JS object", queries_create_from_existing: () => "From existing datasource", queries_create_new: () => "New API", + loading_building_blocks: () => "Loading building blocks", }; export const PARTIAL_IMPORT_EXPORT = { diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index f7d25601de..f736df31f0 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -80,6 +80,7 @@ import type { LayoutElementPositionsReduxState } from "layoutSystems/anvil/integ import type { ActiveField } from "reducers/uiReducers/activeFieldEditorReducer"; import type { SelectedWorkspaceReduxState } from "@appsmith/reducers/uiReducers/selectedWorkspaceReducer"; import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; +import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; export const reducerObject = { entities: entityReducer, @@ -104,6 +105,7 @@ export interface AppState { apiPane: ApiPaneReduxState; auth: AuthState; templates: TemplatesReduxState; + buildingBlocks: BuildingBlocksReduxState; workspaces: WorkspaceReduxState; selectedWorkspace: SelectedWorkspaceReduxState; users: UsersReduxState; diff --git a/app/client/src/ce/reducers/uiReducers/index.tsx b/app/client/src/ce/reducers/uiReducers/index.tsx index d08b032fc2..5d5312798d 100644 --- a/app/client/src/ce/reducers/uiReducers/index.tsx +++ b/app/client/src/ce/reducers/uiReducers/index.tsx @@ -8,6 +8,7 @@ import datasourcePaneReducer from "reducers/uiReducers/datasourcePaneReducer"; import authReducer from "reducers/uiReducers/authReducer"; import workspaceReducer from "@appsmith/reducers/uiReducers/workspaceReducer"; import templateReducer from "reducers/uiReducers/templateReducer"; +import buildingBlockReducer from "reducers/uiReducers/buildingBlockReducer"; import usersReducer from "reducers/uiReducers/usersReducer"; import { widgetDraggingReducer } from "reducers/uiReducers/dragResizeReducer"; import importReducer from "reducers/uiReducers/importReducer"; @@ -61,6 +62,7 @@ export const uiReducerObject = { apiPane: apiPaneReducer, auth: authReducer, templates: templateReducer, + buildingBlocks: buildingBlockReducer, workspaces: workspaceReducer, selectedWorkspace: selectedWorkspaceReducer, users: usersReducer, diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx index 2a294be3bf..89ee7deda6 100644 --- a/app/client/src/constants/WidgetConstants.tsx +++ b/app/client/src/constants/WidgetConstants.tsx @@ -228,8 +228,8 @@ export const MAX_MODAL_WIDTH_FROM_MAIN_WIDTH = 0.95; export const FILE_SIZE_LIMIT_FOR_BLOBS = 5000 * 1024; // 5MB export const WIDGET_TAGS = { - SUGGESTED_WIDGETS: "Suggested", BUILDING_BLOCKS: "Building Blocks", + SUGGESTED_WIDGETS: "Suggested", INPUTS: "Inputs", BUTTONS: "Buttons", SELECT: "Select", @@ -265,6 +265,8 @@ export const SUGGESTED_WIDGETS_ORDER: Record = { // Constant key to show walkthrough for a widget -> stores widget id export const WIDGET_ID_SHOW_WALKTHROUGH = "WIDGET_ID_SHOW_WALKTHROUGH"; -export const DEFAULT_ROWS_FOR_EXPLORER_BUILDING_BLOCKS = 30; -export const DEFAULT_COLUMNS_FOR_EXPLORER_BUILDING_BLOCKS = 5; +export const DEFAULT_ROWS_FOR_EXPLORER_BUILDING_BLOCKS = 60; +export const DEFAULT_COLUMNS_FOR_EXPLORER_BUILDING_BLOCKS = 62; +export const BUILDING_BLOCK_MIN_HORIZONTAL_LIMIT = 2000; +export const BUILDING_BLOCK_MIN_VERTICAL_LIMIT = 800; export const BUILDING_BLOCK_EXPLORER_TYPE = "BUILDING_BLOCK"; diff --git a/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx b/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx index 846dc4c1a8..94845b9656 100644 --- a/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx +++ b/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx @@ -47,6 +47,8 @@ import { } from "widgets/WidgetUtils"; import DragLayerComponent from "./DragLayerComponent"; import StarterBuildingBlocks from "./starterBuildingBlocks"; +import BuildingBlockExplorerDropTarget from "./buildingBlockExplorerDropTarget"; +import { isDraggingBuildingBlockToCanvas } from "selectors/buildingBlocksSelectors"; export type DropTargetComponentProps = PropsWithChildren<{ snapColumnSpace: number; @@ -72,40 +74,55 @@ const StyledDropTarget = styled.div` function Onboarding() { const isMobileCanvas = useSelector(getIsMobileCanvasLayout); + const isDraggingBuildingBlock = useSelector(isDraggingBuildingBlockToCanvas); const appState = useCurrentAppState(); const isAirgappedInstance = isAirgapped(); - const showStarterTemplatesInsteadofBlankCanvas = useFeatureFlag( + const showStarterTemplatesInsteadOfBlankCanvas = useFeatureFlag( FEATURE_FLAG.ab_show_templates_instead_of_blank_canvas_enabled, ); - const releaseDragDropBuildingBlocks = useFeatureFlag( + const releaseDragDropBuildingBlocksEnabled = useFeatureFlag( FEATURE_FLAG.release_drag_drop_building_blocks_enabled, ); const shouldShowStarterTemplates = useMemo( () => - showStarterTemplatesInsteadofBlankCanvas && + showStarterTemplatesInsteadOfBlankCanvas && !isMobileCanvas && !isAirgappedInstance && - // This is to hide starter building blocks once building blocks are available in the explorer - !releaseDragDropBuildingBlocks, + !releaseDragDropBuildingBlocksEnabled, // Hide starter templates when drag-drop building blocks are available [ - showStarterTemplatesInsteadofBlankCanvas, + showStarterTemplatesInsteadOfBlankCanvas, isMobileCanvas, isAirgappedInstance, - releaseDragDropBuildingBlocks, + releaseDragDropBuildingBlocksEnabled, ], ); - if (shouldShowStarterTemplates && appState === IDEAppState.EDITOR) + const shouldShowBuildingBlocksDropTarget = useMemo( + () => releaseDragDropBuildingBlocksEnabled && !isDraggingBuildingBlock, + [releaseDragDropBuildingBlocksEnabled, isDraggingBuildingBlock], + ); + + const isEditorState = appState === IDEAppState.EDITOR; + + if (shouldShowStarterTemplates && isEditorState) { return ; - else if (!shouldShowStarterTemplates && appState === IDEAppState.EDITOR) + } else if (shouldShowBuildingBlocksDropTarget && isEditorState) { + return ; + } else if ( + !shouldShowBuildingBlocksDropTarget && + !shouldShowStarterTemplates && + !isDraggingBuildingBlock + ) { return (

Drag and drop a widget here

); - else return null; + } else { + return null; + } } /* diff --git a/app/client/src/layoutSystems/common/dropTarget/buildingBlockExplorerDropTarget/index.tsx b/app/client/src/layoutSystems/common/dropTarget/buildingBlockExplorerDropTarget/index.tsx new file mode 100644 index 0000000000..9ece35309f --- /dev/null +++ b/app/client/src/layoutSystems/common/dropTarget/buildingBlockExplorerDropTarget/index.tsx @@ -0,0 +1,71 @@ +import { importSvg } from "@design-system/widgets-old/src/utils/icon-loadables"; +import { Text } from "design-system"; +import React from "react"; +import styled from "styled-components"; + +const DROP_TARGET_CONTAINER_TOP_MARGIN = 20; +const DROP_TARGET_CONTAINER_LEFT_MARGIN = 50; +const DROP_TARGET_CONTAINER_PADDING = 16; + +export const DropTargetContainer = styled.div` + position: absolute; + top: ${DROP_TARGET_CONTAINER_TOP_MARGIN}px; + display: flex; + flex-direction: column; + height: 100vh; + align-items: flex-start; +`; + +const MainContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + padding: ${DROP_TARGET_CONTAINER_PADDING}px; + margin-left: ${DROP_TARGET_CONTAINER_LEFT_MARGIN}px; +`; + +const TextContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + max-width: 220px; + margin-top: 20px; +`; + +const BuildingBlockExplorerDropTarget = () => { + return ( + + + + + + + Drag & drop a building block + + + + Make a working app in seconds using functional blocks + + + + + + + ); +}; + +const ClickIcon = importSvg( + async () => + import( + "../../../../assets/icons/templates/building-block-explorer-drop-target-icon.svg" + ), +); +const ArrowIcon = importSvg( + async () => + import( + "../../../../assets/icons/templates/building-block-explorer-drop-target-arrow.svg" + ), +); + +export default BuildingBlockExplorerDropTarget; diff --git a/app/client/src/layoutSystems/common/utils/canvasDraggingUtils.ts b/app/client/src/layoutSystems/common/utils/canvasDraggingUtils.ts index edd998c0b4..9899e2ebbd 100644 --- a/app/client/src/layoutSystems/common/utils/canvasDraggingUtils.ts +++ b/app/client/src/layoutSystems/common/utils/canvasDraggingUtils.ts @@ -465,10 +465,12 @@ export const modifyBlockDimension = ( parentBottomRow: number, canExtend: boolean, modifyBlock: boolean, + // this allows dynamic resize limit for building blocks + horizontalMinResizeLimit: number = HORIZONTAL_RESIZE_MIN_LIMIT, + verticalMinResizeLimit: number = VERTICAL_RESIZE_MIN_LIMIT, ) => { const { columnWidth, fixedHeight, height, left, rowHeight, top, width } = draggingBlock; - //get left and top of widget on canvas grid const [leftColumn, topRow] = getDropZoneOffsets( snapColumnSpace, @@ -490,23 +492,23 @@ export const modifyBlockDimension = ( // calculate offsets based on collisions and limits if (leftColumn < 0) { leftOffset = - leftColumn + columnWidth > HORIZONTAL_RESIZE_MIN_LIMIT + leftColumn + columnWidth > horizontalMinResizeLimit ? leftColumn - : HORIZONTAL_RESIZE_MIN_LIMIT - columnWidth; + : horizontalMinResizeLimit - columnWidth; } else if (leftColumn + columnWidth > GridDefaults.DEFAULT_GRID_COLUMNS) { rightOffset = GridDefaults.DEFAULT_GRID_COLUMNS - leftColumn - columnWidth; rightOffset = - columnWidth + rightOffset >= HORIZONTAL_RESIZE_MIN_LIMIT + columnWidth + rightOffset >= horizontalMinResizeLimit ? rightOffset - : HORIZONTAL_RESIZE_MIN_LIMIT - columnWidth; + : horizontalMinResizeLimit - columnWidth; } if (topRow < 0 && fixedHeight === undefined) { topOffset = - topRow + rowHeight > VERTICAL_RESIZE_MIN_LIMIT + topRow + rowHeight > verticalMinResizeLimit ? topRow - : VERTICAL_RESIZE_MIN_LIMIT - rowHeight; + : verticalMinResizeLimit - rowHeight; } if ( @@ -516,9 +518,9 @@ export const modifyBlockDimension = ( ) { bottomOffset = parentBottomRow - topRow - rowHeight; bottomOffset = - rowHeight + bottomOffset >= VERTICAL_RESIZE_MIN_LIMIT + rowHeight + bottomOffset >= verticalMinResizeLimit ? bottomOffset - : VERTICAL_RESIZE_MIN_LIMIT - rowHeight; + : verticalMinResizeLimit - rowHeight; } } diff --git a/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/hooks/useCanvasDragging.ts b/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/hooks/useCanvasDragging.ts index a404caaecb..8fcba5e902 100644 --- a/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/hooks/useCanvasDragging.ts +++ b/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/hooks/useCanvasDragging.ts @@ -1,5 +1,6 @@ import type { OccupiedSpace } from "constants/CanvasEditorConstants"; import { + BUILDING_BLOCK_EXPLORER_TYPE, GridDefaults, MAIN_CONTAINER_WIDGET_ID, } from "constants/WidgetConstants"; @@ -34,6 +35,8 @@ import { useBlocksToBeDraggedOnCanvas } from "./useBlocksToBeDraggedOnCanvas"; import { useRenderBlocksOnCanvas } from "./useRenderBlocksOnCanvas"; import { useCanvasDragToScroll } from "layoutSystems/common/canvasArenas/useCanvasDragToScroll"; import type { FixedCanvasDraggingArenaProps } from "../FixedCanvasDraggingArena"; +import { useSelector } from "react-redux"; +import { getDragDetails } from "sagas/selectors"; /** * useCanvasDragging hook is utilized to handle all drag and drop related functions that are required to give user the sense of dragging and dropping while moving a widget on canvas @@ -63,6 +66,7 @@ export const useCanvasDragging = ( }: FixedCanvasDraggingArenaProps, ) => { const currentDirection = useRef(ReflowDirection.UNSET); + const dragDetails = useSelector(getDragDetails); const { devicePixelRatio: scale = 1 } = window; const { blocksToDraw, @@ -352,8 +356,14 @@ export const useCanvasDragging = ( top: e.offsetY - startPoints.top - parentDiff.top, }; - const drawingBlocks = blocksToDraw.map((each) => - modifyBlockDimension( + const drawingBlocks = blocksToDraw.map((each) => { + let buildingBlockRows; + let buildingBlockColumns; + if (each.type === BUILDING_BLOCK_EXPLORER_TYPE) { + buildingBlockRows = dragDetails.newWidget.rows; + buildingBlockColumns = dragDetails.newWidget.columns; + } + return modifyBlockDimension( { ...each, left: each.left + delta.left, @@ -364,8 +374,10 @@ export const useCanvasDragging = ( rowRef.current - 1, canExtend, false, - ), - ); + buildingBlockColumns, + buildingBlockRows, + ); + }); const newRows = updateRelativeRows(drawingBlocks, rowRef.current); const rowDelta = newRows ? newRows - rowRef.current : 0; rowRef.current = newRows ? newRows : rowRef.current; diff --git a/app/client/src/pages/Editor/widgetSidebar/SeeMoreButton.tsx b/app/client/src/pages/Editor/widgetSidebar/SeeMoreButton.tsx index 82b00a0b69..f9b5d4381a 100644 --- a/app/client/src/pages/Editor/widgetSidebar/SeeMoreButton.tsx +++ b/app/client/src/pages/Editor/widgetSidebar/SeeMoreButton.tsx @@ -9,9 +9,7 @@ interface Props { const SeeMoreButton = (props: Props) => { const SEE_MORE_LESS_TEXT = !props.showSeeLess ? "See more" : "See less"; - const SEE_MORE_ARROW = !props.showSeeLess - ? "arrow-down-s-line" - : "arrow-up-s-line"; + const SEE_MORE_ARROW = !props.showSeeLess ? "down-arrow-2" : "arrow-up-line"; return ( ) : null} @@ -203,7 +205,7 @@ export const generateQuickCommands = ( ? `{{${name}.}}` : `{{${name}}}`, displayText: `${name}`, - className: "CodeMirror-commands", + className: "CodeMirror-commands group relative", data: suggestion, triggerCompletionsPostPick: suggestion.type !== ENTITY_TYPE.ACTION, render: (element: HTMLElement, _: unknown, data: CommandsCompletion) => { diff --git a/app/client/src/globalStyles/CodemirrorHintStyles.ts b/app/client/src/globalStyles/CodemirrorHintStyles.ts index 0be60f7385..658ad56fd5 100644 --- a/app/client/src/globalStyles/CodemirrorHintStyles.ts +++ b/app/client/src/globalStyles/CodemirrorHintStyles.ts @@ -42,9 +42,6 @@ export const CodemirrorHintStyles = createGlobalStyle<{ color: var(--ads-v2-color-fg); } } - .command-suggestion-edit { - background: var(--ads-v2-color-bg-subtle); - } } .CodeMirror-command-header { From e98b824ecd8236c529b32f6542b4eeea2996a53b Mon Sep 17 00:00:00 2001 From: Manish Kumar <107841575+sondermanish@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:01:14 +0530 Subject: [PATCH 13/18] chore: uncommented the fix (#32703) --- .../ServerSchemaMigrationEnforcerTest.java | 9 +- .../server/git/ce-automation-test.json | 87 ------------------- 2 files changed, 3 insertions(+), 93 deletions(-) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java index dca30bd65a..8d9542cd3f 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java @@ -137,12 +137,9 @@ public class ServerSchemaMigrationEnforcerTest { assertThat(exportedApplicationJsonObject.get("theme").getAsJsonObject()) .isEqualTo(importApplicationGitReferenceObject.get("theme").getAsJsonObject()); - /** - * This piece of assertion is commented out because of the flakiness - */ - // verifyMapAssertions( - // exportedApplicationJsonObject.get("actions").getAsJsonObject(), - // importApplicationGitReferenceObject.get("actions").getAsJsonObject()); + verifyMapAssertions( + exportedApplicationJsonObject.get("actions").getAsJsonObject(), + importApplicationGitReferenceObject.get("actions").getAsJsonObject()); verifyMapAssertions( exportedApplicationJsonObject.get("actionBody").getAsJsonObject(), diff --git a/app/server/appsmith-server/src/test/resources/com/appsmith/server/git/ce-automation-test.json b/app/server/appsmith-server/src/test/resources/com/appsmith/server/git/ce-automation-test.json index f346369a4f..39b3207748 100644 --- a/app/server/appsmith-server/src/test/resources/com/appsmith/server/git/ce-automation-test.json +++ b/app/server/appsmith-server/src/test/resources/com/appsmith/server/git/ce-automation-test.json @@ -25358,93 +25358,6 @@ "deleted": false, "gitSyncId": "660d3e57a59c5e33b46bace0_660d3e57a59c5e33b46bad79" }, - { - "pluginType": "JS", - "pluginId": "js-plugin", - "unpublishedAction": { - "name": "cat", - "fullyQualifiedName": "TC4.cat", - "datasource": { - "name": "UNUSED_DATASOURCE", - "pluginId": "js-plugin", - "invalids": [], - "messages": [], - "isAutoGenerated": false, - "deleted": false, - "policies": [], - "userPermissions": [] - }, - "pageId": "Page 2", - "actionConfiguration": { - "timeoutInMillisecond": 10000, - "paginationType": "NONE", - "encodeParamsToggle": true, - "body": "() =>n", - "selfReferencingDataPaths": [], - "jsArguments": [], - "isAsync": false - }, - "executeOnLoad": false, - "dynamicBindingPathList": [ - { - "key": "body" - } - ], - "isValid": true, - "invalids": [], - "messages": [], - "jsonPathKeys": [ - "() =>n" - ], - "userSetOnLoad": false, - "confirmBeforeExecute": false, - "policies": [], - "userPermissions": [], - "createdAt": "2024-04-03T11:32:39Z" - }, - "publishedAction": { - "name": "cat", - "fullyQualifiedName": "TC4.cat", - "datasource": { - "name": "UNUSED_DATASOURCE", - "pluginId": "js-plugin", - "invalids": [], - "messages": [], - "isAutoGenerated": false, - "deleted": false, - "policies": [], - "userPermissions": [] - }, - "pageId": "Page 2", - "actionConfiguration": { - "timeoutInMillisecond": 10000, - "paginationType": "NONE", - "encodeParamsToggle": true, - "body": "() =>n", - "selfReferencingDataPaths": [], - "jsArguments": [], - "isAsync": false - }, - "executeOnLoad": false, - "dynamicBindingPathList": [ - { - "key": "body" - } - ], - "isValid": true, - "invalids": [], - "messages": [], - "jsonPathKeys": [], - "userSetOnLoad": false, - "confirmBeforeExecute": false, - "policies": [], - "userPermissions": [], - "createdAt": "2024-04-03T11:32:39Z" - }, - "id": "Page 2_TC4.cat", - "deleted": false, - "gitSyncId": "660d3e57a59c5e33b46bace0_660d3e57a59c5e33b46bad0f" - }, { "pluginType": "API", "pluginId": "restapi-plugin", From 3ed620e1568f74ebbe292869cf6a2d34a82d249e Mon Sep 17 00:00:00 2001 From: Ankita Kinger Date: Tue, 16 Apr 2024 19:05:07 +0530 Subject: [PATCH 14/18] fix: Updating the ramp link for Enterprise features to open the pricing page (#32698) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Updating the ramp link for Enterprise features to open the pricing page. Fixes [#30211](https://github.com/appsmithorg/appsmith/issues/30211) ## Automation /ok-to-test tags="@tag.Settings" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: b9925ae2ec5a14724586f72affa02a1d83078813 > Cypress dashboard url: Click here! ## Summary by CodeRabbit - **New Features** - Enhanced enterprise-level provisioning and authentication settings across various components. - Added a new Cypress command to improve testing by simulating customer portal interactions. - **Refactor** - Streamlined UI components by adjusting styles and simplifying rendering logic. - Removed redundant spinner components and simplified conditions in various editor components. - **Style** - Updated CSS properties and variables for better consistency and maintainability. - **Tests** - Updated regression tests to reflect new functionalities and page interactions. --- .../AdminSettings/Admin_settings_spec.js | 22 ++++++---- app/client/cypress/support/commands.js | 8 ++++ .../pages/Upgrade/ProvisioningUpgradePage.tsx | 1 + .../editorComponents/ActionNameEditor.tsx | 3 +- .../editorComponents/EditableText.tsx | 32 +++++++-------- .../AdminSettings/Authentication/AuthPage.tsx | 1 + .../pages/AdminSettings/FormGroup/Common.tsx | 18 +++----- .../src/pages/AdminSettings/LeftPane.tsx | 2 +- .../Editor/DataSourceEditor/FormTitle.tsx | 2 - .../Editor/JSEditor/JSObjectNameEditor.tsx | 3 +- app/client/src/utils/hooks/useOnUpgrade.ts | 41 +++++++++++++------ 11 files changed, 77 insertions(+), 56 deletions(-) diff --git a/app/client/cypress/e2e/Regression/Enterprise/AdminSettings/Admin_settings_spec.js b/app/client/cypress/e2e/Regression/Enterprise/AdminSettings/Admin_settings_spec.js index 114649375e..597673d113 100644 --- a/app/client/cypress/e2e/Regression/Enterprise/AdminSettings/Admin_settings_spec.js +++ b/app/client/cypress/e2e/Regression/Enterprise/AdminSettings/Admin_settings_spec.js @@ -95,12 +95,12 @@ describe("Admin settings page", { tags: ["@tag.Settings"] }, function () { cy.get("@pricingPage").should("be.called"); cy.wait(2000); cy.go(-1); - cy.stubPricingPage(); + cy.stubCustomerPortalPage(); cy.get(adminsSettings.branding).click(); cy.url().should("contain", adminSettingsHelper.routes.BRANDING); cy.get(adminsSettings.brandingSubmitButton).should("be.disabled"); cy.xpath(adminsSettings.upgrade).click(); - cy.get("@pricingPage").should("be.called"); + cy.get("@customerPortalPage").should("be.called"); cy.wait(2000); cy.go(-1); } @@ -119,11 +119,14 @@ describe("Admin settings page", { tags: ["@tag.Settings"] }, function () { }); cy.get(adminsSettings.accessControl).click(); cy.url().should("contain", adminSettingsHelper.routes.ACCESS_CONTROL); - cy.stubPricingPage(); + cy.stubCustomerPortalPage(); cy.xpath(adminsSettings.upgrade).click(); - cy.get("@pricingPage").should("be.called"); + cy.get("@customerPortalPage").should("be.called"); cy.wait(2000); - cy.go(-1); + agHelper.VisitNAssert( + adminSettingsHelper.routes.GENERAL, + "getEnvVariables", + ); cy.get(adminsSettings.auditLogs).within(() => { cy.get(adminsSettings.businessTag) .should("exist") @@ -131,11 +134,14 @@ describe("Admin settings page", { tags: ["@tag.Settings"] }, function () { }); cy.get(adminsSettings.auditLogs).click(); cy.url().should("contain", adminSettingsHelper.routes.AUDIT_LOGS); - cy.stubPricingPage(); + cy.stubCustomerPortalPage(); cy.xpath(adminsSettings.upgrade).click(); - cy.get("@pricingPage").should("be.called"); + cy.get("@customerPortalPage").should("be.called"); cy.wait(2000); - cy.go(-1); + agHelper.VisitNAssert( + adminSettingsHelper.routes.GENERAL, + "getEnvVariables", + ); cy.get(adminsSettings.provisioning).within(() => { cy.get(adminsSettings.enterpriseTag) .should("exist") diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js index ce0769a313..a888f44863 100644 --- a/app/client/cypress/support/commands.js +++ b/app/client/cypress/support/commands.js @@ -2076,6 +2076,14 @@ Cypress.Commands.add("stubPricingPage", () => { }); }); +Cypress.Commands.add("stubCustomerPortalPage", () => { + cy.window().then((win) => { + cy.stub(win, "open", (url) => { + win.location.href = "https://customer.appsmith.com?"; + }).as("customerPortalPage"); + }); +}); + /** * @param testID * @returns diff --git a/app/client/src/ce/pages/Upgrade/ProvisioningUpgradePage.tsx b/app/client/src/ce/pages/Upgrade/ProvisioningUpgradePage.tsx index f4d5eda917..42201f84dd 100644 --- a/app/client/src/ce/pages/Upgrade/ProvisioningUpgradePage.tsx +++ b/app/client/src/ce/pages/Upgrade/ProvisioningUpgradePage.tsx @@ -22,6 +22,7 @@ export function ProvisioningUpgradePage() { logEventData: { source: "Provisioning" }, featureName: RampFeature.Provisioning, sectionName: RampSection.AdminSettings, + isEnterprise: true, }); const header: Header = { diff --git a/app/client/src/components/editorComponents/ActionNameEditor.tsx b/app/client/src/components/editorComponents/ActionNameEditor.tsx index 6301f9980f..6339e1c797 100644 --- a/app/client/src/components/editorComponents/ActionNameEditor.tsx +++ b/app/client/src/components/editorComponents/ActionNameEditor.tsx @@ -9,7 +9,7 @@ import { removeSpecialChars } from "utils/helpers"; import type { AppState } from "@appsmith/reducers"; import { saveActionName } from "actions/pluginActionActions"; -import { Flex, Spinner } from "design-system"; +import { Flex } from "design-system"; import { getAction, getPlugin } from "@appsmith/selectors/entitiesSelector"; import NameEditorComponent, { IconBox, @@ -116,7 +116,6 @@ function ActionNameEditor(props: ActionNameEditorProps) { updating={saveStatus.isSaving} valueTransform={removeSpecialChars} /> - {saveStatus.isSaving && } )} diff --git a/app/client/src/components/editorComponents/EditableText.tsx b/app/client/src/components/editorComponents/EditableText.tsx index 7dc9b0ca43..9ca152518c 100644 --- a/app/client/src/components/editorComponents/EditableText.tsx +++ b/app/client/src/components/editorComponents/EditableText.tsx @@ -6,7 +6,7 @@ import { } from "@blueprintjs/core"; import styled from "styled-components"; import _ from "lodash"; -import { Button, toast, Tooltip } from "design-system"; +import { Button, Spinner, toast, Tooltip } from "design-system"; export enum EditInteractionKind { SINGLE, @@ -221,13 +221,8 @@ export function EditableText(props: EditableTextProps) { [valueTransform, isInvalid], ); - const showEditIcon = !( - disabled || - minimal || - hideEditIcon || - updating || - isEditing - ); + const showEditIcon = !(disabled || minimal || hideEditIcon || isEditing); + return ( - {showEditIcon && ( -