Skip to content

Commit 44d6152

Browse files
tomjose92abhvsn
andauthored
feat(backend): sort applications and workspaces alphabetically (#41253)
## Description Made changes in backend to sort applications and workspaces in alphabetic order Also added feature flag control to this functionality. Fixes #31108 ## Automation /test Workspace ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/17998282833> > Commit: ff76753 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=17998282833&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Workspace` > Spec: > <hr>Thu, 25 Sep 2025 06:09:23 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Optional alphabetical ordering for workspaces and applications on the Home page, toggleable via a new feature flag. * Home view now chooses between case-insensitive alphabetical sorting and the existing “recently used” ordering based on that flag. * **Tests** * Added automated tests verifying alphabetical workspace ordering and exact name sequencing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Abhijeet <abhi.nagarnaik@gmail.com>
1 parent e742df0 commit 44d6152

File tree

11 files changed

+170
-10
lines changed

11 files changed

+170
-10
lines changed

app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public enum FeatureFlagEnum {
3131
release_git_autocommit_eligibility_enabled,
3232
release_dynamodb_connection_time_to_live_enabled,
3333
release_reactive_actions_enabled,
34+
/**
35+
* Feature flag to enable alphabetical ordering for workspaces and applications
36+
*/
37+
release_alphabetical_ordering_enabled,
3438

3539
// Add EE flags below this line, to avoid conflicts.
3640
}

app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceCE.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public interface ApplicationServiceCE extends CrudService<Application, String> {
2929

3030
Flux<Application> findByWorkspaceIdAndBaseApplicationsInRecentlyUsedOrder(String workspaceId);
3131

32+
Flux<Application> findByWorkspaceIdAndBaseApplicationsInAlphabeticalOrder(String workspaceId);
33+
34+
Flux<Application> findByWorkspaceIdAndBaseApplicationsForHome(String workspaceId);
35+
3236
Mono<Application> save(Artifact application);
3337

3438
Mono<Application> updateApplicationWithPresets(String branchedApplicationId, Application application);

app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceCEImpl.java

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.appsmith.server.applications.base;
22

3+
import com.appsmith.external.enums.FeatureFlagEnum;
34
import com.appsmith.external.models.ActionDTO;
45
import com.appsmith.external.models.Policy;
56
import com.appsmith.server.acl.AclPermission;
@@ -36,6 +37,7 @@
3637
import com.appsmith.server.services.AnalyticsService;
3738
import com.appsmith.server.services.AssetService;
3839
import com.appsmith.server.services.BaseService;
40+
import com.appsmith.server.services.FeatureFlagService;
3941
import com.appsmith.server.services.PermissionGroupService;
4042
import com.appsmith.server.services.SessionUserService;
4143
import com.appsmith.server.services.UserDataService;
@@ -59,6 +61,7 @@
5961

6062
import java.time.Instant;
6163
import java.util.ArrayList;
64+
import java.util.Comparator;
6265
import java.util.HashMap;
6366
import java.util.HashSet;
6467
import java.util.List;
@@ -90,6 +93,7 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
9093
private final WorkspaceService workspaceService;
9194
private final WorkspacePermission workspacePermission;
9295
private final ObservationRegistry observationRegistry;
96+
private final FeatureFlagService featureFlagService;
9397

9498
private static final Integer MAX_RETRIES = 5;
9599

@@ -108,7 +112,8 @@ public ApplicationServiceCEImpl(
108112
UserDataService userDataService,
109113
WorkspaceService workspaceService,
110114
WorkspacePermission workspacePermission,
111-
ObservationRegistry observationRegistry) {
115+
ObservationRegistry observationRegistry,
116+
FeatureFlagService featureFlagService) {
112117

113118
super(validator, repository, analyticsService);
114119
this.policySolution = policySolution;
@@ -122,6 +127,7 @@ public ApplicationServiceCEImpl(
122127
this.workspaceService = workspaceService;
123128
this.workspacePermission = workspacePermission;
124129
this.observationRegistry = observationRegistry;
130+
this.featureFlagService = featureFlagService;
125131
}
126132

127133
@Override
@@ -214,6 +220,63 @@ public Flux<Application> findByWorkspaceIdAndBaseApplicationsInRecentlyUsedOrder
214220
})));
215221
}
216222

223+
/**
224+
* This method is used to fetch all the applications for a given workspaceId. It sorts the applications in
225+
* alphabetical order by name.
226+
* For git connected applications only default branched application is returned.
227+
*
228+
* @param workspaceId workspaceId for which applications are to be fetched
229+
* @return Flux of applications sorted alphabetically
230+
*/
231+
@Override
232+
public Flux<Application> findByWorkspaceIdAndBaseApplicationsInAlphabeticalOrder(String workspaceId) {
233+
234+
if (!StringUtils.hasLength(workspaceId)) {
235+
return Flux.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.WORKSPACE_ID));
236+
}
237+
238+
// Read the workspace
239+
Mono<Workspace> workspaceMono = workspaceService
240+
.findById(workspaceId, workspacePermission.getReadPermission())
241+
.switchIfEmpty(Mono.error(
242+
new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)));
243+
244+
return workspaceMono.thenMany(this.findByWorkspaceId(workspaceId, applicationPermission.getReadPermission())
245+
.sort(Comparator.comparing(application -> application.getName().toLowerCase()))
246+
.filter(application -> {
247+
/*
248+
* Filter applications based on the following criteria:
249+
* - Applications that are not connected to Git.
250+
* - Applications that, when connected, revert with default branch only.
251+
*/
252+
return !GitUtils.isArtifactConnectedToGit(application.getGitArtifactMetadata())
253+
|| GitUtils.isDefaultBranchedArtifact(application.getGitArtifactMetadata());
254+
}));
255+
}
256+
257+
/**
258+
* This method is used to fetch all the applications for a given workspaceId. It sorts the applications based
259+
* on feature flag - either alphabetically or by recently used order.
260+
* For git connected applications only default branched application is returned.
261+
*
262+
* @param workspaceId workspaceId for which applications are to be fetched
263+
* @return Flux of applications sorted based on feature flag
264+
*/
265+
@Override
266+
public Flux<Application> findByWorkspaceIdAndBaseApplicationsForHome(String workspaceId) {
267+
Mono<Boolean> isAlphabeticalOrderingEnabled =
268+
featureFlagService.check(FeatureFlagEnum.release_alphabetical_ordering_enabled);
269+
return isAlphabeticalOrderingEnabled.flatMapMany(isEnabled -> {
270+
if (isEnabled) {
271+
// If alphabetical ordering is enabled, then we need to sort the applications in alphabetical order
272+
return findByWorkspaceIdAndBaseApplicationsInAlphabeticalOrder(workspaceId);
273+
} else {
274+
// If alphabetical ordering is disabled, then we need to sort the applications in recently used order
275+
return findByWorkspaceIdAndBaseApplicationsInRecentlyUsedOrder(workspaceId);
276+
}
277+
});
278+
}
279+
217280
@Override
218281
public Mono<Application> save(Artifact artifact) {
219282
Application application = (Application) artifact;

app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.appsmith.server.repositories.NewActionRepository;
77
import com.appsmith.server.services.AnalyticsService;
88
import com.appsmith.server.services.AssetService;
9+
import com.appsmith.server.services.FeatureFlagService;
910
import com.appsmith.server.services.PermissionGroupService;
1011
import com.appsmith.server.services.SessionUserService;
1112
import com.appsmith.server.services.UserDataService;
@@ -39,7 +40,8 @@ public ApplicationServiceImpl(
3940
UserDataService userDataService,
4041
WorkspaceService workspaceService,
4142
WorkspacePermission workspacePermission,
42-
ObservationRegistry observationRegistry) {
43+
ObservationRegistry observationRegistry,
44+
FeatureFlagService featureFlagService) {
4345
super(
4446
validator,
4547
repository,
@@ -54,6 +56,7 @@ public ApplicationServiceImpl(
5456
userDataService,
5557
workspaceService,
5658
workspacePermission,
57-
observationRegistry);
59+
observationRegistry,
60+
featureFlagService);
5861
}
5962
}

app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public Mono<ResponseDTO<Application>> delete(@PathVariable String branchedApplic
130130
public Mono<ResponseDTO<List<Application>>> findByWorkspaceIdAndRecentlyUsedOrder(
131131
@RequestParam(required = false) String workspaceId) {
132132
log.debug("Going to get all applications by workspace id {}", workspaceId);
133-
return service.findByWorkspaceIdAndBaseApplicationsInRecentlyUsedOrder(workspaceId)
133+
return service.findByWorkspaceIdAndBaseApplicationsForHome(workspaceId)
134134
.collectList()
135135
.map(applications -> new ResponseDTO<>(HttpStatus.OK, applications));
136136
}

app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/WorkspaceControllerCE.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public Mono<ResponseDTO<Workspace>> deleteLogo(@PathVariable String workspaceId)
107107
@GetMapping("/home")
108108
public Mono<ResponseDTO<List<Workspace>>> workspacesForHome() {
109109
return userWorkspaceService
110-
.getUserWorkspacesByRecentlyUsedOrder()
110+
.getUserWorkspacesForHome()
111111
.map(workspaces -> new ResponseDTO<>(HttpStatus.OK, workspaces));
112112
}
113113
}

app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserWorkspaceServiceImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public UserWorkspaceServiceImpl(
1919
PermissionGroupService permissionGroupService,
2020
OrganizationService organizationService,
2121
WorkspacePermission workspacePermission,
22-
PermissionGroupPermission permissionGroupPermission) {
22+
PermissionGroupPermission permissionGroupPermission,
23+
FeatureFlagService featureFlagService) {
2324

2425
super(
2526
sessionUserService,
@@ -29,6 +30,7 @@ public UserWorkspaceServiceImpl(
2930
permissionGroupService,
3031
organizationService,
3132
workspacePermission,
32-
permissionGroupPermission);
33+
permissionGroupPermission,
34+
featureFlagService);
3335
}
3436
}

app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCE.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ Mono<MemberInfoDTO> updatePermissionGroupForMember(
2525
Mono<Boolean> isLastAdminRoleEntity(PermissionGroup permissionGroup);
2626

2727
Mono<List<Workspace>> getUserWorkspacesByRecentlyUsedOrder();
28+
29+
Mono<List<Workspace>> getUserWorkspacesInAlphabeticalOrder();
30+
31+
Mono<List<Workspace>> getUserWorkspacesForHome();
2832
}

app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.appsmith.server.services.ce;
22

3+
import com.appsmith.external.enums.FeatureFlagEnum;
34
import com.appsmith.server.constants.FieldName;
45
import com.appsmith.server.domains.PermissionGroup;
56
import com.appsmith.server.domains.User;
@@ -13,6 +14,7 @@
1314
import com.appsmith.server.exceptions.AppsmithException;
1415
import com.appsmith.server.helpers.AppsmithComparators;
1516
import com.appsmith.server.repositories.UserRepository;
17+
import com.appsmith.server.services.FeatureFlagService;
1618
import com.appsmith.server.services.OrganizationService;
1719
import com.appsmith.server.services.PermissionGroupService;
1820
import com.appsmith.server.services.SessionUserService;
@@ -32,6 +34,7 @@
3234
import java.util.ArrayList;
3335
import java.util.Collection;
3436
import java.util.Collections;
37+
import java.util.Comparator;
3538
import java.util.HashSet;
3639
import java.util.List;
3740
import java.util.Map;
@@ -54,6 +57,7 @@ public class UserWorkspaceServiceCEImpl implements UserWorkspaceServiceCE {
5457
private final OrganizationService organizationService;
5558
private final WorkspacePermission workspacePermission;
5659
private final PermissionGroupPermission permissionGroupPermission;
60+
private final FeatureFlagService featureFlagService;
5761

5862
@Autowired
5963
public UserWorkspaceServiceCEImpl(
@@ -64,7 +68,8 @@ public UserWorkspaceServiceCEImpl(
6468
PermissionGroupService permissionGroupService,
6569
OrganizationService organizationService,
6670
WorkspacePermission workspacePermission,
67-
PermissionGroupPermission permissionGroupPermission) {
71+
PermissionGroupPermission permissionGroupPermission,
72+
FeatureFlagService featureFlagService) {
6873
this.sessionUserService = sessionUserService;
6974
this.workspaceService = workspaceService;
7075
this.userRepository = userRepository;
@@ -73,6 +78,7 @@ public UserWorkspaceServiceCEImpl(
7378
this.organizationService = organizationService;
7479
this.workspacePermission = workspacePermission;
7580
this.permissionGroupPermission = permissionGroupPermission;
81+
this.featureFlagService = featureFlagService;
7682
}
7783

7884
@Override
@@ -419,4 +425,39 @@ public Mono<List<Workspace>> getUserWorkspacesByRecentlyUsedOrder() {
419425
// collect to list to keep the order of the workspaces
420426
.collectList());
421427
}
428+
429+
/*
430+
* Returns a list of workspaces for the current user, sorted in alphabetical order.
431+
*
432+
* @return Mono containing the list of workspaces
433+
*/
434+
@Override
435+
public Mono<List<Workspace>> getUserWorkspacesInAlphabeticalOrder() {
436+
return workspaceService
437+
.getAll(workspacePermission.getReadPermission())
438+
.sort(Comparator.comparing(workspace -> workspace.getName().toLowerCase()))
439+
.collectList();
440+
}
441+
442+
/**
443+
* Returns a list of workspaces for the current user, sorted based on feature flag.
444+
* If alphabetical ordering is enabled, returns workspaces in alphabetical order.
445+
* Otherwise, returns workspaces in recently used order.
446+
*
447+
* @return Mono containing the list of workspaces
448+
*/
449+
@Override
450+
public Mono<List<Workspace>> getUserWorkspacesForHome() {
451+
Mono<Boolean> isAlphabeticalOrderingEnabled =
452+
featureFlagService.check(FeatureFlagEnum.release_alphabetical_ordering_enabled);
453+
return isAlphabeticalOrderingEnabled.flatMap(isEnabled -> {
454+
if (isEnabled) {
455+
// If alphabetical ordering is enabled, then we need to sort the workspaces in alphabetical order
456+
return getUserWorkspacesInAlphabeticalOrder();
457+
} else {
458+
// If alphabetical ordering is disabled, then we need to sort the workspaces in recently used order
459+
return getUserWorkspacesByRecentlyUsedOrder();
460+
}
461+
});
462+
}
422463
}

app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatibleImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.appsmith.server.repositories.NewActionRepository;
66
import com.appsmith.server.services.AnalyticsService;
77
import com.appsmith.server.services.AssetService;
8+
import com.appsmith.server.services.FeatureFlagService;
89
import com.appsmith.server.services.PermissionGroupService;
910
import com.appsmith.server.services.SessionUserService;
1011
import com.appsmith.server.services.UserDataService;
@@ -34,7 +35,8 @@ public ApplicationServiceCECompatibleImpl(
3435
UserDataService userDataService,
3536
WorkspaceService workspaceService,
3637
WorkspacePermission workspacePermission,
37-
ObservationRegistry observationRegistry) {
38+
ObservationRegistry observationRegistry,
39+
FeatureFlagService featureFlagService) {
3840
super(
3941
validator,
4042
repository,
@@ -49,6 +51,7 @@ public ApplicationServiceCECompatibleImpl(
4951
userDataService,
5052
workspaceService,
5153
workspacePermission,
52-
observationRegistry);
54+
observationRegistry,
55+
featureFlagService);
5356
}
5457
}

0 commit comments

Comments
 (0)