From 9dd5ff867490059b60a57adee5e883b7f758e1ab Mon Sep 17 00:00:00 2001 From: rooij_e Date: Wed, 19 Aug 2026 08:25:40 +0200 Subject: [PATCH 01/13] Remove /subscriptions in deltares-fews-theme --- configs/artifacts-release.json | 4 ++-- modules/context-contributors/bnd.bnd | 2 +- .../context/contributor/UtilsTemplateContextContributor.java | 1 - themes/deltares-fews-theme/package.json | 2 +- themes/deltares-fews-theme/src/templates/user_personal.ftl | 5 ----- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/configs/artifacts-release.json b/configs/artifacts-release.json index 7bc12087..2c481414 100644 --- a/configs/artifacts-release.json +++ b/configs/artifacts-release.json @@ -50,7 +50,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.worth.portal.context.contributor", - "version" : "1.1.3", + "version" : "1.1.4", "extension" : "jar" }, { @@ -117,7 +117,7 @@ { "groupId" : "nl.deltares", "artifactId" : "deltares-fews-theme", - "version" : "1.1.5", + "version" : "1.1.6", "extension" : "war" } ] \ No newline at end of file diff --git a/modules/context-contributors/bnd.bnd b/modules/context-contributors/bnd.bnd index e8128813..93a387f0 100644 --- a/modules/context-contributors/bnd.bnd +++ b/modules/context-contributors/bnd.bnd @@ -1,4 +1,4 @@ Bundle-Name: context-contributors Bundle-SymbolicName: nl.worth.portal.context.contributor -Bundle-Version: 1.1.3 +Bundle-Version: 1.1.4 -noee: true diff --git a/modules/context-contributors/src/main/java/nl/worth/portal/context/contributor/UtilsTemplateContextContributor.java b/modules/context-contributors/src/main/java/nl/worth/portal/context/contributor/UtilsTemplateContextContributor.java index 912dffe1..9c7a6a18 100644 --- a/modules/context-contributors/src/main/java/nl/worth/portal/context/contributor/UtilsTemplateContextContributor.java +++ b/modules/context-contributors/src/main/java/nl/worth/portal/context/contributor/UtilsTemplateContextContributor.java @@ -72,7 +72,6 @@ public void prepare(Map contextObjects, HttpServletRequest reque } contextObjects.put("is_site_admin", isAdmin); contextObjects.put("user_signout_url", themeDisplay.getURLSignOut()); - contextObjects.put("user_mailing_url", "/subscriptions"); contextObjects.put("user_account_url", "/account"); contextObjects.put("user_announcements_url", "/announcements"); diff --git a/themes/deltares-fews-theme/package.json b/themes/deltares-fews-theme/package.json index 1c566770..45ac6951 100644 --- a/themes/deltares-fews-theme/package.json +++ b/themes/deltares-fews-theme/package.json @@ -1,6 +1,6 @@ { "name": "deltares-fews-theme", - "version": "1.1.5", + "version": "1.1.6", "main": "package.json", "repository": { "type": "git", diff --git a/themes/deltares-fews-theme/src/templates/user_personal.ftl b/themes/deltares-fews-theme/src/templates/user_personal.ftl index b6770c05..4e2e2ece 100644 --- a/themes/deltares-fews-theme/src/templates/user_personal.ftl +++ b/themes/deltares-fews-theme/src/templates/user_personal.ftl @@ -29,11 +29,6 @@ - <#if user_mailing_url??> - -
  • Logout
  • From 4b843f50e993411e4c96995b47df85cd6cc46826 Mon Sep 17 00:00:00 2001 From: rooij_e Date: Wed, 19 Aug 2026 10:45:20 +0200 Subject: [PATCH 02/13] Add copilot-instructions.md --- .github/copilot-instructions.md | 154 ++++++++++++++++++++++++++++++++ platform.bndrun | 29 ------ 2 files changed, 154 insertions(+), 29 deletions(-) create mode 100644 .github/copilot-instructions.md delete mode 100644 platform.bndrun diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..38c09eaf --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,154 @@ + +% Copilot instructions for the `oss` workspace + +Purpose +------- +This file describes the default, workspace-specific instructions that an automated coding assistant (Copilot) should follow when making suggestions or applying edits in this repository. Follow these guidelines whenever you open, modify, or create files in this workspace. + +Project overview +---------------- +- Multi-module Java/Gradle project located at the repository root. Main Gradle wrapper files: `gradlew`, `gradlew.bat`, `build.gradle`, `settings.gradle`. +- Submodules live under `modules/`. +- Themes live under `themes/`. These are frontend assets (a `package.json`). + +High-level goals for edits +------------------------- +1. Preserve build stability: avoid changes that break a full `./gradlew build` (on Windows: `gradlew.bat build`). +2. Make the minimal change necessary to implement a fix or feature. +3. Run and prefer project-provided build/test/format tooling before proposing changes as final. +4. When in doubt, add tests and keep public APIs backwards compatible. + +How to build locally (Windows) +------------------------------- +Use the Gradle wrapper to build the whole project from the repository root: + +``` +gradlew.bat build +``` + +To run tests for a single module (example): + +``` +cd modules/registration-service +..\..\gradlew.bat :modules:registration-service:test +``` + +If you need a clean build: + +``` +gradlew.bat clean build +``` + +Frontend (node) tasks +---------------------- +If you need to run Node/NPM tasks for the repo root frontend: + +``` +npm install +npm test +``` + +Adjust the working directory if you operate within a module with its own `package.json`. + +Docker / local Liferay environment +---------------------------------- +This repository includes a Docker-based Liferay development environment that can be started from the repository root. On Windows use the Gradle wrapper batch file; on Unix-like systems use the shell wrapper. + +Start Docker/Liferay (Windows - cmd.exe): + +``` +gradlew.bat startLiferay +``` + +Start Docker/Liferay (Unix/macOS): + +``` +./gradlew startLiferay +``` + +Notes: +- Wait for the containers to finish starting before deploying modules. You can check container status with `docker ps` and inspect logs with `docker-compose logs` if needed. +- Once Docker/Liferay is up you can deploy modules from the repository root using Gradle. On Windows: + +``` +gradlew.bat deploy +``` + +Or on Unix/macOS: + +``` +./gradlew deploy +``` + +You can also deploy a single module by running the module's deploy task, for example: + +``` +cd modules/registration-service +..\..\gradlew.bat :modules:registration-service:deploy +``` + +Adjust paths and task names as needed for specific modules. + +Formatting / linting +-------------------- +- Keep existing formatting conventions. If the repo has a formatting tool configured, prefer using that (e.g. `./gradlew fmt` if present) before changing formatting manually. +- Add or update lint fixes conservatively and run the associated checks locally. + +Testing requirements +-------------------- +- For any non-trivial code change, add or update automated tests (unit tests or integration tests) that demonstrate the fix/feature. +- Run `gradlew.bat test` (or module-specific tasks) and ensure tests pass locally before finalizing changes. + +Dependency management +--------------------- +- When adding/updating dependencies update only the smallest set of build files necessary. +- Run `gradlew.bat build` after dependency changes to verify nothing else broke. +- Prefer using existing BOMs and aligned versions used across modules when possible. + +Commit and PR guidelines +------------------------ +- Keep commits small and focused: one logical change per commit. +- Commit messages should have a short summary and a short body when necessary. Example: + + "Fix NPE in UserRegistrationService when email is null\n\n Add a null-check and a unit test that covers the edge case." + +- When proposing changes as a patch in this workspace, include the commands you ran to validate (build/test) and a brief summary of results. + +Files and directories to avoid / sensitive files +--------------------------------------------- +- Do not open or modify secrets or local credential files unless the user explicitly asks and permits it. Examples in this repository include but may not be limited to: + - `gradle-local-with-pw.properties` + - `gradle-local.properties` + - `example-gradle-local.properties` (read-only example ok) + - any `*.keystore`, `*.p12`, or other credential artifacts + +- Avoid leaking values from these files into diffs or suggestions. + +When making automated edits +-------------------------- +- Create minimal, well-scoped patches. Use the repository coding style and preserve formatting of surrounding code. +- Add missing imports and adjust related build files only when required. +- If a refactor touches many modules, prefer splitting into multiple PRs and run a full build after each stage. + +If tests or build fail after an edit +---------------------------------- +1. Re-run with `--stacktrace` and capture the failing task output. +2. Try to localize failure to a single module and create a failing unit test if one does not already exist. +3. Propose a fix with the minimal change and include the failing output and the verification steps in the patch description. + +Additional helpful repository hints +---------------------------------- +- The repository contains many frontend dependencies in `node_modules_cache/` (cached tarballs) — prefer using the provided `package.json` scripts rather than manual changes to `node_modules_cache`. + +Contact / follow-up +------------------- +If you want me to open or modify specific files, list them and I will: + - read their current contents, + - propose the precise minimal patch(s), and + - run / describe the verification steps I used (build/test commands and results). + +If you want stricter or different instructions (for example: prefer Kotlin DSL for Gradle, or use a specific Java style guide), update this file to reflect those preferences. + +-- End of copilot-instructions.md + + diff --git a/platform.bndrun b/platform.bndrun deleted file mode 100644 index 2ba4438e..00000000 --- a/platform.bndrun +++ /dev/null @@ -1,29 +0,0 @@ -## Check GETTING_STARTED.markdown#platform.bndrun for more information. - --distro: ${targetPlatformDistro};x-whitelist=osgi.wiring.host --resolve.effective: active --runprovidedcapabilities:\ - osgi.service;objectClass:List='com.liferay.asset.kernel.service.persistence.AssetCategoryPersistence',\ - osgi.service;objectClass:List='com.liferay.frontend.js.loader.modules.extender.npm.NPMResolver',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.configuration.Configuration',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.dao.orm.SessionFactory',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.json.JSONFactory',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.language.Language',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.model.Portlet',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.portlet.PortletPreferencesFactory',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.portlet.PortletURLFactory',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.service.persistence.LayoutSetPersistence',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.File',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.Html',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.Http',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.MimeTypes',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.Portal',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.PrefsProps',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.util.Props',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.xml.SAXReader',\ - osgi.service;objectClass:List='com.liferay.portal.kernel.zip.ZipReaderFactory',\ - osgi.service;objectClass:List='javax.servlet.ServletContext',\ - osgi.service;objectClass:List='javax.sql.DataSource',\ - osgi.wiring.package;osgi.wiring.package=com.sun.nio.file --runrequires: osgi.identity;filter:='(osgi.identity=${project.bundle.Bundle-SymbolicName})' \ No newline at end of file From dfd5d47e8b38ec447dfef539c3df835c6ff40759 Mon Sep 17 00:00:00 2001 From: rooij_e Date: Tue, 25 Aug 2026 13:50:16 +0200 Subject: [PATCH 03/13] Switch back from Podman to Docker-Desktop --- build.gradle | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index ff9c12ec..be0b31e0 100755 --- a/build.gradle +++ b/build.gradle @@ -56,8 +56,13 @@ task startContainers( System.out.println('dockerComposeFilePath: ' + dockerComposeFilePath) System.out.println('bundleDir: ' + bundleDir) exec { - executable 'podman' - args('compose', '-p', dockerContainerPrefix, '-f', dockerComposeFilePath, 'up', '--build', '--force-recreate', '-d') +// Docker compose + executable 'docker-compose' + args('-p', dockerContainerPrefix, '-f', dockerComposeFilePath, 'up', '--build', '--force-recreate', '-d') + +// Podman +// executable 'podman' +// args('compose', '-p', dockerContainerPrefix, '-f', dockerComposeFilePath, 'up', '--build', '--force-recreate', '-d') environment('LIFERAY_BUNDLE_DIR', bundleDir) standardOutput = System.out errorOutput = System.err @@ -141,8 +146,13 @@ task stopLiferay( ) { doLast { exec { - executable 'podman' - args('compose', '-p', dockerContainerPrefix, '-f', dockerComposeFilePath, 'down', '--rmi', 'local') +// Docker Compose + executable 'docker-compose' + args('-p', dockerContainerPrefix, '-f', dockerComposeFilePath, 'down', '--rmi', 'local') + +// Podman +// executable 'podman' +// args('compose', '-p', dockerContainerPrefix, '-f', dockerComposeFilePath, 'down', '--rmi', 'local') standardOutput = System.out errorOutput = System.err } @@ -156,7 +166,7 @@ task dumpDB( ) { doLast { exec { - executable 'podman' + executable 'docker-compose' args('exec', '-t', "${dockerContainerPrefix}-mariadb-74", 'mysqldump', "-u${dbUser}", "-p${dbPassword}", '--extended-insert=FALSE', '--no-autocommit', '--opt', "${dbName}") standardOutput new FileOutputStream("${projectDir}/docker/resources/dump-${dbName}.sql") From a086075afd8c2f3a7138608bca2c5c9bd0ae2696 Mon Sep 17 00:00:00 2001 From: rooij_e Date: Tue, 25 Aug 2026 13:52:44 +0200 Subject: [PATCH 04/13] MYDELTARES-484: Improve filtering of Registrations table --- .../service/RegistrationLocalService.java | 7 ++++ .../service/RegistrationLocalServiceUtil.java | 13 +++++++ .../RegistrationLocalServiceWrapper.java | 16 +++++++++ .../impl/RegistrationLocalServiceImpl.java | 36 ++++++++++++++++++- .../src/main/resources/service.properties | 4 +-- 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java index 7c23ee29..fe4dbe08 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java @@ -270,6 +270,13 @@ public List getArticleRegistrations( public List getArticleRegistrations( long groupId, long articleResourceId, int start, int end); + @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) + public List getDistinctEventResourceIds(long companyId, long groupId); + + @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) + public List getDistinctRegistrationResourceIds( + long companyId, long groupId, long eventResourceId, long userId); + @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) public List getEventRegistrations( long groupId, long eventResourceId); diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java index f1ee45d6..660bd077 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java @@ -316,6 +316,19 @@ public static List getArticleRegistrations( groupId, articleResourceId, start, end); } + public static List getDistinctEventResourceIds( + long companyId, long groupId) { + + return getService().getDistinctEventResourceIds(companyId, groupId); + } + + public static List getDistinctRegistrationResourceIds( + long companyId, long groupId, long eventResourceId, long userId) { + + return getService().getDistinctRegistrationResourceIds( + companyId, groupId, eventResourceId, userId); + } + public static List getEventRegistrations( long groupId, long eventResourceId) { diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java index 101b24b4..09d32aca 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java @@ -354,6 +354,22 @@ public nl.deltares.dsd.registration.model.Registration fetchRegistration( groupId, articleResourceId, start, end); } + @Override + public java.util.List getDistinctEventResourceIds( + long companyId, long groupId) { + + return _registrationLocalService.getDistinctEventResourceIds( + companyId, groupId); + } + + @Override + public java.util.List getDistinctRegistrationResourceIds( + long companyId, long groupId, long eventResourceId, long userId) { + + return _registrationLocalService.getDistinctRegistrationResourceIds( + companyId, groupId, eventResourceId, userId); + } + @Override public java.util.List getEventRegistrations(long groupId, long eventResourceId) { diff --git a/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java b/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java index a1f7edc9..477e0341 100644 --- a/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java +++ b/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java @@ -173,6 +173,41 @@ public void deleteUserRegistration(long groupId, long resourceId, long userId, D } + public List getDistinctEventResourceIds(long companyId, long groupId) { + + Criterion checkCompanyId = PropertyFactoryUtil.forName("companyId").eq(companyId); + Criterion checkGroupId = PropertyFactoryUtil.forName("groupId").eq(groupId); + + DynamicQuery query = DynamicQueryFactoryUtil.forClass(Registration.class, getClass().getClassLoader()) + .add(checkCompanyId).add(checkGroupId); + + Projection distinct = ProjectionFactoryUtil.distinct(PropertyFactoryUtil.forName("eventResourcePrimaryKey")); + query.setProjection(distinct); + + return RegistrationUtil.getPersistence().findWithDynamicQuery(query); + } + + public List getDistinctRegistrationResourceIds(long companyId, long groupId, long eventResourceId, long userId) { + + Criterion checkCompanyId = PropertyFactoryUtil.forName("companyId").eq(companyId); + Criterion checkGroupId = PropertyFactoryUtil.forName("groupId").eq(groupId); + + DynamicQuery query = DynamicQueryFactoryUtil.forClass(Registration.class, getClass().getClassLoader()) + .add(checkCompanyId).add(checkGroupId); + if (eventResourceId > 0L) { + Criterion checkEventResourceId = PropertyFactoryUtil.forName("eventResourcePrimaryKey").eq(eventResourceId); + query.add(checkEventResourceId); + } + if (userId > 0L) { + Criterion checkUserId = PropertyFactoryUtil.forName("userId").eq(userId); + query.add(checkUserId); + } + Projection distinct = ProjectionFactoryUtil.distinct(PropertyFactoryUtil.forName("resourcePrimaryKey")); + query.setProjection(distinct); + + return RegistrationUtil.getPersistence().findWithDynamicQuery(query); + } + private DynamicQuery getDynamicQuery(long groupId, long resourceId, long userId, Date startDate) { Criterion checkUserId = PropertyFactoryUtil.forName("userId").eq(userId); Criterion checkGroupId = PropertyFactoryUtil.forName("groupId").eq(groupId); @@ -240,7 +275,6 @@ public List getRegistrationDates(long groupId, long userId, long resourceI public List getUserEventRegistrations(long groupId, long userId, long eventResourceId) { return RegistrationUtil.findByUserEventRegistrations(groupId, userId, eventResourceId); - } public List getEventRegistrations(long groupId, long eventResourceId) { diff --git a/modules/registration-service/registration-service-service/src/main/resources/service.properties b/modules/registration-service/registration-service-service/src/main/resources/service.properties index 681e1d06..44c3a253 100644 --- a/modules/registration-service/registration-service-service/src/main/resources/service.properties +++ b/modules/registration-service/registration-service-service/src/main/resources/service.properties @@ -13,5 +13,5 @@ ## build.namespace=nl.deltares.dsd.registration.service - build.number=68 - build.date=1758619542436 \ No newline at end of file + build.number=82 + build.date=1787647108710 \ No newline at end of file From e670409b33a19fa02fd8ed70c4cf3a3bdbe28e63 Mon Sep 17 00:00:00 2001 From: rooij_e Date: Tue, 25 Aug 2026 13:52:53 +0200 Subject: [PATCH 05/13] MYDELTARES-484: Improve filtering of Registrations table --- .../portlet/RegistrationTablePortlet.java | 169 ++++++++++++------ .../META-INF/resources/editRegistration.jsp | 12 +- .../META-INF/resources/registrationTable.jsp | 132 ++++++++------ .../resources/content/Language.properties | 4 +- 4 files changed, 201 insertions(+), 116 deletions(-) diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java index 71cc0026..00bfdc07 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java @@ -58,18 +58,59 @@ public void render(RenderRequest renderRequest, RenderResponse renderResponse) t final int curPage = ParamUtil.getInteger(renderRequest, "cur", 1); final int deltas = ParamUtil.getInteger(renderRequest, "delta", 25); - final String filterValue = ParamUtil.getString(renderRequest, "filterValue", null); - final String filterSelection = ParamUtil.getString(renderRequest, "filterSelection", null); - + final String filterEmailValue = ParamUtil.getString(renderRequest, "filterEmailValue", null); + final long filterEventValue = Long.parseLong(ParamUtil.getString(renderRequest, "filterEventValue", "0")); + final long filterRegistrationValue = Long.parseLong(ParamUtil.getString(renderRequest, "filterRegistrationValue", "0")); final String path = ParamUtil.getString(renderRequest, "mvcPath", null); + if (path != null && path.endsWith("editRegistration.jsp")) { doLoadRegistration(renderRequest); } else { - doFilterValues(filterValue, filterSelection, curPage, deltas, renderRequest); + doFilterValues(filterEmailValue, filterEventValue, filterRegistrationValue, curPage, deltas, renderRequest); } + + if (filterEmailValue != null) renderRequest.setAttribute("filterEmailValue", filterEmailValue); + if (filterRegistrationValue > 0) renderRequest.setAttribute("filterRegistrationValue", String.valueOf(filterRegistrationValue)); + if (filterEventValue > 0) renderRequest.setAttribute("filterEventValue", String.valueOf(filterEventValue)); + super.render(renderRequest, renderResponse); } + private Map doLoadEventTitles(ThemeDisplay themeDisplay) { + + Map titles = new HashMap<>(); + + List resourceIds = RegistrationLocalServiceUtil.getDistinctEventResourceIds( + themeDisplay.getCompanyId(), themeDisplay.getSiteGroupId()); + doLoadResourceTitle(resourceIds, titles); + return titles; + } + + private Map doLoadRegistrationTitles(ThemeDisplay themeDisplay, Long selectedEventResourceId, Long selectedUserId) { + + if (selectedEventResourceId == null) {return Collections.emptyMap();} + + Map titles = new HashMap<>(); + List resourceIds = RegistrationLocalServiceUtil.getDistinctRegistrationResourceIds( + themeDisplay.getCompanyId(), themeDisplay.getSiteGroupId(), selectedEventResourceId, selectedUserId); + doLoadResourceTitle(resourceIds, titles); + return titles; + } + + private void doLoadResourceTitle(List resourcePrimaryKeys, Map titles) { + for (Long resourceId : resourcePrimaryKeys) { + if (titles.containsKey(resourceId)) {continue;} + try { + JournalArticle journalArticle = dsdJournalArticleUtils.getLatestArticle(resourceId); + if (journalArticle != null) titles.put(resourceId, journalArticle.getTitle()); + } catch (PortalException e) { + + //Article no longer exists; + titles.put(resourceId, String.valueOf(resourceId)); + } + } + } + private void doLoadRegistration(RenderRequest renderRequest) { final String recordId = ParamUtil.getString(renderRequest, "recordId", null); @@ -104,8 +145,7 @@ private void doLoadRegistration(RenderRequest renderRequest) { } catch (PortalException e) { sessionName = String.valueOf(registration.getResourcePrimaryKey()); } - final String email = ParamUtil.getString(renderRequest, "filterEmail", null); - + final String email = ParamUtil.getString(renderRequest, "editEmailValue", null); renderRequest.setAttribute("record", new DisplayRegistration(id, registration.getResourcePrimaryKey(), eventResourceId, email, eventName, sessionName, formatJson(registration.getUserPreferences()), registration.getStartTime(), registration.getEndTime())); @@ -122,52 +162,51 @@ private String formatJson(String json) { } - private void doFilterValues(String filterValue, String filterSelection, int curPage, int deltas, RenderRequest renderRequest) { + private void doFilterValues(String filterEmailValue, long filterEventValue, long filterRegistrationValue, int curPage, int deltas, RenderRequest renderRequest) { ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest .getAttribute(WebKeys.THEME_DISPLAY); - final long siteGroupId = themeDisplay.getSiteGroupId(); + Map eventTitles = doLoadEventTitles(themeDisplay); + renderRequest.setAttribute("eventTitles", eventTitles); + long userId = 0; + if (filterEmailValue != null && !filterEmailValue.trim().isEmpty()) { + User user = UserLocalServiceUtil.fetchUserByEmailAddress(themeDisplay.getCompanyId(), filterEmailValue); + userId = user != null ? user.getUserId() : 0; + } + + Map registrationTitles = doLoadRegistrationTitles(themeDisplay, filterEventValue, userId); + renderRequest.setAttribute("registrationTitles", registrationTitles); - List registrations = null; - int recordCount = 0; + final long siteGroupId = themeDisplay.getSiteGroupId(); + + List registrations; + int recordCount; final int start = (curPage - 1) * deltas; final int end = curPage * deltas; try { - if (filterValue != null && !filterValue.trim().isEmpty()) { - switch (filterSelection) { - case "email": - User user = UserLocalServiceUtil.getUserByEmailAddress(themeDisplay.getCompanyId(), filterValue); - registrations = RegistrationLocalServiceUtil.getUserRegistrations(siteGroupId, user.getUserId(), start, end); - recordCount = RegistrationLocalServiceUtil.getUserRegistrationsCount(siteGroupId, user.getUserId()); - break; - case "resourceid": { - final long articleResourceId = Long.parseLong(filterValue); - registrations = RegistrationLocalServiceUtil.getArticleRegistrations(siteGroupId, articleResourceId, start, end); - recordCount = RegistrationLocalServiceUtil.getRegistrationsCount(siteGroupId, articleResourceId); - break; - } - case "eventid": { - final long eventResourceId = Long.parseLong(filterValue); - registrations = RegistrationLocalServiceUtil.getEventRegistrations(siteGroupId, eventResourceId, start, end); - recordCount = RegistrationLocalServiceUtil.getEventRegistrationsCount(siteGroupId, eventResourceId); - break; - } - } - } - if (registrations == null) { - registrations = RegistrationLocalServiceUtil.getRegistrations(start, end); - recordCount = RegistrationLocalServiceUtil.getRegistrationsCount(); + if (userId > 0) { + registrations = RegistrationLocalServiceUtil.getUserRegistrations(siteGroupId, userId, start, end); + recordCount = RegistrationLocalServiceUtil.getUserRegistrationsCount(siteGroupId, userId); + } else if (filterRegistrationValue > 0) { + registrations = RegistrationLocalServiceUtil.getArticleRegistrations(siteGroupId, filterRegistrationValue, start, end); + recordCount = RegistrationLocalServiceUtil.getRegistrationsCount(siteGroupId, filterRegistrationValue); + } else if (filterEventValue > 0) { + registrations = RegistrationLocalServiceUtil.getEventRegistrations(siteGroupId, filterEventValue, start, end); + recordCount = RegistrationLocalServiceUtil.getEventRegistrationsCount(siteGroupId, filterEventValue); + } else { + registrations = Collections.emptyList(); + recordCount = 0; } + List displays = convertToDisplayValues(registrations, eventTitles, registrationTitles); + String orderByCol = ParamUtil.getString(renderRequest, "orderByCol"); String orderByType = ParamUtil.getString(renderRequest, "orderByType"); - final List displays = convertToDisplayRegistrations(registrations); sortDownloads(displays, orderByCol, orderByType); + renderRequest.setAttribute("records", displays); renderRequest.setAttribute("total", recordCount); - renderRequest.setAttribute("filterValue", filterValue); - renderRequest.setAttribute("filterSelection", filterSelection); } catch (Exception e) { SessionErrors.add(renderRequest, "filter-failed", e.getMessage()); @@ -188,27 +227,41 @@ private JournalArticle getArticleByResourcePrimaryKey(long resourceId, Map convertToDisplayRegistrations(List registrations) { + private List convertToDisplayValues(List registrations, + Map eventTitles, Map registrationTitles) { final ArrayList displays = new ArrayList<>(registrations.size()); Map articleCache = new HashMap<>(); registrations.forEach(registration -> { - String registrationTitle; - String eventTitle; - final long registrationPrimaryKey = registration.getResourcePrimaryKey(); - JournalArticle registrationArticle = getArticleByResourcePrimaryKey(registrationPrimaryKey, articleCache); - registrationTitle = registrationArticle != null ? registrationArticle.getTitle() : ""; + + String registrationTitle = registrationTitles.get(registrationPrimaryKey); + if (registrationTitle == null) { + JournalArticle registrationArticle = getArticleByResourcePrimaryKey(registrationPrimaryKey, articleCache); + if (registrationArticle != null) { + registrationTitle = registrationArticle.getTitle(); + registrationTitles.put(registrationPrimaryKey, registrationTitle); + } else { + registrationTitle = String.valueOf(registrationPrimaryKey); + } + } + final long eventResourcePrimaryKey = registration.getEventResourcePrimaryKey(); - JournalArticle eventArticle = getArticleByResourcePrimaryKey(eventResourcePrimaryKey, articleCache); - eventTitle = eventArticle != null ? eventArticle.getTitle() : ""; + String eventTitle = eventTitles.get(eventResourcePrimaryKey); + if (eventTitle == null) { + JournalArticle eventArticle = getArticleByResourcePrimaryKey(eventResourcePrimaryKey, articleCache); + if (eventArticle != null) { + eventTitle = eventArticle.getTitle(); + eventTitles.put(eventResourcePrimaryKey, eventTitle); + } else { + eventTitle = String.valueOf(eventResourcePrimaryKey); + } + } final User user = UserLocalServiceUtil.fetchUser(registration.getUserId()); - final String email = user != null ? user.getEmailAddress() : ""; + final String email = user != null ? user.getEmailAddress() : String.valueOf(registration.getUserId()); displays.add(new DisplayRegistration(registration.getRegistrationId(), registrationPrimaryKey, eventResourcePrimaryKey, email, eventTitle, registrationTitle, null, registration.getStartTime(), registration.getEndTime())); }); - - displays.sort(DisplayRegistration::compareTo); return displays; } @@ -221,8 +274,13 @@ private List convertToDisplayRegistrations(List - + + + + - + + + diff --git a/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp b/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp index 042f75af..36f61a34 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp +++ b/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp @@ -4,34 +4,38 @@ <%@ taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %> <%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %> <%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %> +<%@ page import="com.liferay.portal.kernel.dao.search.RowChecker" %> <%@ page import="com.liferay.portal.kernel.language.LanguageUtil" %> <%@ page import="com.liferay.portal.kernel.servlet.SessionErrors" %> <%@ page import="com.liferay.portal.kernel.servlet.SessionMessages" %> -<%@ page import="com.liferay.portal.kernel.dao.search.RowChecker" %> +<%@ page import="java.util.Map" %> <% final Integer count = (Integer) request.getAttribute("total"); - final String filterValue = (String) request.getAttribute("filterValue"); - final String filterSelection = (String) request.getAttribute("filterSelection"); + final String filterEmailValue = (String) request.getAttribute("filterEmailValue"); + final String filterEventValue = (String) request.getAttribute("filterEventValue"); + final String filterRegistrationValue = (String) request.getAttribute("filterRegistrationValue"); + final Map eventTitles = (Map) request.getAttribute("eventTitles"); + final Map registrationTitles = (Map) request.getAttribute("registrationTitles"); %> - - + - - + + + - + - + -
    +
    +
    + + +
    + - +
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    + + + Select... + <% + for (Map.Entry eventInfo : eventTitles.entrySet()) { + %> + + <% + } + %> + - - - + + + Select... + <% + for (Map.Entry registrationInfo : registrationTitles.entrySet()) { + %> + + <% + } + %> +
    + + + +

    - + - - + + - - - - - - - - <%-- --%> + + + + + - + - + + + + - + + + - - + + @@ -141,7 +155,7 @@ let deleteButtons = document.getElementsByClassName("deleteButton"); Array.from(deleteButtons).forEach(function (button) { - button.addEventListener('click', function (event){ + button.addEventListener('click', function (event) { if (confirm("You are about to delete this registration.\nDo you want to continue?") === false) { event.preventDefault(); } diff --git a/modules/tableviews/src/main/resources/content/Language.properties b/modules/tableviews/src/main/resources/content/Language.properties index a4429d45..38ab1f0f 100644 --- a/modules/tableviews/src/main/resources/content/Language.properties +++ b/modules/tableviews/src/main/resources/content/Language.properties @@ -4,8 +4,8 @@ table.download.title=Downloads table table.registration.title=Registrations table table.registration.edit.title=Edit Registration table.downloads.count.title=Downloads count -table.filter.label=Select filter -table.filter.email.label=Enter search e-mail +table.filter.email.label=Search e-mail +table.filter.selection.label=Search selection table.filter.button=Filter table.filter.clear=Clear filter table.update.label=Update share info From 8ca4261f04cc1ba7485291dce451d8103adf0344 Mon Sep 17 00:00:00 2001 From: rooij_e Date: Wed, 26 Aug 2026 11:43:52 +0200 Subject: [PATCH 06/13] MYDELTARES-484: Improve filtering of Registrations table --- .../service/RegistrationLocalService.java | 10 +++ .../service/RegistrationLocalServiceUtil.java | 13 ++++ .../RegistrationLocalServiceWrapper.java | 15 +++++ .../impl/RegistrationLocalServiceImpl.java | 12 ++++ .../src/main/resources/service.properties | 4 +- .../portlet/RegistrationTablePortlet.java | 61 +++++++++++++++---- .../META-INF/resources/css/main.scss | 4 ++ .../META-INF/resources/registrationTable.jsp | 37 +++++++---- 8 files changed, 131 insertions(+), 25 deletions(-) diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java index fe4dbe08..622b5f6f 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java @@ -104,6 +104,16 @@ public PersistedModel createPersistedModel(Serializable primaryKeyObj) */ public void deleteAllEventRegistrations(long groupId, long eventResourceId); + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param groupId Site Identifier + * @param registrationResourceId Article Identifier of Event being removed. + */ + public void deleteAllRegistrations( + long groupId, long registrationResourceId); + /** * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId * that matches 'resourceId'. diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java index 660bd077..2c6f750c 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java @@ -104,6 +104,19 @@ public static void deleteAllEventRegistrations( getService().deleteAllEventRegistrations(groupId, eventResourceId); } + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param groupId Site Identifier + * @param registrationResourceId Article Identifier of Event being removed. + */ + public static void deleteAllRegistrations( + long groupId, long registrationResourceId) { + + getService().deleteAllRegistrations(groupId, registrationResourceId); + } + /** * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId * that matches 'resourceId'. diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java index 09d32aca..2c604aa3 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java @@ -107,6 +107,21 @@ public void deleteAllEventRegistrations( groupId, eventResourceId); } + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param groupId Site Identifier + * @param registrationResourceId Article Identifier of Event being removed. + */ + @Override + public void deleteAllRegistrations( + long groupId, long registrationResourceId) { + + _registrationLocalService.deleteAllRegistrations( + groupId, registrationResourceId); + } + /** * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId * that matches 'resourceId'. diff --git a/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java b/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java index 477e0341..e18e63e5 100644 --- a/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java +++ b/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java @@ -121,6 +121,18 @@ public void deleteAllEventRegistrations(long groupId, long eventResourceId) { RegistrationUtil.removeByEventRegistrations(groupId, eventResourceId); } + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param groupId Site Identifier + * @param registrationResourceId Article Identifier of Event being removed. + */ + public void deleteAllRegistrations(long groupId, long registrationResourceId) { + + //Remove all registrations with a parentArticleId equal to resourceId + RegistrationUtil.removeByArticleRegistrations(groupId, registrationResourceId); + } /** * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId * that matches 'resourceId'. diff --git a/modules/registration-service/registration-service-service/src/main/resources/service.properties b/modules/registration-service/registration-service-service/src/main/resources/service.properties index 44c3a253..3a2b2c54 100644 --- a/modules/registration-service/registration-service-service/src/main/resources/service.properties +++ b/modules/registration-service/registration-service-service/src/main/resources/service.properties @@ -13,5 +13,5 @@ ## build.namespace=nl.deltares.dsd.registration.service - build.number=82 - build.date=1787647108710 \ No newline at end of file + build.number=83 + build.date=1787662775198 \ No newline at end of file diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java index 00bfdc07..022a8364 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java @@ -58,7 +58,7 @@ public void render(RenderRequest renderRequest, RenderResponse renderResponse) t final int curPage = ParamUtil.getInteger(renderRequest, "cur", 1); final int deltas = ParamUtil.getInteger(renderRequest, "delta", 25); - final String filterEmailValue = ParamUtil.getString(renderRequest, "filterEmailValue", null); + final String filterEmailValue = ParamUtil.getString(renderRequest, "filterEmailValue", ""); final long filterEventValue = Long.parseLong(ParamUtil.getString(renderRequest, "filterEventValue", "0")); final long filterRegistrationValue = Long.parseLong(ParamUtil.getString(renderRequest, "filterRegistrationValue", "0")); final String path = ParamUtil.getString(renderRequest, "mvcPath", null); @@ -69,9 +69,15 @@ public void render(RenderRequest renderRequest, RenderResponse renderResponse) t doFilterValues(filterEmailValue, filterEventValue, filterRegistrationValue, curPage, deltas, renderRequest); } - if (filterEmailValue != null) renderRequest.setAttribute("filterEmailValue", filterEmailValue); - if (filterRegistrationValue > 0) renderRequest.setAttribute("filterRegistrationValue", String.valueOf(filterRegistrationValue)); - if (filterEventValue > 0) renderRequest.setAttribute("filterEventValue", String.valueOf(filterEventValue)); + if (filterEmailValue.isEmpty()) { + renderRequest.setAttribute("filterEmailValue", ""); + renderRequest.setAttribute("filterRegistrationValue", String.valueOf(filterRegistrationValue)); + renderRequest.setAttribute("filterEventValue", String.valueOf(filterEventValue)); + } else { + renderRequest.setAttribute("filterEmailValue", filterEmailValue); + renderRequest.setAttribute("filterRegistrationValue", "0"); + renderRequest.setAttribute("filterEventValue", "0"); + } super.render(renderRequest, renderResponse); } @@ -272,15 +278,48 @@ private List convertToDisplayValues(List regi * @param actionResponse Filter response */ @SuppressWarnings("unused") - public void filter(ActionRequest actionRequest, ActionResponse actionResponse) { + public void filterEmail(ActionRequest actionRequest, ActionResponse actionResponse) { - final String selectedEmail = ParamUtil.getString(actionRequest, "filterEmailValue", null); - final String filterEventValue = ParamUtil.getString(actionRequest, "filterEventValue", null); - final String filterRegistrationValue = ParamUtil.getString(actionRequest, "filterRegistrationValue", null); + final String selectedEmail = ParamUtil.getString(actionRequest, "filterEmailValue", ""); - actionResponse.getRenderParameters().setValue("filterEmailValue", selectedEmail); - actionResponse.getRenderParameters().setValue("filterEventValue", selectedEmail); - actionResponse.getRenderParameters().setValue("filterRegistrationValue", selectedEmail); + if ( !selectedEmail.isEmpty() ) { + RenderURL redirectURL = actionResponse.createRedirectURL(MimeResponse.Copy.ALL); + redirectURL.getRenderParameters().setValue("filterEmailValue", selectedEmail); + redirectURL.getRenderParameters().setValue("filterEventValue", "0"); + redirectURL.getRenderParameters().setValue("filterRegistrationValue", "0"); + + try { + actionResponse.sendRedirect(redirectURL.toString()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Pass the selected filter options to the render request + * + * @param actionRequest Filter action + * @param actionResponse Filter response + */ + @SuppressWarnings("unused") + public void filterSelections(ActionRequest actionRequest, ActionResponse actionResponse) { + + final String selectedEventValue = ParamUtil.getString(actionRequest, "filterEventValue", ""); + final String selectedRegistrationValue = ParamUtil.getString(actionRequest, "filterRegistrationValue", ""); + + if ( !selectedEventValue.isEmpty() ) { + RenderURL redirectURL = actionResponse.createRedirectURL(MimeResponse.Copy.ALL); + redirectURL.getRenderParameters().setValue("filterEmailValue", ""); + redirectURL.getRenderParameters().setValue("filterEventValue", selectedEventValue); + redirectURL.getRenderParameters().setValue("filterRegistrationValue", selectedRegistrationValue); + + try { + actionResponse.sendRedirect(redirectURL.toString()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } /** diff --git a/modules/tableviews/src/main/resources/META-INF/resources/css/main.scss b/modules/tableviews/src/main/resources/META-INF/resources/css/main.scss index 762161be..e382d7f3 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/css/main.scss +++ b/modules/tableviews/src/main/resources/META-INF/resources/css/main.scss @@ -1,3 +1,7 @@ .table thead th, .table thead td { vertical-align: top; +} + +.float-right { + float: right; } \ No newline at end of file diff --git a/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp b/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp index 36f61a34..589d7cb8 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp +++ b/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp @@ -25,17 +25,14 @@ - - - - - + + - + +
    - + + + + + +
    +
    +
    + + +
    @@ -78,7 +86,7 @@
    - + Select... <% for (Map.Entry registrationInfo : registrationTitles.entrySet()) { @@ -90,12 +98,16 @@
    - - - - +
    + + <%-- Don't pass filter values so filter fields will be emptied.--%> + + + + +
    @@ -135,6 +147,7 @@
    + From 60bc80694fa446b5e2bb715e8f3ce3536a0f605e Mon Sep 17 00:00:00 2001 From: rooij_e Date: Wed, 26 Aug 2026 14:01:48 +0200 Subject: [PATCH 07/13] MYDELTARES-484: Improve filtering of Registrations table --- .../model/listeners/UserModelListener.java | 37 +++++++++++++++++++ .../service/DownloadLocalService.java | 2 + .../service/DownloadLocalServiceUtil.java | 4 ++ .../service/DownloadLocalServiceWrapper.java | 5 +++ .../impl/DownloadLocalServiceImpl.java | 11 +++++- .../src/main/resources/service.properties | 4 +- .../service/RegistrationLocalService.java | 8 ++++ .../service/RegistrationLocalServiceUtil.java | 10 +++++ .../RegistrationLocalServiceWrapper.java | 11 ++++++ .../impl/RegistrationLocalServiceImpl.java | 18 +++++++++ .../src/main/resources/service.properties | 4 +- 11 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java diff --git a/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java b/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java new file mode 100644 index 00000000..7d212d94 --- /dev/null +++ b/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java @@ -0,0 +1,37 @@ +package nl.deltares.portal.model.listeners; + +import com.liferay.portal.kernel.exception.ModelListenerException; +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; +import com.liferay.portal.kernel.model.BaseModelListener; +import com.liferay.portal.kernel.model.ModelListener; +import com.liferay.portal.kernel.model.User; +import nl.deltares.dsd.registration.service.RegistrationLocalServiceUtil; +import nl.deltares.oss.download.service.DownloadLocalServiceUtil; + +import org.osgi.service.component.annotations.Component; + +@Component(service = ModelListener.class) +public class UserModelListener extends BaseModelListener { + + private static final Log LOGGER = LogFactoryUtil.getLog(UserModelListener.class); + + @Override + public void onBeforeRemove(User model) throws ModelListenerException { + + try { + int count = RegistrationLocalServiceUtil.deleteAllUserRegistrations(model.getUserId()); + if (count > 0) { + LOGGER.info(String.format("Deleting %d Registration references for user %d with email %s", count, model.getUserId(), model.getEmailAddress())); + } + + count = DownloadLocalServiceUtil.deleteAllUserDownloads(model.getUserId()); + if (count > 0) { + LOGGER.info(String.format("Deleting %d Download references for user %d with email %s", count, model.getUserId(), model.getEmailAddress())); + } + } finally { + super.onBeforeRemove(model); + } + + } +} diff --git a/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalService.java b/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalService.java index 06b14c5d..4d666d1c 100644 --- a/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalService.java +++ b/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalService.java @@ -90,6 +90,8 @@ public interface DownloadLocalService public PersistedModel createPersistedModel(Serializable primaryKeyObj) throws PortalException; + public int deleteAllUserDownloads(long userId); + /** * Deletes the download from the database. Also notifies the appropriate model listeners. * diff --git a/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceUtil.java b/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceUtil.java index d9ad1775..5b35718e 100644 --- a/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceUtil.java +++ b/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceUtil.java @@ -87,6 +87,10 @@ public static PersistedModel createPersistedModel( return getService().createPersistedModel(primaryKeyObj); } + public static int deleteAllUserDownloads(long userId) { + return getService().deleteAllUserDownloads(userId); + } + /** * Deletes the download from the database. Also notifies the appropriate model listeners. * diff --git a/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceWrapper.java b/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceWrapper.java index 70cc42be..51ef82ac 100644 --- a/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceWrapper.java +++ b/modules/download/download-api/src/main/java/nl/deltares/oss/download/service/DownloadLocalServiceWrapper.java @@ -89,6 +89,11 @@ public com.liferay.portal.kernel.model.PersistedModel createPersistedModel( return _downloadLocalService.createPersistedModel(primaryKeyObj); } + @Override + public int deleteAllUserDownloads(long userId) { + return _downloadLocalService.deleteAllUserDownloads(userId); + } + /** * Deletes the download from the database. Also notifies the appropriate model listeners. * diff --git a/modules/download/download-service/src/main/java/nl/deltares/oss/download/service/impl/DownloadLocalServiceImpl.java b/modules/download/download-service/src/main/java/nl/deltares/oss/download/service/impl/DownloadLocalServiceImpl.java index 0ed4ed37..99216407 100644 --- a/modules/download/download-service/src/main/java/nl/deltares/oss/download/service/impl/DownloadLocalServiceImpl.java +++ b/modules/download/download-service/src/main/java/nl/deltares/oss/download/service/impl/DownloadLocalServiceImpl.java @@ -158,5 +158,14 @@ private DynamicQuery getGeoLocationQuery(long locationId) { return dynamicQuery; } + public int deleteAllUserDownloads(long userId){ + DynamicQuery dynamicQuery = dynamicQuery(); + dynamicQuery.add(RestrictionsFactoryUtil.eq("userId", userId)); + List withDynamicQuery = DownloadUtil.findWithDynamicQuery(dynamicQuery); + for (Download download : withDynamicQuery) { + DownloadUtil.removeByDownloads(download.getGroupId(), download.getDownloadId()); + } + return withDynamicQuery.size(); + } -} \ No newline at end of file + } \ No newline at end of file diff --git a/modules/download/download-service/src/main/resources/service.properties b/modules/download/download-service/src/main/resources/service.properties index 7a4c6d14..06465cfd 100644 --- a/modules/download/download-service/src/main/resources/service.properties +++ b/modules/download/download-service/src/main/resources/service.properties @@ -13,5 +13,5 @@ ## build.namespace=nl.deltares.oss.download.service - build.number=74 - build.date=1775224821174 \ No newline at end of file + build.number=78 + build.date=1787741990331 \ No newline at end of file diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java index 622b5f6f..b93c27fc 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalService.java @@ -135,6 +135,14 @@ public void deleteAllRegistrationsAndChildRegistrations( public void deleteAllUserEventRegistrations( long groupId, long userId, long eventResourceId); + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param userId Article Identifier of Event being removed. + */ + public int deleteAllUserRegistrations(long userId); + /** * @throws PortalException */ diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java index 2c6f750c..6f8de0fa 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceUtil.java @@ -146,6 +146,16 @@ public static void deleteAllUserEventRegistrations( groupId, userId, eventResourceId); } + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param userId Article Identifier of Event being removed. + */ + public static int deleteAllUserRegistrations(long userId) { + return getService().deleteAllUserRegistrations(userId); + } + /** * @throws PortalException */ diff --git a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java index 2c604aa3..4900c37b 100644 --- a/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java +++ b/modules/registration-service/registration-service-api/src/main/java/nl/deltares/dsd/registration/service/RegistrationLocalServiceWrapper.java @@ -153,6 +153,17 @@ public void deleteAllUserEventRegistrations( groupId, userId, eventResourceId); } + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param userId Article Identifier of Event being removed. + */ + @Override + public int deleteAllUserRegistrations(long userId) { + return _registrationLocalService.deleteAllUserRegistrations(userId); + } + /** * @throws PortalException */ diff --git a/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java b/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java index e18e63e5..e916ac48 100644 --- a/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java +++ b/modules/registration-service/registration-service-service/src/main/java/nl/deltares/dsd/registration/service/impl/RegistrationLocalServiceImpl.java @@ -108,6 +108,24 @@ public void deleteAllRegistrationsAndChildRegistrations(long groupId, long resou } + /** + * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId + * that matches 'resourceId'. + * + * @param userId Article Identifier of Event being removed. + */ + public int deleteAllUserRegistrations(long userId) { + + //Remove all registrations with a parentArticleId equal to resourceId + DynamicQuery dynamicQuery = dynamicQuery(); + dynamicQuery.add(RestrictionsFactoryUtil.eq("userId", userId)); + List withDynamicQuery = RegistrationUtil.findWithDynamicQuery(dynamicQuery); + for (Registration registration : withDynamicQuery) { + RegistrationUtil.removeByUserRegistrations(registration.getGroupId(), registration.getUserId()); + } + return withDynamicQuery.size(); + } + /** * Delete all registrations related to 'resourceId'. This includes all registration with a parentArticleId * that matches 'resourceId'. diff --git a/modules/registration-service/registration-service-service/src/main/resources/service.properties b/modules/registration-service/registration-service-service/src/main/resources/service.properties index 3a2b2c54..502f3297 100644 --- a/modules/registration-service/registration-service-service/src/main/resources/service.properties +++ b/modules/registration-service/registration-service-service/src/main/resources/service.properties @@ -13,5 +13,5 @@ ## build.namespace=nl.deltares.dsd.registration.service - build.number=83 - build.date=1787662775198 \ No newline at end of file + build.number=88 + build.date=1787742420799 \ No newline at end of file From 81d0ceaff15a07422eea12e4ea964bbb670e6dbb Mon Sep 17 00:00:00 2001 From: rooij_e Date: Thu, 27 Aug 2026 10:41:58 +0200 Subject: [PATCH 08/13] MYDELTARES-484: Improve filtering of Registrations table --- .../model/listeners/UserModelListener.java | 30 ++++++++++++++----- .../deltares/portal/utils/AccountUtils.java | 2 ++ .../portal/utils/impl/AccountUtilsImpl.java | 28 +++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java b/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java index 7d212d94..23802704 100644 --- a/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java +++ b/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/UserModelListener.java @@ -6,32 +6,46 @@ import com.liferay.portal.kernel.model.BaseModelListener; import com.liferay.portal.kernel.model.ModelListener; import com.liferay.portal.kernel.model.User; -import nl.deltares.dsd.registration.service.RegistrationLocalServiceUtil; -import nl.deltares.oss.download.service.DownloadLocalServiceUtil; +import nl.deltares.dsd.registration.service.RegistrationLocalService; +import nl.deltares.oss.download.service.DownloadLocalService; +import nl.deltares.portal.utils.AccountUtils; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; @Component(service = ModelListener.class) public class UserModelListener extends BaseModelListener { private static final Log LOGGER = LogFactoryUtil.getLog(UserModelListener.class); - @Override - public void onBeforeRemove(User model) throws ModelListenerException { + @Reference + private AccountUtils accountUtils; + + @Reference + RegistrationLocalService registrationLocalService; + @Reference + DownloadLocalService downloadLocalService; + + @Override + public void onAfterRemove(User model) throws ModelListenerException { try { - int count = RegistrationLocalServiceUtil.deleteAllUserRegistrations(model.getUserId()); + int count = registrationLocalService.deleteAllUserRegistrations(model.getUserId()); if (count > 0) { LOGGER.info(String.format("Deleting %d Registration references for user %d with email %s", count, model.getUserId(), model.getEmailAddress())); } - count = DownloadLocalServiceUtil.deleteAllUserDownloads(model.getUserId()); + count = downloadLocalService.deleteAllUserDownloads(model.getUserId()); if (count > 0) { LOGGER.info(String.format("Deleting %d Download references for user %d with email %s", count, model.getUserId(), model.getEmailAddress())); } + + count = accountUtils.deleteUserPersonalAccount(model.getScreenName()); + if (count > 0) { + LOGGER.info(String.format("Deleting personal account for user %d with email %s", model.getUserId(), model.getEmailAddress())); + } } finally { - super.onBeforeRemove(model); + super.onAfterRemove(model); } - } } diff --git a/modules/common-utils/src/main/java/nl/deltares/portal/utils/AccountUtils.java b/modules/common-utils/src/main/java/nl/deltares/portal/utils/AccountUtils.java index 21175b68..b4efe4a5 100644 --- a/modules/common-utils/src/main/java/nl/deltares/portal/utils/AccountUtils.java +++ b/modules/common-utils/src/main/java/nl/deltares/portal/utils/AccountUtils.java @@ -38,4 +38,6 @@ static String[] getSplitDomains(String domains) { return new String[]{domains}; } } + + int deleteUserPersonalAccount(String screenName); } diff --git a/modules/common-utils/src/main/java/nl/deltares/portal/utils/impl/AccountUtilsImpl.java b/modules/common-utils/src/main/java/nl/deltares/portal/utils/impl/AccountUtilsImpl.java index ce14026b..65364ffa 100644 --- a/modules/common-utils/src/main/java/nl/deltares/portal/utils/impl/AccountUtilsImpl.java +++ b/modules/common-utils/src/main/java/nl/deltares/portal/utils/impl/AccountUtilsImpl.java @@ -13,7 +13,10 @@ import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.*; +import com.liferay.portal.kernel.module.configuration.ConfigurationException; +import com.liferay.portal.kernel.module.configuration.ConfigurationProvider; import com.liferay.portal.kernel.service.*; +import nl.deltares.portal.configuration.SiteMapConfiguration; import nl.deltares.portal.model.AccountInfo; import nl.deltares.portal.model.AddressInfo; import nl.deltares.portal.utils.AccountUtils; @@ -229,6 +232,28 @@ public Address createOrUpdateAddress(AddressInfo addressInfo, long companyId, lo return address; } + @Override + public int deleteUserPersonalAccount(String screenName) { + + String externalReferenceCode = PERSONAL_ACCOUNT_PREFIX + screenName; + long companyId = 101331; + try { + SiteMapConfiguration _configuration = _configurationProvider.getSystemConfiguration(SiteMapConfiguration.class); + companyId = _configuration.accountsCompanyId(); + } catch (ConfigurationException e) { + // + } + AccountEntry accountEntry = _accountEntryLocalService.fetchAccountEntryByExternalReferenceCode(externalReferenceCode, companyId); + if (accountEntry == null) return 0; + + try { + _accountEntryLocalService.deleteAccountEntry(accountEntry.getAccountEntryId()); + } catch (PortalException e) { + return 0; + } + return 1; + } + @Reference private AccountEntryLocalService _accountEntryLocalService; @@ -249,5 +274,8 @@ public Address createOrUpdateAddress(AddressInfo addressInfo, long companyId, lo @Reference private UserLocalService _userLocalService; + + @Reference + private ConfigurationProvider _configurationProvider; } From 747bf992fb40519acbd0c212bb0c052eaa2f78cf Mon Sep 17 00:00:00 2001 From: rooij_e Date: Thu, 27 Aug 2026 11:03:28 +0200 Subject: [PATCH 09/13] MYDELTARES-484: Improve filtering of Registrations table --- configs/artifacts-release.json | 12 ++++++------ modules/common-utils/bnd.bnd | 2 +- modules/download/download-api/bnd.bnd | 2 +- modules/download/download-service/bnd.bnd | 2 +- .../registration-service-api/bnd.bnd | 2 +- .../registration-service-service/bnd.bnd | 2 +- modules/tableviews/bnd.bnd | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/configs/artifacts-release.json b/configs/artifacts-release.json index 2c481414..d50c3105 100644 --- a/configs/artifacts-release.json +++ b/configs/artifacts-release.json @@ -2,25 +2,25 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.dsd.registration.api", - "version" : "1.1.0", + "version" : "1.1.1", "extension" : "jar" }, { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.dsd.registration.service", - "version" : "1.1.0", + "version" : "1.1.1", "extension" : "jar" }, { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.oss.download.api", - "version" : "1.1.2", + "version" : "1.1.3", "extension" : "jar" }, { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.oss.download.service", - "version" : "1.1.2", + "version" : "1.1.3", "extension" : "jar" }, { @@ -38,7 +38,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.portal.common-utils", - "version" : "1.1.41", + "version" : "1.1.42", "extension" : "jar" }, { @@ -93,7 +93,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.tableview.portlet", - "version" : "1.1.7", + "version" : "1.1.8", "extension" : "jar" }, { diff --git a/modules/common-utils/bnd.bnd b/modules/common-utils/bnd.bnd index 5bd3c31b..004c168f 100644 --- a/modules/common-utils/bnd.bnd +++ b/modules/common-utils/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: common-utils Bundle-SymbolicName: nl.deltares.portal.common-utils -Bundle-Version: 1.1.41 +Bundle-Version: 1.1.42 Export-Package: \ nl.deltares.portal.constants, \ nl.deltares.portal.utils, \ diff --git a/modules/download/download-api/bnd.bnd b/modules/download/download-api/bnd.bnd index e0dbb820..454f3209 100644 --- a/modules/download/download-api/bnd.bnd +++ b/modules/download/download-api/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: download-api Bundle-SymbolicName: nl.deltares.oss.download.api -Bundle-Version: 1.1.2 +Bundle-Version: 1.1.3 Export-Package:\ nl.deltares.oss.download.exception,\ nl.deltares.oss.download.model,\ diff --git a/modules/download/download-service/bnd.bnd b/modules/download/download-service/bnd.bnd index bbc7578d..404ba635 100644 --- a/modules/download/download-service/bnd.bnd +++ b/modules/download/download-service/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: download-service Bundle-SymbolicName: nl.deltares.oss.download.service -Bundle-Version: 1.1.2 +Bundle-Version: 1.1.3 Liferay-Require-SchemaVersion: 1.3.0 Liferay-Service: true -dsannotations-options: inherit \ No newline at end of file diff --git a/modules/registration-service/registration-service-api/bnd.bnd b/modules/registration-service/registration-service-api/bnd.bnd index e30f2c75..ba44deb1 100644 --- a/modules/registration-service/registration-service-api/bnd.bnd +++ b/modules/registration-service/registration-service-api/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: registration-service-api Bundle-SymbolicName: nl.deltares.dsd.registration.api -Bundle-Version: 1.1.0 +Bundle-Version: 1.1.1 Export-Package:\ nl.deltares.dsd.registration.exception, \ nl.deltares.dsd.registration.model, \ diff --git a/modules/registration-service/registration-service-service/bnd.bnd b/modules/registration-service/registration-service-service/bnd.bnd index 4cbf65d5..90f0bbaf 100644 --- a/modules/registration-service/registration-service-service/bnd.bnd +++ b/modules/registration-service/registration-service-service/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: registration-service-service Bundle-SymbolicName: nl.deltares.dsd.registration.service -Bundle-Version: 1.1.0 +Bundle-Version: 1.1.1 Liferay-Require-SchemaVersion: 1.2.0 Liferay-Service: true -dsannotations-options: inherit diff --git a/modules/tableviews/bnd.bnd b/modules/tableviews/bnd.bnd index 70336081..9b8a6fe6 100644 --- a/modules/tableviews/bnd.bnd +++ b/modules/tableviews/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: tableviews Bundle-SymbolicName: nl.deltares.tableview.portlet -Bundle-Version: 1.1.7 +Bundle-Version: 1.1.8 Export-Package: nl.deltares.tableview.portlet.constants Import-Package: \ nl.deltares.tasks.*, \ From ef1993c578921ac63e450d9846c2ad14ce93c66b Mon Sep 17 00:00:00 2001 From: rooij_e Date: Wed, 2 Sep 2026 09:33:22 +0200 Subject: [PATCH 10/13] MYDELTARES-484: Improve filtering of Registrations table --- configs/artifacts-release.json | 2 +- modules/tableviews/bnd.bnd | 2 +- .../portlet/portlet/DownloadTablePortlet.java | 118 +++++++++--------- .../impl/DeletedSelectedDownloadsRequest.java | 4 +- ... ExportSelectedDownloadsTableRequest.java} | 118 +++++++++--------- .../resources/downloadCountsTable.jsp | 2 +- .../META-INF/resources/downloadsTable.jsp | 66 ++++------ .../resources/content/Language.properties | 2 +- 8 files changed, 149 insertions(+), 165 deletions(-) rename modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/{ExportDownloadsTableRequest.java => ExportSelectedDownloadsTableRequest.java} (68%) diff --git a/configs/artifacts-release.json b/configs/artifacts-release.json index d50c3105..afa8d2e7 100644 --- a/configs/artifacts-release.json +++ b/configs/artifacts-release.json @@ -93,7 +93,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.tableview.portlet", - "version" : "1.1.8", + "version" : "1.1.9", "extension" : "jar" }, { diff --git a/modules/tableviews/bnd.bnd b/modules/tableviews/bnd.bnd index 9b8a6fe6..5fa86077 100644 --- a/modules/tableviews/bnd.bnd +++ b/modules/tableviews/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: tableviews Bundle-SymbolicName: nl.deltares.tableview.portlet -Bundle-Version: 1.1.8 +Bundle-Version: 1.1.9 Export-Package: nl.deltares.tableview.portlet.constants Import-Package: \ nl.deltares.tasks.*, \ diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java index d82cbc8f..37eebd58 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java @@ -12,17 +12,17 @@ import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.PortalUtil; +import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.util.WebKeys; import nl.deltares.oss.download.model.Download; import nl.deltares.oss.download.service.DownloadLocalServiceUtil; import nl.deltares.oss.geolocation.model.GeoLocation; import nl.deltares.oss.geolocation.service.GeoLocationLocalServiceUtil; import nl.deltares.portal.utils.KeycloakUtils; -import nl.deltares.tableview.comparator.DownloadComparator; import nl.deltares.tableview.model.DisplayDownload; import nl.deltares.tableview.portlet.constants.TablePortletKeys; import nl.deltares.tableview.tasks.impl.DeletedSelectedDownloadsRequest; -import nl.deltares.tableview.tasks.impl.ExportDownloadsTableRequest; +import nl.deltares.tableview.tasks.impl.ExportSelectedDownloadsTableRequest; import nl.deltares.tasks.DataRequest; import nl.deltares.tasks.DataRequestManager; import org.osgi.service.component.annotations.Component; @@ -75,57 +75,60 @@ public void render(RenderRequest renderRequest, RenderResponse renderResponse) t final int curPage = ParamUtil.getInteger(renderRequest, "cur", 1); final int deltas = ParamUtil.getInteger(renderRequest, "delta", 25); - final String filterValue = ParamUtil.getString(renderRequest, "filterValue", null); - final String filterSelection = ParamUtil.getString(renderRequest, "filterSelection", null); + final String filterValue = ParamUtil.getString(renderRequest, "filterValue", ""); final String orderByCol = ParamUtil.getString(renderRequest, "orderByCol", "modifiedDate"); final String orderByType = ParamUtil.getString(renderRequest, "orderByType", "desc"); - doFilterValues(filterValue, filterSelection, curPage, deltas, orderByCol, orderByType, renderRequest); + doFilterValues(filterValue, curPage, deltas, orderByCol, orderByType, renderRequest); + + renderRequest.setAttribute("filterValue", filterValue); super.render(renderRequest, renderResponse); } - private void doFilterValues(String filterValue, String filterSelection, int curPage, int deltas, + private void doFilterValues(String filterValue, int curPage, int deltas, String orderByCol, String orderByType, RenderRequest renderRequest) { ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest .getAttribute(WebKeys.THEME_DISPLAY); + long userId = 0; + String fileNameFilter = null; + if (Validator.isEmailAddress(filterValue)) { + User user = UserLocalServiceUtil.fetchUserByEmailAddress(themeDisplay.getCompanyId(), filterValue); + userId = user != null ? user.getUserId() : 0; + } else if (filterValue != null && !filterValue.trim().isEmpty()) { + fileNameFilter = filterValue.trim(); + } + final long siteGroupId = themeDisplay.getSiteGroupId(); List downloads = null; int downloadsCount = 0; final int start = (curPage - 1) * deltas; final int end = curPage * deltas; try { - if (filterValue != null && !filterValue.trim().isEmpty()) { - switch (filterSelection) { - case "email": - User user = UserLocalServiceUtil.getUserByEmailAddress(themeDisplay.getCompanyId(), filterValue); - downloads = DownloadLocalServiceUtil.findDownloadsByUserId(siteGroupId, user.getUserId(), start, end, orderByCol, orderByType); - downloadsCount = DownloadLocalServiceUtil.countDownloadsByUserId(siteGroupId, user.getUserId()); - break; - case "fileName": - downloads = DownloadLocalServiceUtil.findDownloadsByFileName(siteGroupId, filterValue, start, end, orderByCol, orderByType); - downloadsCount = DownloadLocalServiceUtil.countDownloadsByFileName(siteGroupId, filterValue); - break; - } + if (userId > 0) { + downloads = DownloadLocalServiceUtil.findDownloadsByUserId(siteGroupId, userId, start, end, orderByCol, orderByType); + downloadsCount = DownloadLocalServiceUtil.countDownloadsByUserId(siteGroupId, userId); + } else if (fileNameFilter != null) { + downloads = DownloadLocalServiceUtil.findDownloadsByFileName(siteGroupId, fileNameFilter, start, end, orderByCol, orderByType); + downloadsCount = DownloadLocalServiceUtil.countDownloadsByFileName(siteGroupId, fileNameFilter); } if (downloads == null) { - downloads = DownloadLocalServiceUtil.findDownloads(siteGroupId, start, end, orderByCol, orderByType); - downloadsCount = DownloadLocalServiceUtil.countDownloads(siteGroupId); + renderRequest.setAttribute("records", Collections.emptyList()); + renderRequest.setAttribute("total", 0); + } else { + final List displays = convertToDisplayDownloads(downloads); + renderRequest.setAttribute("records", displays); + renderRequest.setAttribute("total", downloadsCount); } - - final List displays = convertToDisplayDownloads(downloads); - - renderRequest.setAttribute("records", displays); - renderRequest.setAttribute("total", downloadsCount); renderRequest.setAttribute("filterValue", filterValue); - renderRequest.setAttribute("filterSelection", filterSelection); } catch (Exception e) { SessionErrors.add(renderRequest, "filter-failed", e.getMessage()); renderRequest.setAttribute("records", Collections.emptyList()); renderRequest.setAttribute("total", 0); } } + private List convertToDisplayDownloads(List downloads) { final ArrayList displays = new ArrayList<>(downloads.size()); @@ -134,41 +137,44 @@ private List convertToDisplayDownloads(List downloads final DisplayDownload displayDownload = new DisplayDownload(download); displays.add(displayDownload); - if (download.getGeoLocationId() == 0){ - final long userId = download.getUserId(); - Map attributes = userAttributeCache.get(userId); - if (attributes == null){ - final User user = UserLocalServiceUtil.fetchUser(userId); - if (user != null && keycloakUtils.isActive()) { - try { - attributes = keycloakUtils.getUserAttributes(user.getEmailAddress()); - userAttributeCache.put(userId, attributes); - } catch (Exception e) { - logger.warn(String.format("Error getting user attributes for %s: %s", user.getEmailAddress(), e.getMessage())); - attributes = Collections.emptyMap(); - userAttributeCache.put(userId, attributes); - } - } else { - attributes = Collections.emptyMap(); - } - } + if (download.getGeoLocationId() == 0) { + Map attributes = getUserAttributes(download.getUserId(), userAttributeCache); displayDownload.setCity(attributes.get(KeycloakUtils.ATTRIBUTES.org_city.name())); final Country country = CountryLocalServiceUtil.fetchCountryByName(download.getCompanyId(), attributes.get(KeycloakUtils.ATTRIBUTES.org_country.name())); if (country != null) displayDownload.setCountryCode(country.getA2()); - } else { + } else if (download.getGeoLocationId() > 0) { final long geoLocationId = download.getGeoLocationId(); final GeoLocation geoLocation = GeoLocationLocalServiceUtil.fetchGeoLocation(geoLocationId); - if (geoLocation != null){ + if (geoLocation != null) { displayDownload.setCity(geoLocation.getCityName()); Country country = CountryServiceUtil.fetchCountry(geoLocation.getCountryId()); displayDownload.setCountryCode(country.getA2()); } } - }); return displays; } + private Map getUserAttributes(long userId, HashMap> userAttributeCache) { + Map attributes = userAttributeCache.get(userId); + if (attributes == null) { + final User user = UserLocalServiceUtil.fetchUser(userId); + if (user != null && keycloakUtils.isActive()) { + try { + attributes = keycloakUtils.getUserAttributes(user.getEmailAddress()); + userAttributeCache.put(userId, attributes); + } catch (Exception e) { + logger.warn(String.format("Error getting user attributes for %s: %s", user.getEmailAddress(), e.getMessage())); + attributes = Collections.emptyMap(); + userAttributeCache.put(userId, attributes); + } + } else { + attributes = Collections.emptyMap(); + } + } + return attributes; + } + /** * Pass the selected filter options to the render request * @@ -176,12 +182,10 @@ private List convertToDisplayDownloads(List downloads * @param actionResponse Filter response */ @SuppressWarnings("unused") - public void filter(ActionRequest actionRequest, ActionResponse actionResponse) { + public void filterDownloads(ActionRequest actionRequest, ActionResponse actionResponse) { final String filter = ParamUtil.getString(actionRequest, "filterValue", "none"); actionResponse.getRenderParameters().setValue("filterValue", filter); - final String filterSelection = ParamUtil.getString(actionRequest, "filterSelection", "none"); - actionResponse.getRenderParameters().setValue("filterSelection", filterSelection); } @Override @@ -197,13 +201,12 @@ public void serveResource(ResourceRequest request, ResourceResponse response) th String action = ParamUtil.getString(request, "action"); String id = ParamUtil.getString(request, "id", null); String filterValue = ParamUtil.getString(request, "filterValue", null); - String filterSelection = ParamUtil.getString(request, "filterSelection", null); if ("export".equals(action)) { if (id == null) { id = DownloadTablePortlet.class.getName() + themeDisplay.getUserId(); } - exportTable(id, filterValue, filterSelection, response, themeDisplay); + exportTable(id, filterValue, response, themeDisplay); } else if ("delete-selected".equals(action)) { if (id == null) { id = DownloadTablePortlet.class.getName() + themeDisplay.getUserId(); @@ -248,12 +251,12 @@ private void deletedSelected(String dataRequestId, ResourceRequest request, Reso } - private void exportTable(String dataRequestId, String filterValue, String filterSelection, ResourceResponse response, ThemeDisplay themeDisplay) throws IOException { + private void exportTable(String dataRequestId, String filterValue, ResourceResponse response, ThemeDisplay themeDisplay) throws IOException { response.setContentType("text/csv"); DataRequestManager instance = DataRequestManager.getInstance(); DataRequest dataRequest = instance.getDataRequest(dataRequestId); if (dataRequest == null) { - dataRequest = new ExportDownloadsTableRequest(dataRequestId, filterValue, filterSelection, themeDisplay.getUserId(), themeDisplay.getSiteGroup(), keycloakUtils); + dataRequest = new ExportSelectedDownloadsTableRequest(dataRequestId, filterValue, themeDisplay.getUserId(), themeDisplay.getSiteGroup(), keycloakUtils); instance.addToQueue(dataRequest); } else if (dataRequest.getStatus() == DataRequest.STATUS.TERMINATED || dataRequest.getStatus() == DataRequest.STATUS.NODATA) { instance.removeDataRequest(dataRequest); @@ -266,11 +269,4 @@ private void exportTable(String dataRequestId, String filterValue, String filter } - private void sortDownloads(List displays, String orderByCol, String orderByType) { - - final DownloadComparator comparator = new DownloadComparator(orderByCol, orderByType.equals("asc")); - displays.sort(comparator); - - } - } \ No newline at end of file diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedDownloadsRequest.java b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedDownloadsRequest.java index ac73cb3f..7757423c 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedDownloadsRequest.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedDownloadsRequest.java @@ -83,7 +83,9 @@ private void deleteSelectedRecords(PrintWriter writer) { final Download download = DownloadLocalServiceUtil.deleteDownload(Long.parseLong(id)); final User user = UserLocalServiceUtil.fetchUser(download.getUserId()); String email = ""; - if (user != null){ + if (user == null){ + email = String.valueOf(download.getUserId()); + } else { email = user.getEmailAddress(); } final Date modifiedDate = download.getModifiedDate(); diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportDownloadsTableRequest.java b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedDownloadsTableRequest.java similarity index 68% rename from modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportDownloadsTableRequest.java rename to modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedDownloadsTableRequest.java index 1dc325ec..aaf92cfe 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportDownloadsTableRequest.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedDownloadsTableRequest.java @@ -6,6 +6,7 @@ import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.service.CountryServiceUtil; import com.liferay.portal.kernel.service.UserLocalServiceUtil; +import com.liferay.portal.kernel.util.Validator; import nl.deltares.oss.download.model.Download; import nl.deltares.oss.download.service.DownloadLocalServiceUtil; import nl.deltares.oss.geolocation.model.GeoLocation; @@ -19,48 +20,45 @@ import java.io.PrintWriter; import java.nio.file.Files; import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; +import java.util.*; -import static nl.deltares.portal.utils.KeycloakUtils.ATTRIBUTES.org_city; -import static nl.deltares.portal.utils.KeycloakUtils.ATTRIBUTES.org_country; +import static nl.deltares.portal.utils.KeycloakUtils.ATTRIBUTES.*; import static nl.deltares.tasks.DataRequest.STATUS.*; import static nl.deltares.tasks.DataRequest.STATUS.TERMINATED; -public class ExportDownloadsTableRequest extends AbstractDataRequest { +public class ExportSelectedDownloadsTableRequest extends AbstractDataRequest { - private static final Log logger = LogFactoryUtil.getLog(ExportDownloadsTableRequest.class); + private static final Log logger = LogFactoryUtil.getLog(ExportSelectedDownloadsTableRequest.class); private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); static { dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); } - private final Group group; private final String filterValue; - private final String filterSelection; private final boolean findByUser; - private final boolean findByArticleId; protected KeycloakUtils keycloakUtils; - public ExportDownloadsTableRequest(String id, String filterValue, String filterSelection, long currentUserId, Group siteGroup, KeycloakUtils keycloakUtils) throws IOException { + public ExportSelectedDownloadsTableRequest(String id, String filterValue, long currentUserId, Group siteGroup, KeycloakUtils keycloakUtils) throws IOException { super(id, currentUserId); this.group = siteGroup; - this.filterValue = filterValue; - this.filterSelection = filterSelection; - - this.findByUser = "email".equals(filterSelection); - this.findByArticleId = "fileName".equals(filterSelection); - + if (filterValue != null && filterValue.trim().isEmpty()){ + this.filterValue = null; + } else { + this.filterValue = filterValue; + } + this.findByUser = Validator.isEmailAddress(filterValue); this.keycloakUtils = keycloakUtils; } @Override public STATUS call() { if (getStatus() == AVAILABLE) return status; - String filter = filterSelection == null ? "none": filterSelection + " = " + filterValue; - statusMessage = "starting exporting for filter " + filter; + + if (filterValue == null){ + status = NODATA; + return status; + } + statusMessage = "starting exporting for filter " + filterValue; init(); status = RUNNING; try { @@ -102,21 +100,22 @@ private void exportAllRecords(PrintWriter writer) { int start = 0; int end = 100; - final User filterUser; - final String fileName; + HashMap> userAttributesCache = new HashMap<>(); + User filterUser; if (findByUser) { - fileName = null; filterUser = UserLocalServiceUtil.fetchUserByEmailAddress(group.getCompanyId(), filterValue); - if (filterUser != null) totalCount = DownloadLocalServiceUtil.countDownloadsByUserId(group.getGroupId(), filterUser.getUserId()); - } else if (findByArticleId) { - filterUser = null; - fileName = filterValue; - totalCount = DownloadLocalServiceUtil.countDownloadsByFileName(group.getGroupId(), fileName); - } else - { - fileName = null; + if (filterUser == null){ + totalCount = 0; + } else { + totalCount = DownloadLocalServiceUtil.countDownloadsByUserId(group.getGroupId(), filterUser.getUserId()); + } + } else { filterUser = null; - totalCount = DownloadLocalServiceUtil.countDownloads(group.getGroupId()); + if (filterValue != null) { + totalCount = DownloadLocalServiceUtil.countDownloadsByFileName(group.getGroupId(), filterValue); + } else { + totalCount = 0; + } } for (int i = 0; i < totalCount; ) { @@ -124,47 +123,29 @@ private void exportAllRecords(PrintWriter writer) { final List downloads; if (filterUser != null) { downloads = DownloadLocalServiceUtil.findDownloadsByUserId(group.getGroupId(), filterUser.getUserId(), start, end); - } else if (fileName != null ) { - downloads = DownloadLocalServiceUtil.findDownloadsByFileName(group.getGroupId(), fileName, start, end); - } else - { - downloads = DownloadLocalServiceUtil.findDownloads(group.getGroupId(), start, end); + } else { + downloads = DownloadLocalServiceUtil.findDownloadsByFileName(group.getGroupId(), filterValue, start, end); } if (downloads.isEmpty()) { setProcessCount(totalCount); return; } - HashMap> userAttributesCache = new HashMap<>(); downloads.forEach(download -> { if (status == TERMINATED) return; incrementProcessCount(1); - if (group.getGroupId() != download.getGroupId()) return; - String email = ""; - String fullName = ""; - if (filterUser != null){ - email = filterValue; - fullName = filterUser.getFullName(); - } else { - final User user = UserLocalServiceUtil.fetchUser(download.getUserId()); - if (user != null) { - email = user.getEmailAddress(); - fullName = user.getFullName(); - } - } String city = ""; String countryCode = ""; + String fullName; + String email; + User downloadUser = filterUser != null ? filterUser : UserLocalServiceUtil.fetchUser(download.getUserId()); try { if (download.getGeoLocationId() > 0) { final GeoLocation geoLocation = GeoLocationLocalServiceUtil.getGeoLocation(download.getGeoLocationId()); city = geoLocation.getCityName(); countryCode = CountryServiceUtil.getCountry(geoLocation.getCountryId()).getA2(); - } else if (keycloakUtils.isActive()) { - Map attributes = userAttributesCache.get(download.getUserId()); - if (attributes == null){ - attributes = keycloakUtils.getUserAttributes(email); - userAttributesCache.put(download.getUserId(), attributes); - } + } else if (keycloakUtils.isActive() && downloadUser != null) { + Map attributes = getUserAttributes(downloadUser, userAttributesCache); city = attributes.get(org_city.name()); countryCode = attributes.get(org_country.name()); } @@ -178,6 +159,13 @@ private void exportAllRecords(PrintWriter writer) { } else { modifiedDate = ""; } + if (downloadUser != null) { + fullName = downloadUser.getFullName(); + email = downloadUser.getEmailAddress(); + } else { + fullName = String.valueOf(download.getUserId()); + email = ""; + } final String expiryDate; if (download.getExpiryDate() != null) { expiryDate = dateFormat.format(download.getExpiryDate()); @@ -201,4 +189,20 @@ private void exportAllRecords(PrintWriter writer) { } + private Map getUserAttributes(User user, HashMap> userAttributeCache) { + long userId = user.getUserId(); + Map attributes = userAttributeCache.get(userId); + if (attributes == null) { + try { + attributes = keycloakUtils.getUserAttributes(user.getEmailAddress()); + userAttributeCache.put(userId, attributes); + } catch (Exception e) { + logger.warn(String.format("Error getting user attributes for %s: %s", user.getEmailAddress(), e.getMessage())); + attributes = Collections.emptyMap(); + userAttributeCache.put(userId, attributes); + } + } + return attributes; + } + } diff --git a/modules/tableviews/src/main/resources/META-INF/resources/downloadCountsTable.jsp b/modules/tableviews/src/main/resources/META-INF/resources/downloadCountsTable.jsp index 4c62f086..92d4e700 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/downloadCountsTable.jsp +++ b/modules/tableviews/src/main/resources/META-INF/resources/downloadCountsTable.jsp @@ -40,7 +40,7 @@ -
    +
    diff --git a/modules/tableviews/src/main/resources/META-INF/resources/downloadsTable.jsp b/modules/tableviews/src/main/resources/META-INF/resources/downloadsTable.jsp index 1970372f..27afe55d 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/downloadsTable.jsp +++ b/modules/tableviews/src/main/resources/META-INF/resources/downloadsTable.jsp @@ -14,8 +14,6 @@ <% final Integer count = (Integer) request.getAttribute("total"); final String filterValue = (String) request.getAttribute("filterValue"); - final String filterSelection = (String) request.getAttribute("filterSelection"); - %> @@ -25,13 +23,11 @@ - - - + - + - + + -
    +
    - + - -
    -
    - -
    -
    - -
    -
    -
    - - - + + + +
    + + <%-- Don't pass filter values so filter fields will be emptied.--%> + + + + +
    @@ -91,19 +76,16 @@ modelVar="entry" keyProperty="id" > - - + - - + + - -
    @@ -124,14 +106,14 @@ let exportResultsButton = document.getElementById('exportResultsButton'); exportResultsButton.onclick = function(event){ - event.preventDefault(); - TableFormsUtil.exportResults("", "", "export-downloads.csv") + event.preventDefault(); + TableFormsUtil.exportResults("", "", "export-downloads.csv") }; let deleteSelectedButton = document.getElementById('deleteSelectedButton'); deleteSelectedButton.onclick = function(event){ - event.preventDefault(); - TableFormsUtil.deleteSelected("", "", "", "delete-selected-downloads.csv") + event.preventDefault(); + TableFormsUtil.deleteSelected("", "", "", "delete-selected-downloads.csv") }; diff --git a/modules/tableviews/src/main/resources/content/Language.properties b/modules/tableviews/src/main/resources/content/Language.properties index 38ab1f0f..07423171 100644 --- a/modules/tableviews/src/main/resources/content/Language.properties +++ b/modules/tableviews/src/main/resources/content/Language.properties @@ -5,7 +5,7 @@ table.registration.title=Registrations table table.registration.edit.title=Edit Registration table.downloads.count.title=Downloads count table.filter.email.label=Search e-mail -table.filter.selection.label=Search selection +table.filter.selection.label=Search table.filter.button=Filter table.filter.clear=Clear filter table.update.label=Update share info From 9a48044d5cc0bf649c728e04d66c07111b65419f Mon Sep 17 00:00:00 2001 From: rooij_e Date: Wed, 2 Sep 2026 14:30:12 +0200 Subject: [PATCH 11/13] MYDELTARES-484: Improve filtering of Registrations table --- configs/artifacts-release.json | 2 +- modules/tableviews/bnd.bnd | 2 +- .../portlet/portlet/DownloadTablePortlet.java | 2 +- .../portlet/RegistrationTablePortlet.java | 254 ++++++++---------- .../DeletedSelectedRegistrationsRequest.java | 114 ++++++++ ...portSelectedRegistrationsTableRequest.java | 163 +++++++++++ .../tableview/utils/RegistrationUtils.java | 107 ++++++++ .../{downloadtableview.js => tableview.js} | 2 +- .../META-INF/resources/registrationTable.jsp | 34 ++- 9 files changed, 517 insertions(+), 163 deletions(-) create mode 100644 modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedRegistrationsRequest.java create mode 100644 modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedRegistrationsTableRequest.java create mode 100644 modules/tableviews/src/main/java/nl/deltares/tableview/utils/RegistrationUtils.java rename modules/tableviews/src/main/resources/META-INF/resources/lib/{downloadtableview.js => tableview.js} (97%) diff --git a/configs/artifacts-release.json b/configs/artifacts-release.json index afa8d2e7..3a5c4e26 100644 --- a/configs/artifacts-release.json +++ b/configs/artifacts-release.json @@ -93,7 +93,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.tableview.portlet", - "version" : "1.1.9", + "version" : "1.1.10", "extension" : "jar" }, { diff --git a/modules/tableviews/bnd.bnd b/modules/tableviews/bnd.bnd index 5fa86077..50f5a305 100644 --- a/modules/tableviews/bnd.bnd +++ b/modules/tableviews/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: tableviews Bundle-SymbolicName: nl.deltares.tableview.portlet -Bundle-Version: 1.1.9 +Bundle-Version: 1.1.10 Export-Package: nl.deltares.tableview.portlet.constants Import-Package: \ nl.deltares.tasks.*, \ diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java index 37eebd58..e8b33471 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/DownloadTablePortlet.java @@ -45,7 +45,7 @@ "javax.portlet.version=3.0", "com.liferay.portlet.display-category=OSS-table", "com.liferay.portlet.header-portlet-css=/css/main.css", - "com.liferay.portlet.header-portlet-javascript=/lib/downloadtableview.js", + "com.liferay.portlet.header-portlet-javascript=/lib/tableview.js", "com.liferay.portlet.header-portlet-javascript=/lib/common.js", "com.liferay.portlet.instanceable=true", "javax.portlet.display-name=DownloadTable", diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java index 022a8364..291d37d4 100644 --- a/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/portlet/portlet/RegistrationTablePortlet.java @@ -3,8 +3,6 @@ import com.liferay.journal.model.JournalArticle; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.json.JSONException; -import com.liferay.portal.kernel.json.JSONFactoryUtil; -import com.liferay.portal.kernel.json.JSONObject; import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet; import com.liferay.portal.kernel.service.UserLocalServiceUtil; @@ -18,14 +16,21 @@ import nl.deltares.dsd.registration.service.RegistrationLocalServiceUtil; import nl.deltares.portal.utils.DsdJournalArticleUtils; import nl.deltares.portal.utils.JsonContentUtils; -import nl.deltares.tableview.comparator.RegistrationComparator; import nl.deltares.tableview.model.DisplayRegistration; import nl.deltares.tableview.portlet.constants.TablePortletKeys; +import nl.deltares.tableview.tasks.impl.DeletedSelectedRegistrationsRequest; +import nl.deltares.tableview.tasks.impl.ExportSelectedRegistrationsTableRequest; +import nl.deltares.tableview.utils.RegistrationUtils; +import nl.deltares.tasks.DataRequest; +import nl.deltares.tasks.DataRequestManager; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import javax.portlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.PrintWriter; import java.util.*; /** @@ -37,6 +42,8 @@ "javax.portlet.version=3.0", "com.liferay.portlet.display-category=OSS-table", "com.liferay.portlet.header-portlet-css=/css/main.css", + "com.liferay.portlet.header-portlet-javascript=/lib/tableview.js", + "com.liferay.portlet.header-portlet-javascript=/lib/common.js", "com.liferay.portlet.instanceable=true", "javax.portlet.display-name=RegistrationTable", "javax.portlet.init-param.template-path=/", @@ -82,41 +89,6 @@ public void render(RenderRequest renderRequest, RenderResponse renderResponse) t super.render(renderRequest, renderResponse); } - private Map doLoadEventTitles(ThemeDisplay themeDisplay) { - - Map titles = new HashMap<>(); - - List resourceIds = RegistrationLocalServiceUtil.getDistinctEventResourceIds( - themeDisplay.getCompanyId(), themeDisplay.getSiteGroupId()); - doLoadResourceTitle(resourceIds, titles); - return titles; - } - - private Map doLoadRegistrationTitles(ThemeDisplay themeDisplay, Long selectedEventResourceId, Long selectedUserId) { - - if (selectedEventResourceId == null) {return Collections.emptyMap();} - - Map titles = new HashMap<>(); - List resourceIds = RegistrationLocalServiceUtil.getDistinctRegistrationResourceIds( - themeDisplay.getCompanyId(), themeDisplay.getSiteGroupId(), selectedEventResourceId, selectedUserId); - doLoadResourceTitle(resourceIds, titles); - return titles; - } - - private void doLoadResourceTitle(List resourcePrimaryKeys, Map titles) { - for (Long resourceId : resourcePrimaryKeys) { - if (titles.containsKey(resourceId)) {continue;} - try { - JournalArticle journalArticle = dsdJournalArticleUtils.getLatestArticle(resourceId); - if (journalArticle != null) titles.put(resourceId, journalArticle.getTitle()); - } catch (PortalException e) { - - //Article no longer exists; - titles.put(resourceId, String.valueOf(resourceId)); - } - } - } - private void doLoadRegistration(RenderRequest renderRequest) { final String recordId = ParamUtil.getString(renderRequest, "recordId", null); @@ -134,45 +106,27 @@ private void doLoadRegistration(RenderRequest renderRequest) { return; } - String eventName; - long eventResourceId; - final JournalArticle eventArticle = getArticleByResourcePrimaryKey(registration.getEventResourcePrimaryKey(), new HashMap<>()); - if (eventArticle != null) { - eventName = eventArticle.getTitle(); - eventResourceId = registration.getEventResourcePrimaryKey(); - } else { - eventName = ""; - eventResourceId = registration.getEventResourcePrimaryKey(); - } - String sessionName; - try { - final JournalArticle registrationArticle = dsdJournalArticleUtils.getLatestArticle(registration.getResourcePrimaryKey()); - sessionName = registrationArticle.getTitle(); - } catch (PortalException e) { - sessionName = String.valueOf(registration.getResourcePrimaryKey()); - } + long eventResourceId = registration.getEventResourcePrimaryKey(); + String eventName = RegistrationUtils.getArticleTitleByResourcePrimaryKey( + registration.getEventResourcePrimaryKey(), new HashMap<>(), dsdJournalArticleUtils, String.valueOf(eventResourceId)); + + String sessionName = RegistrationUtils.getArticleTitleByResourcePrimaryKey( + registration.getResourcePrimaryKey(), new HashMap<>(), dsdJournalArticleUtils, String.valueOf(registration.getResourcePrimaryKey())); + final String email = ParamUtil.getString(renderRequest, "editEmailValue", null); renderRequest.setAttribute("record", - new DisplayRegistration(id, registration.getResourcePrimaryKey(), eventResourceId, email, eventName, sessionName, formatJson(registration.getUserPreferences()), + new DisplayRegistration(id, registration.getResourcePrimaryKey(), eventResourceId, email, eventName, sessionName, + RegistrationUtils.formatJson(registration.getUserPreferences()), registration.getStartTime(), registration.getEndTime())); } - private String formatJson(String json) { - - try { - final JSONObject jsonObject = JSONFactoryUtil.createJSONObject(json); - return jsonObject.toString(4); - } catch (JSONException e) { - return json; - } - - } - private void doFilterValues(String filterEmailValue, long filterEventValue, long filterRegistrationValue, int curPage, int deltas, RenderRequest renderRequest) { ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest .getAttribute(WebKeys.THEME_DISPLAY); - Map eventTitles = doLoadEventTitles(themeDisplay); + Map articleCache = new HashMap<>(); + Map eventTitles = RegistrationUtils.doLoadEventTitles(themeDisplay.getCompanyId(), themeDisplay.getSiteGroupId(), + articleCache, dsdJournalArticleUtils); renderRequest.setAttribute("eventTitles", eventTitles); long userId = 0; @@ -181,9 +135,10 @@ private void doFilterValues(String filterEmailValue, long filterEventValue, long userId = user != null ? user.getUserId() : 0; } - Map registrationTitles = doLoadRegistrationTitles(themeDisplay, filterEventValue, userId); - renderRequest.setAttribute("registrationTitles", registrationTitles); + Map registrationTitles = RegistrationUtils.doLoadRegistrationTitles(themeDisplay.getCompanyId(), + themeDisplay.getSiteGroupId(), filterEventValue, userId, articleCache, dsdJournalArticleUtils); + renderRequest.setAttribute("registrationTitles", registrationTitles); final long siteGroupId = themeDisplay.getSiteGroupId(); List registrations; @@ -205,11 +160,12 @@ private void doFilterValues(String filterEmailValue, long filterEventValue, long registrations = Collections.emptyList(); recordCount = 0; } - List displays = convertToDisplayValues(registrations, eventTitles, registrationTitles); + List displays = RegistrationUtils.convertToDisplayValues(registrations, articleCache + , dsdJournalArticleUtils); String orderByCol = ParamUtil.getString(renderRequest, "orderByCol"); String orderByType = ParamUtil.getString(renderRequest, "orderByType"); - sortDownloads(displays, orderByCol, orderByType); + RegistrationUtils.sortDownloads(displays, orderByCol, orderByType); renderRequest.setAttribute("records", displays); renderRequest.setAttribute("total", recordCount); @@ -220,55 +176,90 @@ private void doFilterValues(String filterEmailValue, long filterEventValue, long } - private JournalArticle getArticleByResourcePrimaryKey(long resourceId, Map cache) { + @Override + public void serveResource(ResourceRequest request, ResourceResponse response) throws IOException, PortletException { - JournalArticle journalArticle = cache.get(resourceId); - if (journalArticle != null) return journalArticle; - try { - journalArticle = dsdJournalArticleUtils.getLatestArticle(resourceId); - if (journalArticle != null) cache.put(resourceId, journalArticle); - return journalArticle; - } catch (PortalException e) { - return null; + ThemeDisplay themeDisplay = (ThemeDisplay) request + .getAttribute(WebKeys.THEME_DISPLAY); + if (!themeDisplay.isSignedIn() || !request.isUserInRole("administrator")) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.getWriter().println("Unauthorized request!"); + return; } + String action = ParamUtil.getString(request, "action"); + String id = ParamUtil.getString(request, "id", null); + final String filterEmailValue = ParamUtil.getString(request, "filterEmailValue", ""); + final long filterEventValue = Long.parseLong(ParamUtil.getString(request, "filterEventValue", "0")); + final long filterRegistrationValue = Long.parseLong(ParamUtil.getString(request, "filterRegistrationValue", "0")); + + if ("export".equals(action)) { + if (id == null) { + id = RegistrationTablePortlet.class.getName() + themeDisplay.getUserId(); + } + exportTable(id, filterEmailValue, filterEventValue, filterRegistrationValue, response, themeDisplay); + } else if ("delete-selected".equals(action)) { + if (id == null) { + id = RegistrationTablePortlet.class.getName() + themeDisplay.getUserId(); + } + deletedSelected(id, request, response, themeDisplay); + + } else if ("updateStatus".equals(action)) { + DataRequestManager.getInstance().updateStatus(id, response); + } else if ("downloadLog".equals(action)) { + DataRequestManager.getInstance().downloadDataFile(id, response); + } else { + DataRequestManager.getInstance().writeError("Unsupported Action error: " + action, response); + } + super.serveResource(request, response); + } - private List convertToDisplayValues(List registrations, - Map eventTitles, Map registrationTitles) { + private void deletedSelected(String dataRequestId, ResourceRequest request, ResourceResponse response, ThemeDisplay themeDisplay) throws IOException { - final ArrayList displays = new ArrayList<>(registrations.size()); - Map articleCache = new HashMap<>(); - registrations.forEach(registration -> { - final long registrationPrimaryKey = registration.getResourcePrimaryKey(); - - String registrationTitle = registrationTitles.get(registrationPrimaryKey); - if (registrationTitle == null) { - JournalArticle registrationArticle = getArticleByResourcePrimaryKey(registrationPrimaryKey, articleCache); - if (registrationArticle != null) { - registrationTitle = registrationArticle.getTitle(); - registrationTitles.put(registrationPrimaryKey, registrationTitle); - } else { - registrationTitle = String.valueOf(registrationPrimaryKey); - } - } + final HttpServletRequest httpReq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(request)); + final String[] selectedIds = httpReq.getParameterValues("selection"); - final long eventResourcePrimaryKey = registration.getEventResourcePrimaryKey(); - String eventTitle = eventTitles.get(eventResourcePrimaryKey); - if (eventTitle == null) { - JournalArticle eventArticle = getArticleByResourcePrimaryKey(eventResourcePrimaryKey, articleCache); - if (eventArticle != null) { - eventTitle = eventArticle.getTitle(); - eventTitles.put(eventResourcePrimaryKey, eventTitle); - } else { - eventTitle = String.valueOf(eventResourcePrimaryKey); - } + if (selectedIds.length == 0) { + response.setContentType("text/plain"); + response.setStatus(HttpServletResponse.SC_NO_CONTENT); + } else { + response.setContentType("text/csv"); + DataRequestManager instance = DataRequestManager.getInstance(); + DataRequest dataRequest = instance.getDataRequest(dataRequestId); + if (dataRequest == null) { + dataRequest = new DeletedSelectedRegistrationsRequest(dataRequestId, Arrays.asList(selectedIds), themeDisplay.getUserId(), dsdJournalArticleUtils); + instance.addToQueue(dataRequest); + } else if (dataRequest.getStatus() == DataRequest.STATUS.TERMINATED || dataRequest.getStatus() == DataRequest.STATUS.NODATA) { + instance.removeDataRequest(dataRequest); } - final User user = UserLocalServiceUtil.fetchUser(registration.getUserId()); - final String email = user != null ? user.getEmailAddress() : String.valueOf(registration.getUserId()); - displays.add(new DisplayRegistration(registration.getRegistrationId(), registrationPrimaryKey, eventResourcePrimaryKey, - email, eventTitle, registrationTitle, null, registration.getStartTime(), registration.getEndTime())); - }); - return displays; + response.setStatus(HttpServletResponse.SC_OK); + String statusMessage = dataRequest.getStatusMessage(); + response.setContentLength(statusMessage.length()); + PrintWriter writer = response.getWriter(); + writer.println(statusMessage); + + } + } + + + private void exportTable(String dataRequestId, String filterEmailValue, long filterEventValue, long filterRegistrationValue, + ResourceResponse response, ThemeDisplay themeDisplay) throws IOException { + response.setContentType("text/csv"); + DataRequestManager instance = DataRequestManager.getInstance(); + DataRequest dataRequest = instance.getDataRequest(dataRequestId); + if (dataRequest == null) { + dataRequest = new ExportSelectedRegistrationsTableRequest(dataRequestId, filterEmailValue, filterEventValue, + filterRegistrationValue, themeDisplay, dsdJournalArticleUtils); + instance.addToQueue(dataRequest); + } else if (dataRequest.getStatus() == DataRequest.STATUS.TERMINATED || dataRequest.getStatus() == DataRequest.STATUS.NODATA) { + instance.removeDataRequest(dataRequest); + } + response.setStatus(HttpServletResponse.SC_OK); + String statusMessage = dataRequest.getStatusMessage(); + response.setContentLength(statusMessage.length()); + PrintWriter writer = response.getWriter(); + writer.println(statusMessage); + } /** @@ -282,7 +273,7 @@ public void filterEmail(ActionRequest actionRequest, ActionResponse actionRespon final String selectedEmail = ParamUtil.getString(actionRequest, "filterEmailValue", ""); - if ( !selectedEmail.isEmpty() ) { + if (!selectedEmail.isEmpty()) { RenderURL redirectURL = actionResponse.createRedirectURL(MimeResponse.Copy.ALL); redirectURL.getRenderParameters().setValue("filterEmailValue", selectedEmail); redirectURL.getRenderParameters().setValue("filterEventValue", "0"); @@ -308,7 +299,7 @@ public void filterSelections(ActionRequest actionRequest, ActionResponse actionR final String selectedEventValue = ParamUtil.getString(actionRequest, "filterEventValue", ""); final String selectedRegistrationValue = ParamUtil.getString(actionRequest, "filterRegistrationValue", ""); - if ( !selectedEventValue.isEmpty() ) { + if (!selectedEventValue.isEmpty()) { RenderURL redirectURL = actionResponse.createRedirectURL(MimeResponse.Copy.ALL); redirectURL.getRenderParameters().setValue("filterEmailValue", ""); redirectURL.getRenderParameters().setValue("filterEventValue", selectedEventValue); @@ -322,32 +313,6 @@ public void filterSelections(ActionRequest actionRequest, ActionResponse actionR } } - /** - * Delete selected registration - * - * @param actionRequest Delete action - * @param actionResponse Delete response - */ - @SuppressWarnings("unused") - public void delete(ActionRequest actionRequest, ActionResponse actionResponse) { - - final String recordId = ParamUtil.getString(actionRequest, "recordId", null); - try { - Registration registration = RegistrationLocalServiceUtil.deleteRegistration(Long.parseLong(recordId)); - SessionMessages.add(actionRequest, "action-success", String.format("Delete registration %s", recordId)); - } catch (Exception e) { - SessionErrors.add(actionRequest, "action-failed", String.format("Failed to delete registration: %s", e.getMessage())); - } - - final String selectedEmail = ParamUtil.getString(actionRequest, "filterEmailValue", null); - final String filterEventValue = ParamUtil.getString(actionRequest, "filterEventValue", null); - final String filterRegistrationValue = ParamUtil.getString(actionRequest, "filterRegistrationValue", null); - - actionResponse.getRenderParameters().setValue("filterEmailValue", selectedEmail); - actionResponse.getRenderParameters().setValue("filterRegistrationValue", selectedEmail); - actionResponse.getRenderParameters().setValue("filterEmailValue", selectedEmail); - } - /** * Pass the selected filter options to the render request * @@ -389,10 +354,5 @@ private void validate(String preferences) throws JSONException { } - private void sortDownloads(List displays, String orderByCol, String orderByType) { - final RegistrationComparator comparator = new RegistrationComparator(orderByCol, orderByType.equals("asc")); - displays.sort(comparator); - - } } \ No newline at end of file diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedRegistrationsRequest.java b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedRegistrationsRequest.java new file mode 100644 index 00000000..2562f811 --- /dev/null +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/DeletedSelectedRegistrationsRequest.java @@ -0,0 +1,114 @@ +package nl.deltares.tableview.tasks.impl; + +import com.liferay.journal.model.JournalArticle; +import com.liferay.portal.kernel.exception.PortalException; +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; +import com.liferay.portal.kernel.model.User; +import com.liferay.portal.kernel.service.UserLocalServiceUtil; +import nl.deltares.dsd.registration.model.Registration; +import nl.deltares.dsd.registration.service.RegistrationLocalServiceUtil; +import nl.deltares.portal.utils.DsdJournalArticleUtils; +import nl.deltares.tableview.utils.RegistrationUtils; +import nl.deltares.tasks.AbstractDataRequest; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import static nl.deltares.tasks.DataRequest.STATUS.*; + +public class DeletedSelectedRegistrationsRequest extends AbstractDataRequest { + + + private static final Log logger = LogFactoryUtil.getLog(DeletedSelectedRegistrationsRequest.class); + + private final List selectedRecords; + private final DsdJournalArticleUtils dsdJournalArticleUtils; + + public DeletedSelectedRegistrationsRequest(String id, List recordIds, long userId, DsdJournalArticleUtils dsdJournalArticleUtils) throws IOException { + super(id, userId); + this.selectedRecords = recordIds; + this.dsdJournalArticleUtils = dsdJournalArticleUtils; + } + + @Override + public STATUS call() { + if (getStatus() == AVAILABLE) return status; + status = RUNNING; + statusMessage = "start deleting..."; + init(); + try { + File tempFile = new File(getExportDir(), id + ".tmp"); + if (tempFile.exists()) Files.deleteIfExists(tempFile.toPath()); + + try (PrintWriter writer = new PrintWriter(new FileWriter(tempFile))) { + deleteSelectedRecords(writer); + if (status != TERMINATED) { + status = AVAILABLE; + } + } catch (Exception e) { + errorMessage = e.getMessage(); + logger.warn("Error serializing csv content: %s", e); + status = TERMINATED; + } + if (status == AVAILABLE) { + this.dataFile = new File(getExportDir(), id + ".csv"); + if (dataFile.exists()) Files.deleteIfExists(dataFile.toPath()); + Files.move(tempFile.toPath(), dataFile.toPath()); + } + + } catch (Exception e) { + errorMessage = e.getMessage(); + status = TERMINATED; + } + fireStateChanged(); + + return status; + } + + private void deleteSelectedRecords(PrintWriter writer) { + + writer.println("event,registration,email,start,end"); + + totalCount = selectedRecords.size(); + + HashMap cachedArticles = new HashMap<>(); + selectedRecords.forEach(id -> { + if (status == TERMINATED) return; + try { + final Registration registration = RegistrationLocalServiceUtil.deleteRegistration(Long.parseLong(id)); + final User user = UserLocalServiceUtil.fetchUser(registration.getUserId()); + String email; + if (user == null) { + email = String.valueOf(registration.getUserId()); + } else { + email = user.getEmailAddress(); + } + JournalArticle eventArticle = RegistrationUtils.getArticleByResourcePrimaryKey(registration.getEventResourcePrimaryKey(), cachedArticles, dsdJournalArticleUtils); + JournalArticle registrationArticle = RegistrationUtils.getArticleByResourcePrimaryKey(registration.getResourcePrimaryKey(), cachedArticles, dsdJournalArticleUtils); + + final Date startDate = registration.getStartTime(); + final Date endDate = registration.getEndTime(); + writer.println(String.format("%s,%s,%s,%s,%s", + eventArticle == null ? registration.getEventResourcePrimaryKey() : eventArticle.getTitle(), + registrationArticle == null ? registration.getResourcePrimaryKey() : registrationArticle.getTitle(), + email, startDate, endDate)); + } catch (PortalException e) { + writer.println(String.format("Failed to delete record %s: %s", id, e.getMessage())); + } finally { + incrementProcessCount(1); + } + if (Thread.interrupted()) { + status = TERMINATED; + errorMessage = String.format("Thread 'DeletedSelectedDownloadsRequest' with id %s is interrupted!", id); + } + }); + } + +} diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedRegistrationsTableRequest.java b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedRegistrationsTableRequest.java new file mode 100644 index 00000000..88103e42 --- /dev/null +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/tasks/impl/ExportSelectedRegistrationsTableRequest.java @@ -0,0 +1,163 @@ +package nl.deltares.tableview.tasks.impl; + +import com.liferay.journal.model.JournalArticle; +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; +import com.liferay.portal.kernel.model.Group; +import com.liferay.portal.kernel.model.User; +import com.liferay.portal.kernel.service.UserLocalServiceUtil; +import com.liferay.portal.kernel.theme.ThemeDisplay; +import com.liferay.portal.kernel.util.Validator; +import nl.deltares.dsd.registration.model.Registration; +import nl.deltares.dsd.registration.service.RegistrationLocalServiceUtil; +import nl.deltares.portal.utils.DsdJournalArticleUtils; +import nl.deltares.tableview.model.DisplayRegistration; +import nl.deltares.tableview.utils.RegistrationUtils; +import nl.deltares.tasks.AbstractDataRequest; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static nl.deltares.tasks.DataRequest.STATUS.*; + +public class ExportSelectedRegistrationsTableRequest extends AbstractDataRequest { + + private static final Log logger = LogFactoryUtil.getLog(ExportSelectedRegistrationsTableRequest.class); + + private final Group group; + private final boolean findByUser; + private final String filterEmail; + private final long filterEventId; + private final long filterRegistrationId; + + private final DsdJournalArticleUtils dsdJournalArticleUtils; + + public ExportSelectedRegistrationsTableRequest(String id, String filterEmailValue, long filterEventValue, + long filterRegistrationValue, ThemeDisplay themeDisplay, + DsdJournalArticleUtils dsdJournalArticleUtils) throws IOException { + super(id, themeDisplay.getUserId()); + this.group = themeDisplay.getSiteGroup(); + this.filterEmail = filterEmailValue; + this.filterEventId = filterEventValue; + this.filterRegistrationId = filterRegistrationValue; + this.findByUser = Validator.isEmailAddress(filterEmailValue); + this.dsdJournalArticleUtils = dsdJournalArticleUtils; + } + + @Override + public STATUS call() { + if (getStatus() == AVAILABLE) return status; + + if (!findByUser && filterEventId == 0 && filterRegistrationId == 0) { + status = NODATA; + return status; + } + statusMessage = "starting exporting registrations for filter"; + + status = RUNNING; + try { + File tempFile = new File(getExportDir(), id + ".tmp"); + if (tempFile.exists()) Files.deleteIfExists(tempFile.toPath()); + + try (PrintWriter writer = new PrintWriter(new FileWriter(tempFile))) { + exportSelectedRecords(writer); + if (status != TERMINATED) { + status = AVAILABLE; + } + } catch (Exception e) { + errorMessage = e.getMessage(); + logger.warn("Error serializing csv content: %s", e); + status = TERMINATED; + } + if (status == AVAILABLE) { + this.dataFile = new File(getExportDir(), id + ".csv"); + if (dataFile.exists()) Files.deleteIfExists(dataFile.toPath()); + Files.move(tempFile.toPath(), dataFile.toPath()); + } + + } catch (Exception e) { + errorMessage = e.getMessage(); + status = TERMINATED; + } finally { + if (status == RUNNING || status == PENDING) { + status = TERMINATED; + } + } + fireStateChanged(); + + return status; + } + + private void exportSelectedRecords(PrintWriter writer) { + + long companyId = group.getCompanyId(); + long groupId = group.getGroupId(); + + User filterUser = null; + Map articleCache = new HashMap<>(); + if (findByUser) { + filterUser = UserLocalServiceUtil.fetchUserByEmailAddress(companyId, filterEmail); + if (filterUser == null) { + totalCount = 0; + } else { + totalCount = RegistrationLocalServiceUtil.getUserRegistrationsCount(groupId, filterUser.getUserId()); + } + } else { + totalCount = RegistrationLocalServiceUtil.getEventRegistrationsCount(groupId, filterEventId); + } + + if (totalCount == 0) { + status = NODATA; + setProcessCount(0); + return; + } + + writer.println("event,registration,email,start,end"); + + int start = 0; + int end = 100; + + for (int i = 0; i < totalCount; ) { + if (status == TERMINATED) return; + final List registrations; + + if (filterUser != null) { + registrations = RegistrationLocalServiceUtil.getUserRegistrations(groupId, filterUser.getUserId(), start, end); + } else if (filterRegistrationId > 0) { + registrations = RegistrationLocalServiceUtil.getArticleRegistrations(groupId, filterRegistrationId, start, end); + } else if (filterEventId > 0) { + registrations = RegistrationLocalServiceUtil.getEventRegistrations(groupId, filterEventId, start, end); + } else { + registrations = Collections.emptyList(); + } + List displayRegistrations = RegistrationUtils.convertToDisplayValues(registrations, + articleCache, dsdJournalArticleUtils); + + displayRegistrations.forEach(registration -> { + if (status == TERMINATED) return; + incrementProcessCount(1); + + writer.println(String.format("%s,%s,%s,%s,%s", + registration.getEventName(), registration.getRegistrationName(), registration.getEmail(), + registration.getStartTime(), registration.getEndTime())); + + if (Thread.interrupted()) { + status = TERMINATED; + errorMessage = String.format("Thread 'ExportSelectedRegistrationsRequest' with id %s is interrupted!", id); + } + }); + i += registrations.size(); + start = end; + end += 100; + } + + } + +} diff --git a/modules/tableviews/src/main/java/nl/deltares/tableview/utils/RegistrationUtils.java b/modules/tableviews/src/main/java/nl/deltares/tableview/utils/RegistrationUtils.java new file mode 100644 index 00000000..4aeb196e --- /dev/null +++ b/modules/tableviews/src/main/java/nl/deltares/tableview/utils/RegistrationUtils.java @@ -0,0 +1,107 @@ +package nl.deltares.tableview.utils; + +import com.liferay.journal.model.JournalArticle; +import com.liferay.portal.kernel.exception.PortalException; +import com.liferay.portal.kernel.json.JSONException; +import com.liferay.portal.kernel.json.JSONFactoryUtil; +import com.liferay.portal.kernel.json.JSONObject; +import com.liferay.portal.kernel.model.User; +import com.liferay.portal.kernel.service.UserLocalServiceUtil; +import nl.deltares.dsd.registration.model.Registration; +import nl.deltares.dsd.registration.service.RegistrationLocalServiceUtil; +import nl.deltares.portal.utils.DsdJournalArticleUtils; +import nl.deltares.tableview.comparator.RegistrationComparator; +import nl.deltares.tableview.model.DisplayRegistration; + +import java.util.*; + +public class RegistrationUtils { + + public static List convertToDisplayValues(List registrations, Map articleCache, + DsdJournalArticleUtils dsdJournalArticleUtils) { + + final ArrayList displays = new ArrayList<>(registrations.size()); + registrations.forEach(registration -> { + final long registrationPrimaryKey = registration.getResourcePrimaryKey(); + + String registrationTitle = getArticleTitleByResourcePrimaryKey(registrationPrimaryKey, articleCache, dsdJournalArticleUtils, String.valueOf(registrationPrimaryKey)); + + final long eventResourcePrimaryKey = registration.getEventResourcePrimaryKey(); + String eventTitle = getArticleTitleByResourcePrimaryKey(eventResourcePrimaryKey, articleCache, dsdJournalArticleUtils, String.valueOf(eventResourcePrimaryKey)); + + final User user = UserLocalServiceUtil.fetchUser(registration.getUserId()); + final String email = user != null ? user.getEmailAddress() : String.valueOf(registration.getUserId()); + displays.add(new DisplayRegistration(registration.getRegistrationId(), registrationPrimaryKey, eventResourcePrimaryKey, + email, eventTitle, registrationTitle, null, registration.getStartTime(), registration.getEndTime())); + }); + return displays; + } + + public static String getArticleTitleByResourcePrimaryKey(long resourceId, Map cache, DsdJournalArticleUtils dsdJournalArticleUtils, String defaultValue) { + + JournalArticle article = getArticleByResourcePrimaryKey(resourceId, cache, dsdJournalArticleUtils); + if (article != null) {return article.getTitle();} + return defaultValue; + + } + public static JournalArticle getArticleByResourcePrimaryKey(long resourceId, Map cache, DsdJournalArticleUtils dsdJournalArticleUtils) { + + JournalArticle journalArticle = cache.get(resourceId); + if (journalArticle != null) return journalArticle; + try { + journalArticle = dsdJournalArticleUtils.getLatestArticle(resourceId); + if (journalArticle != null) cache.put(resourceId, journalArticle); + return journalArticle; + } catch (PortalException e) { + return null; + } + } + + public static Map doLoadEventTitles(long companyId, long siteGroupId, Map cache, DsdJournalArticleUtils dsdJournalArticleUtils) { + + Map titles = new HashMap<>(); + + List resourceIds = RegistrationLocalServiceUtil.getDistinctEventResourceIds( + companyId, siteGroupId); + for (Long resourceId : resourceIds) { + String title = getArticleTitleByResourcePrimaryKey(resourceId, cache, dsdJournalArticleUtils, String.valueOf(resourceId)); + if (title != null) titles.put(resourceId, title); + } + return titles; + } + + public static Map doLoadRegistrationTitles(long companyId, long groupId, long selectedEventResourceId, + long selectedUserId, Map cache, DsdJournalArticleUtils dsdJournalArticleUtils) { + + if (selectedEventResourceId == 0) { + return Collections.emptyMap(); + } + + Map titles = new HashMap<>(); + List resourceIds = RegistrationLocalServiceUtil.getDistinctRegistrationResourceIds( + companyId, groupId, selectedEventResourceId, selectedUserId); + for (Long resourceId : resourceIds) { + String title = getArticleTitleByResourcePrimaryKey(resourceId, cache, dsdJournalArticleUtils, String.valueOf(resourceId)); + if (title != null) titles.put(resourceId, title); + } + return titles; + } + + public static String formatJson(String json) { + + try { + final JSONObject jsonObject = JSONFactoryUtil.createJSONObject(json); + return jsonObject.toString(4); + } catch (JSONException e) { + return json; + } + + } + + public static void sortDownloads(List displays, String orderByCol, String orderByType) { + + final RegistrationComparator comparator = new RegistrationComparator(orderByCol, orderByType.equals("asc")); + displays.sort(comparator); + + } +} diff --git a/modules/tableviews/src/main/resources/META-INF/resources/lib/downloadtableview.js b/modules/tableviews/src/main/resources/META-INF/resources/lib/tableview.js similarity index 97% rename from modules/tableviews/src/main/resources/META-INF/resources/lib/downloadtableview.js rename to modules/tableviews/src/main/resources/META-INF/resources/lib/tableview.js index 540f4c22..a88b8d57 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/lib/downloadtableview.js +++ b/modules/tableviews/src/main/resources/META-INF/resources/lib/tableview.js @@ -14,7 +14,7 @@ var TableFormsUtil = { let selected = []; this.loadSelection(namespace, selected); if (selected.length === 0){ - alert("Please select one or more downloads before continuing."); + alert("Please select one or more records before continuing."); } else { this.callResourceUrl(resourceUrl, namespace, filename, "delete-selected", selected, renderUrl); } diff --git a/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp b/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp index 589d7cb8..35a7ce80 100644 --- a/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp +++ b/modules/tableviews/src/main/resources/META-INF/resources/registrationTable.jsp @@ -22,6 +22,7 @@ final Map registrationTitles = (Map) request.getAttribute("registrationTitles"); %> + @@ -120,6 +121,7 @@ @@ -149,13 +151,17 @@
    - +<%-- +<%-- href="<%=deleteRegistrationURL%>"/>--%> + + + +
    @@ -164,16 +170,20 @@
    - - - let deleteButtons = document.getElementsByClassName("deleteButton"); - Array.from(deleteButtons).forEach(function (button) { - button.addEventListener('click', function (event) { - if (confirm("You are about to delete this registration.\nDo you want to continue?") === false) { - event.preventDefault(); - } - }); - }); + + + + let exportResultsButton = document.getElementById('exportResultsButton'); + exportResultsButton.onclick = function(event){ + event.preventDefault(); + TableFormsUtil.exportResults("", "", "export-registrations.csv") + }; + + let deleteSelectedButton = document.getElementById('deleteSelectedButton'); + deleteSelectedButton.onclick = function(event){ + event.preventDefault(); + TableFormsUtil.deleteSelected("", "", "", "delete-selected-registrations.csv") + }; From f2905cc868aba9c26c0a05ef743c5c985a7631f0 Mon Sep 17 00:00:00 2001 From: rooij_e Date: Thu, 3 Sep 2026 09:15:03 +0200 Subject: [PATCH 12/13] MYDELTARES-484: Improve filtering of Registrations table --- configs/artifacts-release.json | 2 +- modules/tableviews/bnd.bnd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/artifacts-release.json b/configs/artifacts-release.json index 3a5c4e26..c68f8d7d 100644 --- a/configs/artifacts-release.json +++ b/configs/artifacts-release.json @@ -93,7 +93,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.tableview.portlet", - "version" : "1.1.10", + "version" : "1.1.11", "extension" : "jar" }, { diff --git a/modules/tableviews/bnd.bnd b/modules/tableviews/bnd.bnd index 50f5a305..e5b18ee6 100644 --- a/modules/tableviews/bnd.bnd +++ b/modules/tableviews/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: tableviews Bundle-SymbolicName: nl.deltares.tableview.portlet -Bundle-Version: 1.1.10 +Bundle-Version: 1.1.11 Export-Package: nl.deltares.tableview.portlet.constants Import-Package: \ nl.deltares.tasks.*, \ From a193a42309378b9d4b648195f1669172b3893a9d Mon Sep 17 00:00:00 2001 From: rooij_e Date: Thu, 3 Sep 2026 16:39:05 +0200 Subject: [PATCH 13/13] AccountEntry domains not being stored --- configs/artifacts-release.json | 2 +- modules/common-utils/bnd.bnd | 2 +- .../listeners/AccountEntryModelListener.java | 21 ------------------- 3 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/AccountEntryModelListener.java diff --git a/configs/artifacts-release.json b/configs/artifacts-release.json index c68f8d7d..c979b1b0 100644 --- a/configs/artifacts-release.json +++ b/configs/artifacts-release.json @@ -38,7 +38,7 @@ { "groupId" : "nl.deltares", "artifactId" : "nl.deltares.portal.common-utils", - "version" : "1.1.42", + "version" : "1.1.43", "extension" : "jar" }, { diff --git a/modules/common-utils/bnd.bnd b/modules/common-utils/bnd.bnd index 004c168f..0abe793f 100644 --- a/modules/common-utils/bnd.bnd +++ b/modules/common-utils/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: common-utils Bundle-SymbolicName: nl.deltares.portal.common-utils -Bundle-Version: 1.1.42 +Bundle-Version: 1.1.43 Export-Package: \ nl.deltares.portal.constants, \ nl.deltares.portal.utils, \ diff --git a/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/AccountEntryModelListener.java b/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/AccountEntryModelListener.java deleted file mode 100644 index fead96c8..00000000 --- a/modules/common-utils/src/main/java/nl/deltares/portal/model/listeners/AccountEntryModelListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package nl.deltares.portal.model.listeners; - -import com.liferay.account.model.AccountEntry; -import com.liferay.portal.kernel.exception.ModelListenerException; -import com.liferay.portal.kernel.model.BaseModelListener; -import com.liferay.portal.kernel.model.ModelListener; -import org.osgi.service.component.annotations.Component; - -@Component(service = ModelListener.class) -public class AccountEntryModelListener extends BaseModelListener { - - @Override - public void onBeforeUpdate(AccountEntry originalModel, AccountEntry model) throws ModelListenerException { - - String domains = originalModel.getDomains(); - model.setDomains(domains); - - super.onBeforeUpdate(originalModel, model); - } - -}