From c8bd0a89ef8261fb3fcfcca2b478ae4082b43ac2 Mon Sep 17 00:00:00 2001 From: Houssem Ben Ali Date: Wed, 6 Jul 2022 10:38:30 +0200 Subject: [PATCH 01/13] Create develop-meed and update project dependencies --- component/api/pom.xml | 2 +- component/common/pom.xml | 2 +- component/core/pom.xml | 2 +- component/notification/pom.xml | 2 +- component/oauth-auth/pom.xml | 2 +- component/pom.xml | 2 +- component/service/pom.xml | 2 +- component/web/pom.xml | 2 +- pom.xml | 6 +++--- webapp/pom.xml | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/component/api/pom.xml b/component/api/pom.xml index 3fdbf9870eb..b9444394b41 100644 --- a/component/api/pom.xml +++ b/component/api/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT social-component-api Meeds:: PLF:: Social API diff --git a/component/common/pom.xml b/component/common/pom.xml index dddb27fadf8..b675c19e370 100644 --- a/component/common/pom.xml +++ b/component/common/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT io.meeds.social social-component-common diff --git a/component/core/pom.xml b/component/core/pom.xml index e75a848164e..738ae7dddb8 100644 --- a/component/core/pom.xml +++ b/component/core/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT social-component-core Meeds:: PLF:: Social Core Component diff --git a/component/notification/pom.xml b/component/notification/pom.xml index 72b6dd56df5..0716c9e5cd0 100644 --- a/component/notification/pom.xml +++ b/component/notification/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT social-component-notification Meeds:: PLF:: Social Notification Component diff --git a/component/oauth-auth/pom.xml b/component/oauth-auth/pom.xml index 591158ac305..ad85b8a2c16 100644 --- a/component/oauth-auth/pom.xml +++ b/component/oauth-auth/pom.xml @@ -21,7 +21,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT 4.0.0 diff --git a/component/pom.xml b/component/pom.xml index 63dcb49e411..1f0657864a5 100644 --- a/component/pom.xml +++ b/component/pom.xml @@ -22,7 +22,7 @@ social io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT social-component pom diff --git a/component/service/pom.xml b/component/service/pom.xml index da2e45ade74..5167afd1837 100644 --- a/component/service/pom.xml +++ b/component/service/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT social-component-service Meeds:: PLF:: Social Service Component diff --git a/component/web/pom.xml b/component/web/pom.xml index 13ed2ddf082..112a16c62be 100644 --- a/component/web/pom.xml +++ b/component/web/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT io.meeds.social social-component-web diff --git a/pom.xml b/pom.xml index d2b3c2cc99b..a6a1e752bc0 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ io.meeds.social social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT pom Meeds:: PLF:: Social Meeds Social - Enterprise Social Networking @@ -45,8 +45,8 @@ - 7.1.x-SNAPSHOT - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT + 7.1.x-meed-SNAPSHOT meeds-io diff --git a/webapp/pom.xml b/webapp/pom.xml index f76bd84cd5c..e0ce0ef0d39 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -22,7 +22,7 @@ io.meeds.social social - 7.1.x-SNAPSHOT + 7.1.x-meed-SNAPSHOT social-webapp war From 3c99437b2931fb1d836146605e575d067636d86f Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Tue, 29 Jul 2025 10:56:48 +0100 Subject: [PATCH 02/13] feat: add search sort selection - MEED-9498 - Meeds-io/MIPs#212 (#5075) --- .../locale/portlet/Portlets_en.properties | 4 + .../search/components/SearchResults.vue | 17 ++++ .../SearchFavoriteSelector.vue} | 0 .../{ => searchOptions}/SearchOptions.vue | 1 + .../SearchSelectedSpaceItem.vue | 0 .../searchOptions/SearchSortSelector.vue | 78 +++++++++++++++++++ .../SearchSpaceSelector.vue | 0 .../{ => searchOptions}/SearchTagList.vue | 0 .../{ => searchOptions}/SearchTagSelector.vue | 0 .../webapp/vue-apps/search/initComponents.js | 16 ++-- 10 files changed, 109 insertions(+), 7 deletions(-) rename webapp/src/main/webapp/vue-apps/search/components/{searchFavoriteSelector.vue => searchOptions/SearchFavoriteSelector.vue} (100%) rename webapp/src/main/webapp/vue-apps/search/components/{ => searchOptions}/SearchOptions.vue (98%) rename webapp/src/main/webapp/vue-apps/search/components/{ => searchOptions}/SearchSelectedSpaceItem.vue (100%) create mode 100644 webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue rename webapp/src/main/webapp/vue-apps/search/components/{ => searchOptions}/SearchSpaceSelector.vue (100%) rename webapp/src/main/webapp/vue-apps/search/components/{ => searchOptions}/SearchTagList.vue (100%) rename webapp/src/main/webapp/vue-apps/search/components/{ => searchOptions}/SearchTagSelector.vue (100%) diff --git a/webapp/src/main/resources/locale/portlet/Portlets_en.properties b/webapp/src/main/resources/locale/portlet/Portlets_en.properties index 98968bad03c..057a15d8aa0 100644 --- a/webapp/src/main/resources/locale/portlet/Portlets_en.properties +++ b/webapp/src/main/resources/locale/portlet/Portlets_en.properties @@ -718,6 +718,10 @@ activity.noComments=No comment yet activity.window.title=Activity: {0} activity.label=activity activity.reactions.seeMore=See more +search.sort.by.relevancy=Best +search.sort.by.date=Last +search.sort.by.relevancy.option=Best matches +search.sort.by.date.option=Last edited: Newest first ##################################################################################### # Textarea # diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue index d19b72b1d28..78968ecb71e 100644 --- a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue +++ b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue @@ -77,6 +77,8 @@ export default { searching: 0, abortController: null, searchInitialized: false, + sortBy: '', + sortDescending: true, }), computed: { hasMore() { @@ -188,6 +190,12 @@ export default { this.search(); } }, + sortBy() { + this.totalSize = 0; + if (this.searchInitialized) { + this.$nextTick().then(this.search); + } + } }, created() { this.$root.$on('refresh', (searchConnector, favorites) => { @@ -218,10 +226,12 @@ export default { } this.$root.$on('spaces-changed', this.selectSpaces); this.$root.$on('favorites-changed', this.selectFavorites); + this.$root.$on('sort-changed', this.selectSort); }, beforeDestroy() { this.$root.$off('spaces-changed', this.selectSpaces); this.$root.$off('favorites-changed', this.selectFavorites); + this.$root.$off('sort-changed', this.selectSort); }, methods: { selectFavorites() { @@ -238,6 +248,10 @@ export default { selectSpaces(spaces) { this.selectedSpaces = spaces || []; }, + selectSort(option, sortDescending) { + this.sortBy = option?.value || ''; + this.sortDescending = sortDescending; + }, selectAllConnector() { if (this.allEnabled) { return; @@ -358,6 +372,9 @@ export default { uri += `&spaceId=${spaceId}`; }); } + if (this.sortBy) { + uri += `&sortBy=${this.sortBy}&sortDescending=${this.sortDescending}`; + } const fetchResultsQuery = connectorModule.fetchSearchResult ? connectorModule.fetchSearchResult(uri, options) : fetch(uri, options); diff --git a/webapp/src/main/webapp/vue-apps/search/components/searchFavoriteSelector.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchFavoriteSelector.vue similarity index 100% rename from webapp/src/main/webapp/vue-apps/search/components/searchFavoriteSelector.vue rename to webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchFavoriteSelector.vue diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchOptions.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchOptions.vue similarity index 98% rename from webapp/src/main/webapp/vue-apps/search/components/SearchOptions.vue rename to webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchOptions.vue index 2e6c92f8c77..42b241bcd66 100644 --- a/webapp/src/main/webapp/vue-apps/search/components/SearchOptions.vue +++ b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchOptions.vue @@ -99,6 +99,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchSelectedSpaceItem.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSelectedSpaceItem.vue similarity index 100% rename from webapp/src/main/webapp/vue-apps/search/components/SearchSelectedSpaceItem.vue rename to webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSelectedSpaceItem.vue diff --git a/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue new file mode 100644 index 00000000000..0e353f67363 --- /dev/null +++ b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue @@ -0,0 +1,78 @@ + + + + \ No newline at end of file diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchSpaceSelector.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSpaceSelector.vue similarity index 100% rename from webapp/src/main/webapp/vue-apps/search/components/SearchSpaceSelector.vue rename to webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSpaceSelector.vue diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchTagList.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchTagList.vue similarity index 100% rename from webapp/src/main/webapp/vue-apps/search/components/SearchTagList.vue rename to webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchTagList.vue diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchTagSelector.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchTagSelector.vue similarity index 100% rename from webapp/src/main/webapp/vue-apps/search/components/SearchTagSelector.vue rename to webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchTagSelector.vue diff --git a/webapp/src/main/webapp/vue-apps/search/initComponents.js b/webapp/src/main/webapp/vue-apps/search/initComponents.js index 9b434e74302..70bcc225ee1 100644 --- a/webapp/src/main/webapp/vue-apps/search/initComponents.js +++ b/webapp/src/main/webapp/vue-apps/search/initComponents.js @@ -3,13 +3,14 @@ import SearchToolbar from './components/SearchToolbar.vue'; import SearchDrawer from './components/SearchDrawer.vue'; import SearchResults from './components/SearchResults.vue'; import SearchResultCard from './components/SearchResultCard.vue'; -import SearchTagSelector from './components/SearchTagSelector.vue'; -import SearchTagList from './components/SearchTagList.vue'; -import SearchOptions from './components/SearchOptions.vue'; +import SearchTagSelector from './components/searchOptions/SearchTagSelector.vue'; +import SearchTagList from './components/searchOptions/SearchTagList.vue'; +import SearchOptions from './components/searchOptions/SearchOptions.vue'; import SearchResultCardGroup from './components/SearchResultCardGroup.vue'; -import SearchSpaceSelector from './components/SearchSpaceSelector.vue'; -import SearchFavoriteSelector from './components/searchFavoriteSelector.vue'; -import SearchSelectedSpaceItem from './components/SearchSelectedSpaceItem.vue'; +import SearchSpaceSelector from './components/searchOptions/SearchSpaceSelector.vue'; +import SearchFavoriteSelector from './components/searchOptions/SearchFavoriteSelector.vue'; +import SearchSelectedSpaceItem from './components/searchOptions/SearchSelectedSpaceItem.vue'; +import SearchSortSelector from './components/searchOptions/SearchSortSelector.vue'; const components = { 'search-application': SearchApplication, @@ -23,7 +24,8 @@ const components = { 'search-result-card-group': SearchResultCardGroup, 'search-favorites-selector': SearchFavoriteSelector, 'search-space-selector': SearchSpaceSelector, - 'search-selected-space-item': SearchSelectedSpaceItem + 'search-selected-space-item': SearchSelectedSpaceItem, + 'search-sort-selector': SearchSortSelector }; for (const key in components) { From a037a790fa3d295675f17dd110170edddea52881 Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Wed, 30 Jul 2025 08:36:43 +0100 Subject: [PATCH 03/13] feat: Enable sorting by last update in Activity search - MEED-9499 - Meeds-io/MIPs#212 (#5078) --- .../activity/filter/ActivitySearchFilter.java | 4 +++ .../jpa/search/ActivitySearchConnector.java | 36 +++++++++++++++++-- .../rest/impl/activity/ActivityRest.java | 9 ++++- .../search/activities-search-query.json | 3 ++ .../search/components/SearchResults.vue | 2 +- 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/component/core/src/main/java/org/exoplatform/social/core/activity/filter/ActivitySearchFilter.java b/component/core/src/main/java/org/exoplatform/social/core/activity/filter/ActivitySearchFilter.java index aa8a6a95d74..7304ce49436 100644 --- a/component/core/src/main/java/org/exoplatform/social/core/activity/filter/ActivitySearchFilter.java +++ b/component/core/src/main/java/org/exoplatform/social/core/activity/filter/ActivitySearchFilter.java @@ -39,6 +39,10 @@ public class ActivitySearchFilter { private boolean favorites; + private String sortField; + + private String sortDirection; + public ActivitySearchFilter(String term) { this.term = term; } diff --git a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ActivitySearchConnector.java b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ActivitySearchConnector.java index 280f7e86c60..1a53831156f 100644 --- a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ActivitySearchConnector.java +++ b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ActivitySearchConnector.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -82,7 +81,7 @@ public class ActivitySearchConnector { " }" + "},"; - public static final String CATEGORY_IDS_QUERY = """ + public static final String CATEGORY_IDS_QUERY = """ { "terms":{ "categoryId": [@categoryIds@] @@ -90,6 +89,23 @@ public class ActivitySearchConnector { } """; + public static final String DEFAULT_SORTING_QUERY = """ + { + "_score": { + "order": "desc" + } + } + """; + + public static final String SORTING_QUERY = """ + { + "@sortField@": { + "order": "@sortOrder@" + } + }, + "_score" + """; + private static final String TERM_REPLACEMENT = "@term@"; private static final String PHRASE_REPLACEMENT = "@phrase@"; @@ -185,11 +201,13 @@ private String buildQueryStatement(Set streamFeedOwnerIds, String favoriteQuery = buildFavoriteQueryStatement(metadataFilters.get(FavoriteService.METADATA_TYPE.getName())); String tagsQuery = buildTagsQueryStatement(metadataFilters.get(TagService.METADATA_TYPE.getName())); String categoryQuery = buildCategoryIdQueryStatement(filter); + String sortQuery = buildSortQueryStatement(filter); return retrieveSearchQuery().replace("@term_query@", termQuery) .replace("@favorite_query@", favoriteQuery) .replace("@tags_query@", tagsQuery) .replace("@category_query@", categoryQuery) .replace("@permissions@", StringUtils.join(streamFeedOwnerIds, ",")) + .replace("@sortQuery@", sortQuery) .replace("@offset@", String.valueOf(offset)) .replace("@limit@", String.valueOf(limit)); } @@ -429,6 +447,20 @@ private String buildTermQueryStatement(String phrase) { } } + private String buildSortQueryStatement(ActivitySearchFilter filter) { + String sortFiled = filter.getSortField(); + String sortDirection = filter.getSortDirection(); + + if (StringUtils.isBlank(sortFiled)) { + return DEFAULT_SORTING_QUERY; + } + + return switch (sortFiled) { + case "date" -> SORTING_QUERY.replace("@sortField@", "lastUpdatedDate").replace("@sortOrder@", sortDirection); + default -> SORTING_QUERY.replace("@sortField@", sortFiled).replace("@sortOrder@", sortDirection); + }; + } + private Long parseLong(JSONObject hitSource, String key) { String value = (String) hitSource.get(key); return StringUtils.isBlank(value) ? null : Long.parseLong(value); diff --git a/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java b/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java index d5c7c02cdfb..be273cce950 100644 --- a/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java +++ b/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java @@ -1004,6 +1004,12 @@ public Response searchActivities( @QueryParam( "spaceId" ) List spaceIds, + @Parameter(description = "Field to sort by") + @QueryParam("sort") + String sortField, + @Parameter(description = "Sort order (asc or desc)") + @QueryParam("order") + String sortDirection, @Parameter(description = "Offset", required = false) @Schema(defaultValue = "0") @QueryParam( "offset" @@ -1032,7 +1038,8 @@ public Response searchActivities( List spaceIdsString = spaceIds.stream().map(String::valueOf).toList(); spaceIdentityIds = SpaceUtils.getSpaceIdentityIds(authenticatedUser, spaceIdsString).stream().map(Long::valueOf).toList(); } - ActivitySearchFilter filter = new ActivitySearchFilter(query, tagNames, categoryIds, spaceIdentityIds, isFavorite); + + ActivitySearchFilter filter = new ActivitySearchFilter(query, tagNames, categoryIds, spaceIdentityIds, isFavorite, sortField, sortDirection); List searchResults = activitySearchConnector.search(currentUserIdentity, filter, offset, limit); List results = searchResults.stream().map(searchResult -> { ActivitySearchResultEntity entity = EntityBuilder.buildEntityFromActivitySearchResult(searchResult); diff --git a/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/activities-search-query.json b/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/activities-search-query.json index 765a8dac146..5438d33255f 100644 --- a/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/activities-search-query.json +++ b/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/activities-search-query.json @@ -16,6 +16,9 @@ @tags_query@ } }, + "sort": [ + @sortQuery@ + ], "highlight" : { "number_of_fragments" : 2, "fragment_size" : 150, diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue index 78968ecb71e..dde2b2a56c5 100644 --- a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue +++ b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue @@ -373,7 +373,7 @@ export default { }); } if (this.sortBy) { - uri += `&sortBy=${this.sortBy}&sortDescending=${this.sortDescending}`; + uri += `&sort=${this.sortBy}&order=${this.sortDescending ? 'desc' : 'asc'}`; } const fetchResultsQuery = connectorModule.fetchSearchResult ? connectorModule.fetchSearchResult(uri, options) From 824c66d8fcb44c3d37716302164cd9044c441a23 Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Tue, 19 Aug 2025 12:52:11 +0100 Subject: [PATCH 04/13] feat: unify sort param appending in search connectors URI - MEED-9503 - Meeds-io/MIPs#212 (#5113) --- .../search/components/SearchResults.vue | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue index dde2b2a56c5..69f0b173a42 100644 --- a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue +++ b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue @@ -372,9 +372,7 @@ export default { uri += `&spaceId=${spaceId}`; }); } - if (this.sortBy) { - uri += `&sort=${this.sortBy}&order=${this.sortDescending ? 'desc' : 'asc'}`; - } + uri = this.appendSortParams(uri, this.sortBy, this.sortDescending); const fetchResultsQuery = connectorModule.fetchSearchResult ? connectorModule.fetchSearchResult(uri, options) : fetch(uri, options); @@ -415,6 +413,20 @@ export default { }, isGroupingResult(result) { return Array.isArray(result); + }, + appendSortParams(uri, sortBy, sortDescending) { + let order = sortDescending ? 'desc' : 'asc'; + order = sortBy && order || ''; + sortDescending = sortBy && sortDescending || ''; + uri = uri.replace('{sort}', sortBy) + .replace('{order}', order) + .replace('{sortDescending}', sortDescending); + + if (this.sortBy && !uri.includes('{sort}') && !uri.includes('{order}') && !uri.includes('{sortDescending}')) { + const separator = uri.includes('?') ? '&' : '?'; + uri += `${separator}sort=${sortBy}&order=${order}`; + } + return uri; } }, }; From 3e825605d187dd877af707dbcec3eba55d57081f Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Tue, 19 Aug 2025 16:16:33 +0100 Subject: [PATCH 05/13] feat: enable sorting by last updated in spaces search - MEED-9505 - Meeds-io/MIPs#212 (#5114) --- .../social/core/space/SpaceFilter.java | 6 +++- .../social/search/SpaceSearchConnector.java | 31 +++++++++++++++++++ .../search/model/SpaceSearchFilter.java | 4 +++ .../search/SpaceIndexingServiceConnector.java | 4 +-- .../social/core/space/SpaceListAccess.java | 4 ++- .../search/SpaceSearchConnectorTest.java | 16 ++++++++++ .../social/search/spaces-search-query.json | 3 ++ 7 files changed, 64 insertions(+), 4 deletions(-) diff --git a/component/api/src/main/java/org/exoplatform/social/core/space/SpaceFilter.java b/component/api/src/main/java/org/exoplatform/social/core/space/SpaceFilter.java index 6b2a7c01108..7ebb4f6eb15 100644 --- a/component/api/src/main/java/org/exoplatform/social/core/space/SpaceFilter.java +++ b/component/api/src/main/java/org/exoplatform/social/core/space/SpaceFilter.java @@ -87,9 +87,13 @@ public List getStatusList() { return Stream.of(status, extraStatus).filter(Objects::nonNull).toList(); } + public boolean isSortingEmpty() { + return sorting == null; + } + public Sorting getSorting() { if (sorting == null) { - sorting = new Sorting(Sorting.SortBy.TITLE, Sorting.OrderBy.ASC); + return new Sorting(Sorting.SortBy.TITLE, Sorting.OrderBy.ASC); } return sorting; } diff --git a/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java b/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java index 28b16575dda..3ea30ce98e5 100644 --- a/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java +++ b/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java @@ -178,6 +178,23 @@ public class SpaceSearchConnector { } """; + public static final String DEFAULT_SORTING_QUERY = """ + { + "_score": { + "order": "desc" + } + } + """; + + public static final String SORTING_QUERY = """ + { + "@sortField@": { + "order": "@sortOrder@" + } + }, + "_score" + """; + private static final String TERM_REPLACEMENT = "@term@"; private static final String PHRASE_REPLACEMENT = "@phrase@"; @@ -275,6 +292,7 @@ private String buildQueryStatement(SpaceSearchFilter filter, String tagsQuery = buildTagsQueryStatement(metadataFilters.get(TagService.METADATA_TYPE.getName())); String visibilityQuery = buildVisibilityStatement(filter.getVisibility()); String registrationQuery = buildRegistrationStatement(filter.getRegistration()); + String sortQuery = buildSortQuery(filter); boolean noCommaToTemplate = StringUtils.isBlank(categoryQuery) || StringUtils.isBlank(templateQuery); boolean noCommaToFavorite = StringUtils.isBlank(favoriteQuery) || StringUtils.isAllBlank(templateQuery, categoryQuery); boolean noCommaToPermission = StringUtils.isBlank(permissionsQuery) @@ -307,6 +325,7 @@ private String buildQueryStatement(SpaceSearchFilter filter, noCommaToRegistration ? registrationQuery : String.format(PREFIX_COMMA_TO_APPEND, registrationQuery)) .replace("@tags_query@", tagsQuery) + .replace("@sortQuery@", sortQuery) .replace("@offset@", String.valueOf(offset)) .replace("@limit@", @@ -585,4 +604,16 @@ private Long parseLong(JSONObject hitSource, String key) { return StringUtils.isBlank(value) ? null : Long.parseLong(value); } + private String buildSortQuery(SpaceSearchFilter filter) { + if (StringUtils.isBlank(filter.getSortField())) { + return DEFAULT_SORTING_QUERY; + } + String sortFiled = filter.getSortField(); + String sortDirection = filter.getSortDirection(); + return switch (sortFiled) { + case "date" -> SORTING_QUERY.replace("@sortField@", "lastUpdatedDate").replace("@sortOrder@", sortDirection); + default -> SORTING_QUERY.replace("@sortField@", sortFiled).replace("@sortOrder@", sortDirection); + }; + } + } diff --git a/component/core/src/main/java/io/meeds/social/search/model/SpaceSearchFilter.java b/component/core/src/main/java/io/meeds/social/search/model/SpaceSearchFilter.java index e050ba4fc33..43881be1d3c 100644 --- a/component/core/src/main/java/io/meeds/social/search/model/SpaceSearchFilter.java +++ b/component/core/src/main/java/io/meeds/social/search/model/SpaceSearchFilter.java @@ -57,4 +57,8 @@ public class SpaceSearchFilter { private SpaceVisibility visibility; + private String sortField; + + private String sortDirection; + } diff --git a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/SpaceIndexingServiceConnector.java b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/SpaceIndexingServiceConnector.java index 9021d1cf571..dc8a2fc3c6c 100644 --- a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/SpaceIndexingServiceConnector.java +++ b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/SpaceIndexingServiceConnector.java @@ -98,11 +98,11 @@ public Document create(String id) { fields.put("registration", space.getRegistration()); fields.put("templateId", String.valueOf(space.getTemplateId())); - Date createdDate = new Date(space.getCreatedTime()); + Date updatedDate = new Date(space.getLastUpdatedTime()); DocumentWithMetadata document = new DocumentWithMetadata(); document.setId(id); - document.setLastUpdatedDate(createdDate); + document.setLastUpdatedDate(updatedDate); document.setFields(fields); setPermissions(space, document); diff --git a/component/core/src/main/java/org/exoplatform/social/core/space/SpaceListAccess.java b/component/core/src/main/java/org/exoplatform/social/core/space/SpaceListAccess.java index d724d2ebb34..eea3dfccd66 100644 --- a/component/core/src/main/java/org/exoplatform/social/core/space/SpaceListAccess.java +++ b/component/core/src/main/java/org/exoplatform/social/core/space/SpaceListAccess.java @@ -308,7 +308,9 @@ private SpaceSearchFilter getSpaceSearchFilter() { filter.getTagNames(), statusType, filter.getRegistration(), - filter.getVisibility()); + filter.getVisibility(), + filter.isSortingEmpty() ? null : filter.getSorting().sortBy.getFieldName(), + filter.isSortingEmpty() ? null : filter.getSorting().orderBy.name().toLowerCase()); } else { return null; } diff --git a/component/core/src/test/java/io/meeds/social/search/SpaceSearchConnectorTest.java b/component/core/src/test/java/io/meeds/social/search/SpaceSearchConnectorTest.java index 2f90c6d89e4..6a23ddcf87f 100644 --- a/component/core/src/test/java/io/meeds/social/search/SpaceSearchConnectorTest.java +++ b/component/core/src/test/java/io/meeds/social/search/SpaceSearchConnectorTest.java @@ -162,6 +162,8 @@ public void testCountFavorites() { null, null, null, + null, + null, null); when(client.countRequest(argThat(esQuery -> hasUserFavoriteQueryPart(esQuery) && hasPermissionQueryPart(esQuery, MEMBER, 1, USER_NAME)), @@ -182,6 +184,8 @@ public void testSearchFavorites() { null, null, null, + null, + null, null); when(client.sendRequest(argThat(esQuery -> hasUserFavoriteQueryPart(esQuery) && hasPermissionQueryPart(esQuery, MEMBER, 1, USER_NAME)), @@ -209,6 +213,8 @@ public void testSearchManagingSpaces() { null, null, null, + null, + null, null); filter.setManagingTemplateIds(Collections.singletonList(2l)); when(client.sendRequest(argThat(esQuery -> hasUserFavoriteQueryPart(esQuery) @@ -245,6 +251,8 @@ public void testSearchSpacesByCategoryIds() { null, null, null, + null, + null, null); when(client.sendRequest(argThat(esQuery -> hasCategoryIdsQueryPart(esQuery, categoryIds)), eq(index))).thenReturn(SEARCH_RESULT); @@ -266,6 +274,8 @@ public void testNotSearchWhenNotUnifiedSearch() { null, SpaceMembershipStatus.MEMBER, null, + null, + null, null), 0, 10)); @@ -314,6 +324,8 @@ public void testSearchSpaceNoMembership() { null, null, null, + null, + null, null); when(client.sendRequest(argThat(esQuery -> hasNotUserFavoriteQueryPart(esQuery) && hasPermissionQueryPart(esQuery, @@ -346,6 +358,8 @@ public void testSearchTags() { Arrays.asList("tag1", "tag2"), null, null, + null, + null, null); when(client.sendRequest(argThat(esQuery -> hasNotUserFavoriteQueryPart(esQuery) && hasPermissionQueryPart(esQuery, PERMISSIONS_FIELD, 2, "all", USER_NAME) @@ -373,6 +387,8 @@ private void checkPermissionField(SpaceMembershipStatus status, String fieldName null, status, null, + null, + null, null); when(client.sendRequest(argThat(esQuery -> hasNotUserFavoriteQueryPart(esQuery) && hasPermissionQueryPart(esQuery, fieldName, 1, USER_NAME)), diff --git a/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/spaces-search-query.json b/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/spaces-search-query.json index 75708c07d1b..79a6967f0a2 100644 --- a/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/spaces-search-query.json +++ b/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search/spaces-search-query.json @@ -15,6 +15,9 @@ @tags_query@ } }, + "sort": [ + @sortQuery@ + ], "highlight" : { "number_of_fragments" : 2, "fragment_size" : 150, From 2a4e5b914695745ee0653bd4dae46190ce52b2fd Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Wed, 20 Aug 2025 13:41:18 +0100 Subject: [PATCH 06/13] feat: enable sorting by last updated in profiles search - MEED-9505 -Meeds-io/MIPs#212 (#5116) --- .../ProfileIndexingServiceConnector.java | 1 - .../social/rest/impl/user/UserRest.java | 13 ++++++- .../service/rest/PeopleRestService.java | 38 +++++++++---------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java index 9b530743d82..adc742adbc0 100644 --- a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java +++ b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java @@ -272,7 +272,6 @@ private Document getDocument(String id) { fields.put("enrollmentDate", profile.getProperty(Profile.ENROLLMENT_DATE).toString()); } Date createdDate = new Date(profile.getCreatedTime()); - for (ProfilePropertySetting profilePropertySetting : profilePropertyService.getPropertySettings()) { if (profilePropertySetting.isVisible() && !fields.containsKey(profilePropertySetting.getPropertyName())) { Object propertyValue = profile.getProperty(profilePropertySetting.getPropertyName()); diff --git a/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java b/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java index 98e683575bc..bbeb489cd73 100644 --- a/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java +++ b/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java @@ -35,6 +35,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.exoplatform.social.core.search.Sorting; import org.json.JSONException; import org.json.JSONObject; import org.picocontainer.Startable; @@ -256,6 +257,8 @@ public Response getUsers(@Context UriInfo uriInfo, @Parameter(description = "Space id to filter only its members, ex: 1") @QueryParam("spaceId") List spaceIds, @Parameter(description = "Is disabled users") @Schema(defaultValue = "false") @QueryParam("isDisabled") boolean isDisabled, @Parameter(description = "Enrollment status, ex: enrolled, not enrolled, no possible enrollment") @QueryParam("enrollmentStatus") String enrollmentStatus, + @Parameter(description = "Sort", required = false) @QueryParam("sort") String sort, + @Parameter(description = "Order", required = false) @QueryParam("order") String order, @Parameter(description = "Offset") @Schema(defaultValue = "0") @QueryParam("offset") int offset, @Parameter(description = "Limit") @Schema(defaultValue = "20") @QueryParam("limit") int limit, @Parameter(description = "Returning the number of users found or not") @Schema(defaultValue = "false") @QueryParam("returnSize") boolean returnSize, @@ -275,7 +278,7 @@ public Response getUsers(@Context UriInfo uriInfo, if (!userACL.getSuperUser().equals(userId) && !RestUtils.isMemberOfAdminGroup() && !RestUtils.isMemberOfDelegatedGroup() && userType != null && !userType.equals(INTERNAL)) { throw new WebApplicationException(Response.Status.FORBIDDEN); } - + offset = offset > 0 ? offset : RestUtils.getOffset(uriInfo); limit = limit > 0 ? limit : RestUtils.getLimit(uriInfo); @@ -310,6 +313,14 @@ public Response getUsers(@Context UriInfo uriInfo, List spaceIdsString = spaceIds.stream().map(String::valueOf).toList(); filter.setSpaceIdentityIds(SpaceUtils.getSpaceIdentityIds(target.getRemoteId(), spaceIdsString)); } + if (StringUtils.isNotBlank(sort)) { + Sorting.SortBy sortBy = Sorting.SortBy.valueOf(sort.toUpperCase()); + Sorting.OrderBy orderBy = Sorting.OrderBy.ASC; + if (StringUtils.isNotBlank(order)) { + orderBy = Sorting.OrderBy.valueOf(order.toUpperCase()); + } + filter.setSorting(new Sorting(sortBy, orderBy)); + } if (target != null && excludeCurrentUser) { filter.setViewerIdentity(target); } diff --git a/component/service/src/main/java/org/exoplatform/social/service/rest/PeopleRestService.java b/component/service/src/main/java/org/exoplatform/social/service/rest/PeopleRestService.java index d558c44a92a..636584910b6 100644 --- a/component/service/src/main/java/org/exoplatform/social/service/rest/PeopleRestService.java +++ b/component/service/src/main/java/org/exoplatform/social/service/rest/PeopleRestService.java @@ -1,21 +1,21 @@ -/** - * This file is part of the Meeds project (https://meeds.io/). - * - * Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ package org.exoplatform.social.service.rest; import org.apache.commons.lang3.ArrayUtils; @@ -630,7 +630,7 @@ private void addSpaceOrUserToList(List identities, IdentityNameList op * @throws Exception * @LevelAPI Platform * @anchor PeopleRestService.suggestUsernames - * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link UserRest#getUsers(UriInfo, String, boolean, boolean, String, String, String, List, boolean, String, int, int, boolean, String, boolean)} + * @deprecated Deprecated from 4.3.x. Replaced by a new API {@link UserRest#getUsers(UriInfo, String, boolean, boolean, String, String, String, List, boolean, String, String, String, int, int, boolean, String, boolean)} * */ @GET From 822dba565830d502d235fa99f0aeeecdf5554e78 Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Wed, 20 Aug 2025 17:16:29 +0100 Subject: [PATCH 07/13] feat: Add analytics statistics for search sorting by date - MEED-9506- Meeds-io/MIPs#212 (#5117) --- .../search/components/searchOptions/SearchSortSelector.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue index 0e353f67363..0d20886c5c5 100644 --- a/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue +++ b/webapp/src/main/webapp/vue-apps/search/components/searchOptions/SearchSortSelector.vue @@ -72,6 +72,9 @@ export default { selectSort(option) { this.selectedSort = option.value; this.$root.$emit('sort-changed', option, this.sortDescending); + if (this.selectedSort === 'date') { + document.dispatchEvent(new CustomEvent('search-sort-by-date-action')); + } }, }, }; From 3c529c74d4432321063fac4ebd519b4d5efdb6bb Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Thu, 21 Aug 2025 11:21:32 +0100 Subject: [PATCH 08/13] fix: Edited profile not first in last updated sort - MEED-9504 - Meeds-io/MIPs#212 (#5118) --- .../core/jpa/search/ProfileIndexingServiceConnector.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java index adc742adbc0..0b9dfe132f8 100644 --- a/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java +++ b/component/core/src/main/java/org/exoplatform/social/core/jpa/search/ProfileIndexingServiceConnector.java @@ -271,7 +271,6 @@ private Document getDocument(String id) { if (profile.getProperty(Profile.ENROLLMENT_DATE) != null) { fields.put("enrollmentDate", profile.getProperty(Profile.ENROLLMENT_DATE).toString()); } - Date createdDate = new Date(profile.getCreatedTime()); for (ProfilePropertySetting profilePropertySetting : profilePropertyService.getPropertySettings()) { if (profilePropertySetting.isVisible() && !fields.containsKey(profilePropertySetting.getPropertyName())) { Object propertyValue = profile.getProperty(profilePropertySetting.getPropertyName()); @@ -305,7 +304,7 @@ private Document getDocument(String id) { fields.put("connections", "@@@[" + connectionsStr + "]@@@"); } - Document document = new ProfileIndexDocument(id, null, createdDate, (Set) null, fields); + Document document = new ProfileIndexDocument(id, null, new Date(), (Set) null, fields); document.setPermissions(getGroupIdentityIds(identity)); LOG.info("profile document generated for identity id={} remote_id={} duration_ms={}", id, From 55dad9021fcf33415a3be786bfba7c904a11cf50 Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Thu, 21 Aug 2025 11:44:14 +0100 Subject: [PATCH 09/13] feat: Display last updated date in activity search results - MEED-9561 - Meeds-io/MIPs#212 (#5119) --- .../search-activity/components/SearchActivityCard.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/webapp/src/main/webapp/vue-apps/search-activity/components/SearchActivityCard.vue b/webapp/src/main/webapp/vue-apps/search-activity/components/SearchActivityCard.vue index 657ff7e37fb..3fa83fe69f9 100644 --- a/webapp/src/main/webapp/vue-apps/search-activity/components/SearchActivityCard.vue +++ b/webapp/src/main/webapp/vue-apps/search-activity/components/SearchActivityCard.vue @@ -74,11 +74,11 @@ - + fas fa-clock - +
Date: Thu, 21 Aug 2025 16:43:48 +0100 Subject: [PATCH 10/13] feat: Unify sort params in search RESTs - MEED-9573 - Meeds-io/MIPs#212 --- .../social/rest/impl/activity/ActivityRest.java | 4 ++-- .../social/rest/impl/user/UserRest.java | 12 ++++++------ .../social/search-configuration.xml | 2 +- .../vue-apps/search/components/SearchResults.vue | 16 +++++++++------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java b/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java index be273cce950..a86b0adcc32 100644 --- a/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java +++ b/component/service/src/main/java/org/exoplatform/social/rest/impl/activity/ActivityRest.java @@ -1005,10 +1005,10 @@ public Response searchActivities( "spaceId" ) List spaceIds, @Parameter(description = "Field to sort by") - @QueryParam("sort") + @QueryParam("sortField") String sortField, @Parameter(description = "Sort order (asc or desc)") - @QueryParam("order") + @QueryParam("sortDirection") String sortDirection, @Parameter(description = "Offset", required = false) @Schema(defaultValue = "0") @QueryParam( diff --git a/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java b/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java index bbeb489cd73..b706e3da408 100644 --- a/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java +++ b/component/service/src/main/java/org/exoplatform/social/rest/impl/user/UserRest.java @@ -257,8 +257,8 @@ public Response getUsers(@Context UriInfo uriInfo, @Parameter(description = "Space id to filter only its members, ex: 1") @QueryParam("spaceId") List spaceIds, @Parameter(description = "Is disabled users") @Schema(defaultValue = "false") @QueryParam("isDisabled") boolean isDisabled, @Parameter(description = "Enrollment status, ex: enrolled, not enrolled, no possible enrollment") @QueryParam("enrollmentStatus") String enrollmentStatus, - @Parameter(description = "Sort", required = false) @QueryParam("sort") String sort, - @Parameter(description = "Order", required = false) @QueryParam("order") String order, + @Parameter(description = "sort Field", required = false) @QueryParam("sortField") String sortField, + @Parameter(description = "sort Direction", required = false) @QueryParam("sortDirection") String sortDirection, @Parameter(description = "Offset") @Schema(defaultValue = "0") @QueryParam("offset") int offset, @Parameter(description = "Limit") @Schema(defaultValue = "20") @QueryParam("limit") int limit, @Parameter(description = "Returning the number of users found or not") @Schema(defaultValue = "false") @QueryParam("returnSize") boolean returnSize, @@ -313,11 +313,11 @@ public Response getUsers(@Context UriInfo uriInfo, List spaceIdsString = spaceIds.stream().map(String::valueOf).toList(); filter.setSpaceIdentityIds(SpaceUtils.getSpaceIdentityIds(target.getRemoteId(), spaceIdsString)); } - if (StringUtils.isNotBlank(sort)) { - Sorting.SortBy sortBy = Sorting.SortBy.valueOf(sort.toUpperCase()); + if (StringUtils.isNotBlank(sortField)) { + Sorting.SortBy sortBy = Sorting.SortBy.valueOf(sortField.toUpperCase()); Sorting.OrderBy orderBy = Sorting.OrderBy.ASC; - if (StringUtils.isNotBlank(order)) { - orderBy = Sorting.OrderBy.valueOf(order.toUpperCase()); + if (StringUtils.isNotBlank(sortDirection)) { + orderBy = Sorting.OrderBy.valueOf(sortDirection.toUpperCase()); } filter.setSorting(new Sorting(sortBy, orderBy)); } diff --git a/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search-configuration.xml b/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search-configuration.xml index a8d9d8db7d7..e7c06db3edd 100644 --- a/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search-configuration.xml +++ b/webapp/src/main/webapp/WEB-INF/conf/social-extension/social/search-configuration.xml @@ -123,7 +123,7 @@ spaces - + ${search.space.enabled:true} diff --git a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue index 69f0b173a42..504da1f5db5 100644 --- a/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue +++ b/webapp/src/main/webapp/vue-apps/search/components/SearchResults.vue @@ -415,17 +415,19 @@ export default { return Array.isArray(result); }, appendSortParams(uri, sortBy, sortDescending) { - let order = sortDescending ? 'desc' : 'asc'; - order = sortBy && order || ''; + let sortDirection = sortDescending ? 'desc' : 'asc'; + sortDirection = sortBy && sortDirection || ''; sortDescending = sortBy && sortDescending || ''; - uri = uri.replace('{sort}', sortBy) - .replace('{order}', order) - .replace('{sortDescending}', sortDescending); - if (this.sortBy && !uri.includes('{sort}') && !uri.includes('{order}') && !uri.includes('{sortDescending}')) { + if (this.sortBy && !uri.includes('{sortField}') && !uri.includes('{sortDirection}') && !uri.includes('{sortDescending}')) { const separator = uri.includes('?') ? '&' : '?'; - uri += `${separator}sort=${sortBy}&order=${order}`; + uri += `${separator}sortField=${sortBy}&sortDirection=${sortDirection}`; + return uri; } + uri = uri.replace('{sortField}', sortBy) + .replace('{sortDirection}', sortDirection) + .replace('{sortDescending}', sortDescending); + return uri; } }, From 526f0363f47794e04504c4432ceb741adbe90870 Mon Sep 17 00:00:00 2001 From: Sofien Haj Chedhli Date: Fri, 22 Aug 2025 16:31:33 +0100 Subject: [PATCH 11/13] fix: handle unsupported sort fields by returning default sorting query - MEED-9574 - Meeds-io/MIPs#212 (#5130) --- .../main/java/io/meeds/social/search/SpaceSearchConnector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java b/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java index 3ea30ce98e5..af435331af4 100644 --- a/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java +++ b/component/core/src/main/java/io/meeds/social/search/SpaceSearchConnector.java @@ -612,7 +612,7 @@ private String buildSortQuery(SpaceSearchFilter filter) { String sortDirection = filter.getSortDirection(); return switch (sortFiled) { case "date" -> SORTING_QUERY.replace("@sortField@", "lastUpdatedDate").replace("@sortOrder@", sortDirection); - default -> SORTING_QUERY.replace("@sortField@", sortFiled).replace("@sortOrder@", sortDirection); + default -> DEFAULT_SORTING_QUERY; }; } From 9213c39804b4f3b25ec4c438f81fbd5e10a267d7 Mon Sep 17 00:00:00 2001 From: halaya Date: Tue, 18 Mar 2025 15:29:07 +0100 Subject: [PATCH 12/13] Task-77677: Create FB meeds-qaui and update projects versions/dependencies --- component/api/pom.xml | 2 +- component/common/pom.xml | 2 +- component/core/pom.xml | 2 +- component/notification/pom.xml | 2 +- component/oauth-auth/pom.xml | 2 +- component/pom.xml | 2 +- component/service/pom.xml | 2 +- component/web/pom.xml | 2 +- pom.xml | 6 +++--- webapp/pom.xml | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/component/api/pom.xml b/component/api/pom.xml index b9444394b41..1f127a0a8e1 100644 --- a/component/api/pom.xml +++ b/component/api/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT social-component-api Meeds:: PLF:: Social API diff --git a/component/common/pom.xml b/component/common/pom.xml index b675c19e370..070effe15fa 100644 --- a/component/common/pom.xml +++ b/component/common/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT io.meeds.social social-component-common diff --git a/component/core/pom.xml b/component/core/pom.xml index 738ae7dddb8..b3950461f5b 100644 --- a/component/core/pom.xml +++ b/component/core/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT social-component-core Meeds:: PLF:: Social Core Component diff --git a/component/notification/pom.xml b/component/notification/pom.xml index 0716c9e5cd0..65ff815da62 100644 --- a/component/notification/pom.xml +++ b/component/notification/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT social-component-notification Meeds:: PLF:: Social Notification Component diff --git a/component/oauth-auth/pom.xml b/component/oauth-auth/pom.xml index ad85b8a2c16..03853af543e 100644 --- a/component/oauth-auth/pom.xml +++ b/component/oauth-auth/pom.xml @@ -21,7 +21,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT 4.0.0 diff --git a/component/pom.xml b/component/pom.xml index 1f0657864a5..068545d51b8 100644 --- a/component/pom.xml +++ b/component/pom.xml @@ -22,7 +22,7 @@ social io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT social-component pom diff --git a/component/service/pom.xml b/component/service/pom.xml index 5167afd1837..17451df9936 100644 --- a/component/service/pom.xml +++ b/component/service/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT social-component-service Meeds:: PLF:: Social Service Component diff --git a/component/web/pom.xml b/component/web/pom.xml index 112a16c62be..e3cc86b93f0 100644 --- a/component/web/pom.xml +++ b/component/web/pom.xml @@ -22,7 +22,7 @@ social-component io.meeds.social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT io.meeds.social social-component-web diff --git a/pom.xml b/pom.xml index a6a1e752bc0..395b7a963b4 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ io.meeds.social social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT pom Meeds:: PLF:: Social Meeds Social - Enterprise Social Networking @@ -45,8 +45,8 @@ - 7.1.x-meed-SNAPSHOT - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT meeds-io diff --git a/webapp/pom.xml b/webapp/pom.xml index e0ce0ef0d39..9b32239a221 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -22,7 +22,7 @@ io.meeds.social social - 7.1.x-meed-SNAPSHOT + 7.1.x-meeds-qaui-SNAPSHOT social-webapp war From 949cddc3b4fe8de58dcb2ee730c14332810bcb15 Mon Sep 17 00:00:00 2001 From: Boubaker Khanfir Date: Tue, 26 Aug 2025 17:42:31 +0100 Subject: [PATCH 13/13] feat: Drop WebUI Portlet Framework - MEED-9616 - Meeds-io/meeds#3321 (#5136) This change will drop the usage of WebUI Portlet Components used in OAuth Validation Process. --- .../oauth/filter/OAuthLoginServletFilter.java | 272 +++++++++--------- .../main/webapp/WEB-INF/gatein-resources.xml | 3 +- 2 files changed, 141 insertions(+), 134 deletions(-) diff --git a/component/oauth-auth/src/main/java/io/meeds/oauth/filter/OAuthLoginServletFilter.java b/component/oauth-auth/src/main/java/io/meeds/oauth/filter/OAuthLoginServletFilter.java index 77c577c1078..f7dde96a554 100644 --- a/component/oauth-auth/src/main/java/io/meeds/oauth/filter/OAuthLoginServletFilter.java +++ b/component/oauth-auth/src/main/java/io/meeds/oauth/filter/OAuthLoginServletFilter.java @@ -22,22 +22,16 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.ResourceBundle; import java.util.Set; import javax.security.auth.login.LoginException; -import jakarta.servlet.FilterChain; -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.exoplatform.commons.utils.ListAccess; +import org.exoplatform.portal.rest.UserFieldValidator; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.organization.DisabledUserException; @@ -52,17 +46,7 @@ import org.exoplatform.services.security.Credential; import org.exoplatform.services.security.PasswordCredential; import org.exoplatform.services.security.UsernameCredential; -import org.exoplatform.web.application.AbstractApplicationMessage; import org.exoplatform.web.security.AuthenticationRegistry; -import org.exoplatform.webui.exception.MessageException; -import org.exoplatform.webui.form.UIForm; -import org.exoplatform.webui.form.UIFormStringInput; -import org.exoplatform.webui.form.validator.MandatoryValidator; -import org.exoplatform.webui.form.validator.PasswordStringLengthValidator; -import org.exoplatform.webui.form.validator.PersonalNameValidator; -import org.exoplatform.webui.form.validator.StringLengthValidator; -import org.exoplatform.webui.form.validator.UserConfigurableValidator; -import org.exoplatform.webui.form.validator.Validator; import io.meeds.oauth.common.OAuthConstants; import io.meeds.oauth.contant.OAuthConst; @@ -73,31 +57,63 @@ import io.meeds.oauth.spi.OAuthProviderType; import io.meeds.oauth.utils.OAuthUtils; +import jakarta.servlet.FilterChain; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + public class OAuthLoginServletFilter extends OAuthAbstractFilter { - private static final String PASSWORD_PARAM = "password"; + private static final String EMAIL_ADDRESS_PARAM = "emailAddress"; + + private static final String USERNAME_PARAM = "username"; + + public static final String EMAIL_PARAM = "email"; + + public static final String LASTNAME_PARAM = "lastName"; + + public static final String FIRSTNAME_PARAM = "firstName"; + + public static final String PASSWORD_PARAM = "password"; + + private static final String INVITATION_CONFIRM_ERROR_PARAM = "invitationConfirmError"; - private static final String INVITATION_CONFIRM_ERROR_PARAM = "invitationConfirmError"; + private final Log log = ExoLogger.getLogger(OAuthLoginServletFilter.class); - private final Log log = ExoLogger.getLogger(OAuthLoginServletFilter.class); + public static final String CONTROLLER_PARAM_NAME = "login_controller"; - public static final String CONTROLLER_PARAM_NAME = "login_controller"; + public static final String CANCEL_OAUTH = "oauth_cancel"; - public static final String CANCEL_OAUTH = "oauth_cancel"; + public static final String CONFIRM_ACCOUNT = "confirm_account"; - public static final String CONFIRM_ACCOUNT = "confirm_account"; + public static final String REGISTER_NEW_ACCOUNT = "register"; - public static final String REGISTER_NEW_ACCOUNT = "register"; + public static final String CONFIRM_REGISTER_ACCOUNT = "submit_register"; - public static final String CONFIRM_REGISTER_ACCOUNT = "submit_register"; + public static final String SESSION_ATTR_REGISTER_NEW_ACCOUNT = "__oauth_create_new_account"; - public static final String SESSION_ATTR_REGISTER_NEW_ACCOUNT = "__oauth_create_new_account"; + private static final String SESSION_ATTR_IS_ON_FLY_ERROR = "isOnFlyError"; - private static final String SESSION_ATTR_IS_ON_FLY_ERROR = "isOnFlyError"; + private static final String OAUTH_REGISTER_JSP_PATH = "/WEB-INF/jsp/login/oauth_register.jsp"; // NOSONAR - private static final String OAUTH_REGISTER_JSP_PATH = "/WEB-INF/jsp/login/oauth_register.jsp"; // NOSONAR + private static final String OAUTH_INVITATION_JSP_PATH = "/WEB-INF/jsp/login/oauth_invitation.jsp"; // NOSONAR - private static final String OAUTH_INVITATION_JSP_PATH = "/WEB-INF/jsp/login/oauth_invitation.jsp"; // NOSONAR + public static final UserFieldValidator USERNAME_VALIDATOR = new UserFieldValidator("userName", true, false); + + public static final UserFieldValidator PASSWORD_VALIDATOR = + new UserFieldValidator(PASSWORD_PARAM, false, false, 8, 255); + + public static final UserFieldValidator LASTNAME_VALIDATOR = + new UserFieldValidator(LASTNAME_PARAM, false, true); + + public static final UserFieldValidator FIRSTNAME_VALIDATOR = + new UserFieldValidator(FIRSTNAME_PARAM, false, true); + + public static final UserFieldValidator EMAIL_VALIDATOR = new UserFieldValidator(EMAIL_PARAM, false, false); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -116,8 +132,9 @@ protected void executeFilter(HttpServletRequest request, AuthenticationRegistry authenticationRegistry = getService(AuthenticationRegistry.class); ResourceBundleService resourceBundleService = getService(ResourceBundleService.class); + Locale locale = request.getLocale(); ResourceBundle resourceBundle = resourceBundleService.getResourceBundle(resourceBundleService.getSharedResourceBundleNames(), - request.getLocale()); + locale); MessageResolver messageResolver = new MessageResolver(resourceBundle); ServletContext context = getContext(); @@ -198,11 +215,10 @@ private void confirmExistingAccount(HttpServletRequest request, String password = request.getParameter(PASSWORD_PARAM); Credential[] credentials = new Credential[] { - new UsernameCredential(username), new PasswordCredential(password) + new UsernameCredential(username), new PasswordCredential(password) }; Authenticator authenticator = getService(Authenticator.class); try { - OrganizationService organizationService = getService(OrganizationService.class); boolean isAuthenticated = StringUtils.isNotBlank(authenticator.validateUser(credentials)); if (isAuthenticated) { OAuthRegistrationService oAuthRegistrationService = getService(OAuthRegistrationService.class); @@ -236,11 +252,9 @@ private void confirmExistingAccount(HttpServletRequest request, getContext().getRequestDispatcher(OAUTH_INVITATION_JSP_PATH).forward(request, response); } - private OAuthPrincipal getPrincipal(HttpServletRequest request, AuthenticationRegistry authenticationRegistry) { - OAuthPrincipal principal = - (OAuthPrincipal) authenticationRegistry.getAttributeOfClient(request, - OAuthConstants.ATTRIBUTE_AUTHENTICATED_OAUTH_PRINCIPAL); - return principal; + private OAuthPrincipal getPrincipal(HttpServletRequest request, AuthenticationRegistry authenticationRegistry) { + return (OAuthPrincipal) authenticationRegistry.getAttributeOfClient(request, + OAuthConstants.ATTRIBUTE_AUTHENTICATED_OAUTH_PRINCIPAL); } private String getUserName(HttpServletRequest request, AuthenticationRegistry authenticationRegistry) { @@ -249,32 +263,40 @@ private String getUserName(HttpServletRequest request, AuthenticationRegistry au return user == null ? null : user.getUserName(); } - private void processCreateNewAccount(HttpServletRequest req, HttpServletResponse res, - MessageResolver bundle, AuthenticationRegistry authReg, + private void processCreateNewAccount(HttpServletRequest req, + HttpServletResponse res, + MessageResolver bundle, + AuthenticationRegistry authReg, User portalUser) throws IOException, ServletException { - String username = req.getParameter("username"); + String username = req.getParameter(USERNAME_PARAM); String password = req.getParameter(PASSWORD_PARAM); String password2 = req.getParameter("password2"); - String firstName = req.getParameter("firstName"); - String lastName = req.getParameter("lastName"); + String firstName = req.getParameter(FIRSTNAME_PARAM); + String lastName = req.getParameter(LASTNAME_PARAM); String displayName = req.getParameter("displayName"); - String email = req.getParameter("email"); + String email = req.getParameter(EMAIL_PARAM); portalUser.setUserName(username); portalUser.setPassword(password); + portalUser.setDisplayName(displayName); portalUser.setFirstName(firstName); portalUser.setLastName(lastName); - portalUser.setDisplayName(displayName); portalUser.setEmail(email); - List errors = new ArrayList(); - Set errorFields = new HashSet(); + List errors = new ArrayList<>(); + Set errorFields = new HashSet<>(); OrganizationService orgService = getService(OrganizationService.class); - validateUser(portalUser, password2, orgService, bundle, errors, errorFields); + validateUser(portalUser, + password2, + orgService, + bundle, + req.getLocale(), + errors, + errorFields); - if (errors.size() == 0) { + if (errors.isEmpty()) { try { orgService.getUserHandler().createUser(portalUser, true); UserProfileHandler profileHandler = orgService.getUserProfileHandler(); @@ -282,9 +304,7 @@ private void processCreateNewAccount(HttpServletRequest req, HttpServletResponse if (newUserProfile == null) { newUserProfile = orgService.getUserProfileHandler().createUserProfileInstance(portalUser.getUserName()); } - OAuthPrincipal oauthPrincipal = - (OAuthPrincipal) authReg.getAttributeOfClient(req, - OAuthConstants.ATTRIBUTE_AUTHENTICATED_OAUTH_PRINCIPAL); + OAuthPrincipal oauthPrincipal = getPrincipal(req, authReg); newUserProfile.setAttribute(oauthPrincipal.getOauthProviderType().getUserNameAttrName(), oauthPrincipal.getUserName()); try { @@ -328,74 +348,78 @@ private void processCreateNewAccount(HttpServletRequest req, HttpServletResponse getContext().getRequestDispatcher(OAUTH_REGISTER_JSP_PATH).forward(req, res); } - private void validateUser(User user, String password2, OrganizationService orgService, - MessageResolver bundle, List errorMessages, Set errorFields) { - Validator validator; - Validator mandatory = new MandatoryValidator(); - Validator stringLength; - ResourceBundle rb = bundle.getBundle(); - // + private void validateUser(User user, + String password2, + OrganizationService organizationService, + MessageResolver bundle, + Locale locale, + List errorMessages, + Set errorFields) { String username = user.getUserName(); - validator = new UserConfigurableValidator(UserConfigurableValidator.USERNAME, - UserConfigurableValidator.DEFAULT_LOCALIZATION_KEY); - validate("username", username, new Validator[] { - mandatory, validator - }, rb, errorMessages, errorFields); - if (!errorFields.contains("username")) { + String firstName = user.getFirstName(); + String lastName = user.getLastName(); + String email = user.getEmail(); + String password = user.getPassword(); + + validate(USERNAME_VALIDATOR, + USERNAME_PARAM, + username, + locale, + errorMessages, + errorFields); + if (!errorFields.contains(USERNAME_PARAM)) { try { - if (orgService.getUserHandler().findUserByName(username, UserStatus.ANY) != null) { - errorFields.add("username"); + if (organizationService.getUserHandler().findUserByName(username, UserStatus.ANY) != null) { + errorFields.add(USERNAME_PARAM); errorMessages.add(bundle.resolve("UIAccountInputSet.msg.user-exist", username)); } } catch (Exception ex) { log.warn("Can not check username exist or not for: " + username); } } - - // - String password = user.getPassword(); - validator = new PasswordStringLengthValidator(6, 30); - validate(PASSWORD_PARAM, password, new Validator[] { - mandatory, validator - }, rb, errorMessages, errorFields); - if (!errorFields.contains(PASSWORD_PARAM)) { - if (!password.equals(password2)) { - errorMessages.add(bundle.resolve("UIAccountForm.msg.password-is-not-match")); - errorFields.add("password2"); - } + validate(USERNAME_VALIDATOR, + USERNAME_PARAM, + username, + locale, + errorMessages, + errorFields); + validate(FIRSTNAME_VALIDATOR, + FIRSTNAME_PARAM, + firstName, + locale, + errorMessages, + errorFields); + validate(LASTNAME_VALIDATOR, + LASTNAME_PARAM, + lastName, + locale, + errorMessages, + errorFields); + validate(EMAIL_VALIDATOR, + EMAIL_ADDRESS_PARAM, + email, + locale, + errorMessages, + errorFields); + validate(PASSWORD_VALIDATOR, + PASSWORD_PARAM, + password, + locale, + errorMessages, + errorFields); + if (!errorFields.contains(PASSWORD_PARAM) + && !password.equals(password2)) { + errorMessages.add(bundle.resolve("UIAccountForm.msg.password-is-not-match")); + errorFields.add("password2"); } - stringLength = new StringLengthValidator(1, 45); - validator = new PersonalNameValidator(); - String firstName = user.getFirstName(); - String lastName = user.getLastName(); - validate("firstName", firstName, new Validator[] { - mandatory, stringLength, validator - }, rb, errorMessages, errorFields); - validate("lastName", lastName, new Validator[] { - mandatory, stringLength, validator - }, rb, errorMessages, errorFields); - - stringLength = new StringLengthValidator(0, 90); - validator = new UserConfigurableValidator("displayname", UserConfigurableValidator.KEY_PREFIX + "displayname", false); - String displayName = user.getDisplayName(); - validate("displayName", displayName, new Validator[] { - stringLength, validator - }, rb, errorMessages, errorFields); - - // - validator = new UserConfigurableValidator(UserConfigurableValidator.EMAIL); - String email = user.getEmail(); - validate("emailAddress", email, new Validator[] { - mandatory, validator - }, rb, errorMessages, errorFields); - if (!errorFields.contains("emailAddress")) { + if (!errorFields.contains(EMAIL_ADDRESS_PARAM)) { try { Query query = new Query(); query.setEmail(email); - ListAccess users = orgService.getUserHandler().findUsersByQuery(query, UserStatus.ANY); + ListAccess users = organizationService.getUserHandler().findUsersByQuery(query, UserStatus.ANY); if (users != null && users.getSize() > 0) { - errorFields.add("emailAddress"); + errorFields.add(EMAIL_ADDRESS_PARAM); errorMessages.add(bundle.resolve("UIAccountInputSet.msg.email-exist", email)); } } catch (Exception ex) { @@ -404,32 +428,16 @@ private void validateUser(User user, String password2, OrganizationService orgSe } } - private void validate(String field, String value, Validator[] validators, final ResourceBundle bundle, - List errorMessages, Set errorFields) { - try { - UIForm form = new UIForm() { - @Override - public String getLabel(String label) throws Exception { - return this.getLabel(bundle, label); - } - }; - form.setId("UIRegisterForm"); - UIFormStringInput uiFormStringInput = new UIFormStringInput(field, field, value); - form.addUIFormInput(uiFormStringInput); - for (Validator validator : validators) { - validator.validate(uiFormStringInput); - } - } catch (Exception e) { - errorFields.add(field); - if (e instanceof MessageException) { - MessageException mex = (MessageException) e; - AbstractApplicationMessage msg = mex.getDetailMessage(); - msg.setResourceBundle(bundle); - errorMessages.add(msg.getMessage()); - } else { - log.debug(e); - errorMessages.add(field + " error"); - } + private void validate(UserFieldValidator validator, + String fieldName, + String value, + Locale locale, + List errorMessages, + Set errorFields) { + String errorMessage = validator.validate(locale, value); + if (StringUtils.isNotBlank(errorMessage)) { + errorFields.add(fieldName); + errorMessages.add(errorMessage); } } diff --git a/webapp/src/main/webapp/WEB-INF/gatein-resources.xml b/webapp/src/main/webapp/WEB-INF/gatein-resources.xml index 93362df3a25..24aaf1ac675 100644 --- a/webapp/src/main/webapp/WEB-INF/gatein-resources.xml +++ b/webapp/src/main/webapp/WEB-INF/gatein-resources.xml @@ -246,7 +246,7 @@ 2 - + social TopBarNotification @@ -254,7 +254,6 @@ /skin/css/portlet/TopBarNotification/Style.css 1 -