fix: git discard if applicationDetail already present (#28307)

This commit is contained in:
Nilansh Bansal 2023-10-24 10:19:39 +05:30 committed by GitHub
parent 5717bccfb6
commit 0a41a781ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 294 additions and 2 deletions

View File

@ -4,6 +4,7 @@ import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.Datasource;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationDetail;
import com.appsmith.server.dtos.ApplicationJson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@ -79,9 +80,36 @@ public class ImportExportUtils {
return "";
}
/**
* This function sets the current applicationDetail properties to null if the user wants to discard the changes
* and accept from the git repo which doesn't contain these.
* @param importedApplicationDetail
* @param existingApplicationDetail
*/
private static void setPropertiesToApplicationDetail(
ApplicationDetail importedApplicationDetail, ApplicationDetail existingApplicationDetail) {
// If the initial commit to git doesn't contain these keys and if we want to discard the changes,
// the function copyNestedNonNullProperties ignore these properties and the changes are not discarded
if (importedApplicationDetail != null && existingApplicationDetail != null) {
if (importedApplicationDetail.getAppPositioning() == null) {
existingApplicationDetail.setAppPositioning(null);
}
if (importedApplicationDetail.getNavigationSetting() == null) {
existingApplicationDetail.setNavigationSetting(null);
}
}
}
public static void setPropertiesToExistingApplication(
Application importedApplication, Application existingApplication) {
importedApplication.setId(existingApplication.getId());
ApplicationDetail importedUnpublishedAppDetail = importedApplication.getUnpublishedApplicationDetail();
ApplicationDetail importedPublishedAppDetail = importedApplication.getPublishedApplicationDetail();
ApplicationDetail existingUnpublishedAppDetail = existingApplication.getUnpublishedApplicationDetail();
ApplicationDetail existingPublishedAppDetail = existingApplication.getPublishedApplicationDetail();
// For the existing application we don't need to default
// value of the flag
// The isPublic flag has a default value as false and this
@ -93,10 +121,10 @@ public class ImportExportUtils {
// These properties are not present in the application when it is created, hence the initial commit
// to git doesn't contain these keys and if we want to discard the changes, the function
// copyNestedNonNullProperties ignore these properties and the changes are not discarded
if (importedApplication.getUnpublishedApplicationDetail() == null) {
if (importedUnpublishedAppDetail == null) {
existingApplication.setUnpublishedApplicationDetail(null);
}
if (importedApplication.getPublishedApplicationDetail() == null) {
if (importedPublishedAppDetail == null) {
existingApplication.setPublishedApplicationDetail(null);
}
if (importedApplication.getPublishedAppLayout() == null) {
@ -106,6 +134,9 @@ public class ImportExportUtils {
existingApplication.setUnpublishedAppLayout(null);
}
setPropertiesToApplicationDetail(importedUnpublishedAppDetail, existingUnpublishedAppDetail);
setPropertiesToApplicationDetail(importedPublishedAppDetail, existingPublishedAppDetail);
copyNestedNonNullProperties(importedApplication, existingApplication);
}

View File

@ -2507,6 +2507,119 @@ public class ImportApplicationServiceTests {
.verifyComplete();
}
/**
* Testcase for checking the discard changes flow for following events:
* 1. Import application in org which has app positioning in applicationDetail already added
* 2. Add Navigation Settings to the imported application
* 3. User tries to import application from same application json file
* 4. Added NavigationSetting will be removed
*/
@Test
@WithUserDetails(value = "api_user")
public void
discardChange_addNavigationSettingAfterAppPositioningAlreadyPresentInImport_addedNavigationSettingRemoved() {
Mono<ApplicationJson> applicationJsonMono =
createAppJson("test_assets/ImportExportServiceTest/valid-application-with-app-positioning.json");
String workspaceId = createTemplateWorkspace().getId();
final Mono<Application> resultMonoWithoutDiscardOperation = applicationJsonMono
.flatMap(applicationJson -> {
applicationJson
.getExportedApplication()
.setName("discard-change-navsettings-added-appPositioning-present");
return importApplicationService.importNewApplicationInWorkspaceFromJson(
workspaceId, applicationJson);
})
.flatMap(application -> {
ApplicationDetail applicationDetail = application.getUnpublishedApplicationDetail();
Application.NavigationSetting navigationSetting = new Application.NavigationSetting();
navigationSetting.setOrientation("top");
applicationDetail.setNavigationSetting(navigationSetting);
application.setUnpublishedApplicationDetail(applicationDetail);
application.setPublishedApplicationDetail(applicationDetail);
return applicationService.save(application);
})
.cache();
StepVerifier.create(resultMonoWithoutDiscardOperation)
.assertNext(initialApplication -> {
assertThat(initialApplication.getUnpublishedApplicationDetail())
.isNotNull();
assertThat(initialApplication
.getUnpublishedApplicationDetail()
.getNavigationSetting())
.isNotNull();
assertThat(initialApplication
.getUnpublishedApplicationDetail()
.getNavigationSetting()
.getOrientation())
.isEqualTo("top");
assertThat(initialApplication.getPublishedApplicationDetail())
.isNotNull();
assertThat(initialApplication
.getPublishedApplicationDetail()
.getNavigationSetting())
.isNotNull();
assertThat(initialApplication
.getPublishedApplicationDetail()
.getNavigationSetting()
.getOrientation())
.isEqualTo("top");
assertThat(initialApplication
.getUnpublishedApplicationDetail()
.getAppPositioning())
.isNotNull();
assertThat(initialApplication
.getUnpublishedApplicationDetail()
.getAppPositioning()
.getType())
.isEqualTo(Application.AppPositioning.Type.AUTO);
assertThat(initialApplication
.getPublishedApplicationDetail()
.getAppPositioning())
.isNotNull();
assertThat(initialApplication
.getPublishedApplicationDetail()
.getAppPositioning()
.getType())
.isEqualTo(Application.AppPositioning.Type.AUTO);
})
.verifyComplete();
// Import the same application again
final Mono<Application> resultMonoWithDiscardOperation = resultMonoWithoutDiscardOperation.flatMap(
importedApplication -> applicationJsonMono.flatMap(applicationJson -> {
importedApplication.setGitApplicationMetadata(new GitApplicationMetadata());
importedApplication
.getGitApplicationMetadata()
.setDefaultApplicationId(importedApplication.getId());
return applicationService
.save(importedApplication)
.then(importApplicationService.importApplicationInWorkspaceFromGit(
importedApplication.getWorkspaceId(),
applicationJson,
importedApplication.getId(),
"main"));
}));
StepVerifier.create(resultMonoWithDiscardOperation)
.assertNext(application -> {
assertThat(application.getWorkspaceId()).isNotNull();
assertThat(application.getUnpublishedApplicationDetail()).isNotNull();
assertThat(application.getPublishedApplicationDetail()).isNotNull();
assertThat(application.getUnpublishedApplicationDetail().getAppPositioning())
.isNotNull();
assertThat(application
.getUnpublishedApplicationDetail()
.getAppPositioning()
.getType())
.isEqualTo(Application.AppPositioning.Type.AUTO);
assertThat(application.getUnpublishedApplicationDetail().getNavigationSetting())
.isNull();
assertThat(application.getPublishedApplicationDetail().getNavigationSetting())
.isNull();
})
.verifyComplete();
}
@Test
@WithUserDetails(value = "api_user")
public void applySchemaMigration_jsonFileWithFirstVersion_migratedToLatestVersionSuccess() {

View File

@ -0,0 +1,148 @@
{
"exportedApplication": {
"name": "Application with ApplicationDetail - App Positioning",
"isPublic": false,
"pages": [
{
"id": "Page1",
"isDefault": true
}
],
"publishedPages": [
{
"id": "Page1",
"isDefault": true
}
],
"viewMode": false,
"appIsExample": false,
"unreadCommentThreads": 0.0,
"unpublishedApplicationDetail": {
"appPositioning": {
"type": "AUTO"
}
},
"color": "#E3DEFF",
"icon": "lotus",
"slug": "untitled-application-1",
"unpublishedCustomJSLibs": [],
"publishedCustomJSLibs": [],
"evaluationVersion": 2.0,
"applicationVersion": 2.0,
"collapseInvisibleWidgets": true,
"isManualUpdate": false,
"deleted": false
},
"datasourceList": [],
"customJSLibList": [],
"pageList": [
{
"unpublishedPage": {
"name": "Page1",
"slug": "page1",
"layouts": [
{
"viewMode": false,
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 4896.0,
"snapColumns": 64.0,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0.0,
"bottomRow": 5000.0,
"containerStyle": "none",
"snapRows": 124.0,
"parentRowSpace": 1.0,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 87.0,
"minHeight": 1292.0,
"useAutoLayout": true,
"dynamicTriggerPathList": [],
"parentColumnSpace": 1.0,
"responsiveBehavior": "fill",
"dynamicBindingPathList": [],
"leftColumn": 0.0,
"children": [],
"positioning": "vertical",
"flexLayers": []
},
"layoutOnLoadActions": [],
"layoutOnLoadActionErrors": [],
"validOnPageLoadActions": true,
"id": "Page1",
"deleted": false,
"policies": [],
"userPermissions": []
}
],
"userPermissions": [],
"policies": []
},
"publishedPage": {
"name": "Page1",
"slug": "page1",
"layouts": [
{
"viewMode": false,
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 1224.0,
"snapColumns": 16.0,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0.0,
"bottomRow": 1250.0,
"containerStyle": "none",
"snapRows": 33.0,
"parentRowSpace": 1.0,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 4.0,
"minHeight": 1292.0,
"dynamicTriggerPathList": [],
"parentColumnSpace": 1.0,
"dynamicBindingPathList": [],
"leftColumn": 0.0,
"children": []
},
"validOnPageLoadActions": true,
"id": "Page1",
"deleted": false,
"policies": [],
"userPermissions": []
}
],
"userPermissions": [],
"policies": []
},
"deleted": false,
"gitSyncId": "65367d79e575c11b12c0ec77_65367d79e575c11b12c0ec79"
}
],
"actionList": [],
"actionCollectionList": [],
"updatedResources": {
"customJSLibList": [],
"actionList": [],
"pageList": [
"Page1"
],
"actionCollectionList": []
},
"editModeTheme": {
"name": "Default-New",
"displayName": "Modern",
"isSystemTheme": true,
"deleted": false
},
"publishedTheme": {
"name": "Default-New",
"displayName": "Modern",
"isSystemTheme": true,
"deleted": false
}
}