From f7f58ef3460ee23d66e2c1141cc71d0a985454ad Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 15 Apr 2023 14:17:39 +0000 Subject: [PATCH 01/47] fix: upgrade com.googlecode.libphonenumber:libphonenumber from 8.13.7 to 8.13.8 Snyk has created this PR to upgrade com.googlecode.libphonenumber:libphonenumber from 8.13.7 to 8.13.8. See this package in Maven Repository: https://mvnrepository.com/artifact/com.googlecode.libphonenumber/libphonenumber/ See this project in Snyk: https://app.snyk.io/org/wwelling/project/17513fa9-8774-4132-a350-41513b4941c1?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 9b82275bd2..bceeff28e1 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ com.googlecode.libphonenumber libphonenumber - 8.13.7 + 8.13.8 @@ -641,7 +641,7 @@ - + @@ -675,7 +675,7 @@ - + From 99825fd4c54f6bdd578a3f0d0a30b00789de2439 Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Mon, 24 Apr 2023 10:45:01 -0500 Subject: [PATCH 02/47] update version --- README.md | 10 +++++----- build/appConfig.js.template | 2 +- package.json | 2 +- pom.xml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 90497e80d7..1bde1045d6 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ $ mvn clean spring-boot:run -Dproduction $ mvn clean package -DskipTests -Dproduction -Dassets.uri=file:/opt/vireo/ -Dconfig.uri=file:/opt/vireo/config/ ``` -If build succeeds, you should have both a `vireo-4.1.5.war` and a `vireo-4.1.5-install.zip` in the `target/` directory. When building for production required static assets are copied into the packaged war file and the index.html template is optimized for production. For development a symlink is used to allow the application to access required static assets. +If build succeeds, you should have both a `vireo-4.2.0.war` and a `vireo-4.2.0-install.zip` in the `target/` directory. When building for production required static assets are copied into the packaged war file and the index.html template is optimized for production. For development a symlink is used to allow the application to access required static assets. #### Apache Reverse Proxy Config @@ -117,7 +117,7 @@ Unzip package into preferred directory (or any directory you choose): ```bash $ cd /opt/vireo -$ unzip vireo-4.1.5-install.zip +$ unzip vireo-4.2.0-install.zip ``` ### Directory Structure of installed package @@ -190,13 +190,13 @@ ln -s /opt/vireo/webapp /opt/tomcat/webapps/ROOT Copy war file into Tomcat webapps directory (your location may vary -- this is an example): ```bash -$ cp ~/vireo-4.1.5.war /usr/local/tomcat/webapps/vireo.war +$ cp ~/vireo-4.2.0.war /usr/local/tomcat/webapps/vireo.war ``` or as root: ```bash -$ cp ~/vireo-4.1.5.war /usr/local/tomcat/webapps/ROOT.war +$ cp ~/vireo-4.2.0.war /usr/local/tomcat/webapps/ROOT.war ``` **if not specifying assets.uri during build the assets will be stored under the vireo webapp's classpath, /opt/tomcat/webapps/vireo/WEB-INF/classes** @@ -209,7 +209,7 @@ $ cp ~/vireo-4.1.5.war /usr/local/tomcat/webapps/ROOT.war ## Running WAR as a stand-alone Spring Boot application ```bash -java -jar target/vireo-4.1.5.war +java -jar target/vireo-4.2.0.war ```
(back to top)
diff --git a/build/appConfig.js.template b/build/appConfig.js.template index 4ac6aaf4d1..85f2f54c5d 100644 --- a/build/appConfig.js.template +++ b/build/appConfig.js.template @@ -1,6 +1,6 @@ var appConfig = { - 'version': '4.1.5', + 'version': '4.2.0', 'allowAnonymous': true, 'anonymousRole': 'ROLE_ANONYMOUS', diff --git a/package.json b/package.json index 447b647e19..ad10584b33 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vireo", "private": false, - "version": "4.1.5", + "version": "4.2.0", "description": "Vireo 4", "homepage": "https://github.com/TexasDigitalLibrary/Vireo", "repository": { diff --git a/pom.xml b/pom.xml index cc0baab33f..dd8b64b59d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.tdl vireo - 4.1.5 + 4.2.0 Vireo Vireo Thesis and Dissertation Submission System From f76100e70960c5f327fe775ba676390d83018d98 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 24 Apr 2023 12:12:54 -0500 Subject: [PATCH 03/47] Issue 1709: Add type checks to prevent errors when handling invalid dates. The Javascript date function is very sensitive to values. The regex match function does not always return an array. While it would be preferred that a Javascript regex match returns an empty array it does not. Handle the error case for when the regex match fails (such as on an empty string). This fixes the display problem on the admin list view. The `date()` function may return the string 'invalid date' or something similar. This then causes the `date.toISOString()` to fail. Oddly enough, the `isNaN()` will succeed for when `date()` is a valid response (which is an Object). Using the `isNaN()` check fixes the display problem with using the submission view confirmation page (step 5 of the submission view for "Confirm & Submit"). Re-organize and add a NULL check to `$scope.displaySubmissionProperty()` just in case. Clean up some white space in related areas of code. --- .../submission/submissionListController.js | 6 ++++-- .../webapp/app/filters/displayFieldValue.js | 21 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index cf1c8edf19..cfe8455779 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -599,9 +599,11 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }; $scope.displaySubmissionProperty = function (row, col) { - var value = $scope.getSubmissionProperty(row, col); + if (angular.isDefined(col) && col !== null) { + return $filter('displayFieldValue')($scope.getSubmissionProperty(row, col), col.inputType); + } - return angular.isDefined(col) ? $filter('displayFieldValue')(value, col.inputType) : value; + return value; }; $scope.getCustomActionLabelById = function (id) { diff --git a/src/main/webapp/app/filters/displayFieldValue.js b/src/main/webapp/app/filters/displayFieldValue.js index 3d1ab79f1f..3ee5b0c78a 100644 --- a/src/main/webapp/app/filters/displayFieldValue.js +++ b/src/main/webapp/app/filters/displayFieldValue.js @@ -1,7 +1,7 @@ vireo.filter('displayFieldValue', function($filter, InputTypes) { return function(value, inputType) { if (angular.isUndefined(inputType)) { - return value; + return value; } var dateColumn = null; @@ -15,7 +15,7 @@ vireo.filter('displayFieldValue', function($filter, InputTypes) { if (type != null) { if (inputType.name == InputTypes.INPUT_LICENSE || inputType.name == InputTypes.INPUT_PROQUEST) { - return value == 'true' ? 'yes' : 'no'; + return value == 'true' ? 'yes' : 'no'; } if (angular.isDefined(appConfig.dateColumns) && angular.isDefined(inputType.name)) { @@ -35,17 +35,28 @@ vireo.filter('displayFieldValue', function($filter, InputTypes) { } } - if (dateColumn == null || angular.isUndefined(value) || value == null) { - return value; + if (dateColumn === null || angular.isUndefined(value) || value === null) { + return value; } // Some browsers, like Firefox, do not support 'MMMM yyyy' formats for Date.parse(). var stamp = Date.parse(value); if (isNaN(stamp) && dateColumn.format == 'MMMM yyyy') { var split = value.match(/^(\S+) (\d+)$/); + + if (split === null || split.length < 3) { + return value; + } + return $filter('date')(new Date(split[1] + ' 01, ' + split[2]).toISOString(), dateColumn.format, 'utc'); } - return $filter('date')(new Date(value).toISOString(), dateColumn.format, 'utc'); + var date = new Date(value); + + if (isNaN(date)) { + return value; + } + + return $filter('date')(date.toISOString(), dateColumn.format, 'utc'); }; }); From d5295b340e4609d64dddf37d18e3788c7999f800 Mon Sep 17 00:00:00 2001 From: William Welling Date: Mon, 24 Apr 2023 13:06:57 -0500 Subject: [PATCH 04/47] Make field profile input info addon tab accessible (#1718) --- .../webapp/app/directives/tooltipDirective.js | 4 ++-- src/main/webapp/app/views/directives/tooltip.html | 15 ++++++++++++++- .../app/views/inputtype/input-textarea.html | 3 +-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/webapp/app/directives/tooltipDirective.js b/src/main/webapp/app/directives/tooltipDirective.js index 75ff191ca3..61a656fccc 100644 --- a/src/main/webapp/app/directives/tooltipDirective.js +++ b/src/main/webapp/app/directives/tooltipDirective.js @@ -23,7 +23,7 @@ vireo.directive('tooltip', function ($timeout) { }, 250); }; - $scope.mouseEnter = function() { + $scope.showTooltip = function() { open(); $timeout(function() { angular.element('.popover').hover(function() { @@ -34,7 +34,7 @@ vireo.directive('tooltip', function ($timeout) { }); }; - $scope.mouseLeave = function() { + $scope.hideTooltip = function() { close(); }; diff --git a/src/main/webapp/app/views/directives/tooltip.html b/src/main/webapp/app/views/directives/tooltip.html index 42d622161f..0c9894655c 100644 --- a/src/main/webapp/app/views/directives/tooltip.html +++ b/src/main/webapp/app/views/directives/tooltip.html @@ -1 +1,14 @@ - + diff --git a/src/main/webapp/app/views/inputtype/input-textarea.html b/src/main/webapp/app/views/inputtype/input-textarea.html index 30e1465786..09480e84a8 100644 --- a/src/main/webapp/app/views/inputtype/input-textarea.html +++ b/src/main/webapp/app/views/inputtype/input-textarea.html @@ -4,8 +4,7 @@ ng-required="!profile.optional" ng-model="fieldValue.value" ng-blur="save(fieldValue)" - ng-disabled="fieldValue.updating" - + ng-disabled="fieldValue.updating"> From 2ffe32f52c96c2f6a87adfeae9dd4ab7b80441f3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Mon, 24 Apr 2023 13:09:48 -0500 Subject: [PATCH 05/47] Return error when submission not editable by reviewer (#1720) --- .../java/org/tdl/vireo/controller/SubmissionController.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionController.java b/src/main/java/org/tdl/vireo/controller/SubmissionController.java index eade201171..3006f822bb 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionController.java @@ -213,7 +213,11 @@ public ApiResponse getActionLogs(@WeaverUser User user, @PathVariable Long submi @JsonView(Views.SubmissionIndividual.class) @RequestMapping("/advisor-review/{advisorAccessHash}") public ApiResponse getOne(@PathVariable String advisorAccessHash) { - return new ApiResponse(SUCCESS, submissionRepo.findOneByAdvisorAccessHash(advisorAccessHash)); + Submission submission = submissionRepo.findOneByAdvisorAccessHash(advisorAccessHash); + + return submission.getSubmissionStatus().isEditableByReviewer() + ? new ApiResponse(SUCCESS, submission) + : new ApiResponse(ERROR, "Submission is not editable by reviewer"); } @GetMapping("/advisor-review/{advisorAccessHash}/action-logs") From effd5c77acd6f45af64a336683a60d7a555f53b8 Mon Sep 17 00:00:00 2001 From: William Welling Date: Mon, 24 Apr 2023 13:14:44 -0500 Subject: [PATCH 06/47] Issues 1660,1661, and 1692: Modal accessibility fixes (#1719) * Ensure refresh function exists on model * Temp branch version of @wvr/core The next patch version of @wvr/core will resolve #1160, #1661, and #1692 * Use latest @wvr/core patched release candidate * Minor cleanup --- package.json | 2 +- src/main/webapp/app/directives/validatedInputDirective.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ad10584b33..577c5d675f 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "build": "wvr build --clean" }, "dependencies": { - "@wvr/core": "2.2.4", + "@wvr/core": "2.2.5-rc.2", "angular-ui-tinymce": "0.0.19", "file-saver": "2.0.5", "ng-csv": "0.3.6", diff --git a/src/main/webapp/app/directives/validatedInputDirective.js b/src/main/webapp/app/directives/validatedInputDirective.js index d229990094..f5e5c3f2c5 100644 --- a/src/main/webapp/app/directives/validatedInputDirective.js +++ b/src/main/webapp/app/directives/validatedInputDirective.js @@ -73,9 +73,9 @@ vireo.directive("validatedinput", function ($q, $timeout) { } // escape(27): reset value using shadow else if ($event.which == 27) { - $scope.model.refresh(); - } else { - + if ($scope.model && typeof $scope.model.refresh === 'function') { + $scope.model.refresh(); + } } }; From 9d22cfa58e14e8a76285ab866844d8a3bb5bea99 Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Fri, 14 Apr 2023 10:30:42 -0500 Subject: [PATCH 07/47] set proper contrast throughout application --- .../config/constant/ConfigurationName.java | 21 ++ .../service/VireoThemeManagerService.java | 2 +- .../resources/settings/SYSTEM_Defaults.json | 25 +- .../webapp/app/resources/styles/sass/app.scss | 59 ++-- .../styles/sass/directives/_tooltip.scss | 1 + .../styles/sass/overrides/_bootstrap.scss | 8 +- .../views/submission/_submissionDialog.scss | 2 +- .../settings/application/lookAndFeel.html | 285 +++++++++++++++--- 8 files changed, 334 insertions(+), 69 deletions(-) diff --git a/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java b/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java index a7cd0535f1..8e384a014c 100644 --- a/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java +++ b/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java @@ -49,6 +49,9 @@ public class ConfigurationName { // Theme settings /** Background main color */ public final static String THEME_PATH = "theme_path"; + + /** Text main color */ + public final static String TEXT_MAIN_COLOR = "text_main_color"; /** Background main color */ public final static String BACKGROUND_MAIN_COLOR = "background_main_color"; @@ -56,18 +59,36 @@ public class ConfigurationName { /** Background highlight color */ public final static String BACKGROUND_HIGHLIGHT_COLOR = "background_highlight_color"; + /** Background text color */ + public final static String BACKGROUND_TEXT_COLOR = "background_text_color"; + /** Submission Step Button main color when in "on" state */ public final static String BUTTON_MAIN_COLOR_ON = "button_main_color_on"; /** Submission Step Button highlight color when in "on" state */ public final static String BUTTON_HIGHLIGHT_COLOR_ON = "button_highlight_color_on"; + /** Submission Step Button text color when in "on" state */ + public final static String BUTTON_TEXT_COLOR_ON = "button_text_color_on"; + /** Submission Step Button main color when in "off" state */ public final static String BUTTON_MAIN_COLOR_OFF = "button_main_color_off"; /** Submission Step Button highlight color when in "off" state */ public final static String BUTTON_HIGHLIGHT_COLOR_OFF = "button_highlight_color_off"; + /** Submission Step Button text color when in "off" state */ + public final static String BUTTON_TEXT_COLOR_OFF = "button_text_color_off"; + + /** Admin main navigation tab background color */ + public final static String ADMIN_TAB_MAIN_COLOR = "admin_tab_main_color"; + + /** Admin selected navigation tab background color */ + public final static String ADMIN_TAB_SELECTED_COLOR = "admin_tab_selected_color"; + + /** Admin navigation tab text color*/ + public final static String ADMIN_TAB_TEXT_COLOR = "admin_tab_text_color"; + /** Custom CSS */ public final static String LEFT_LOGO = "left_logo"; diff --git a/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java b/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java index 9e4ce62afb..8fda3eaaba 100644 --- a/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java +++ b/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java @@ -24,7 +24,7 @@ public class VireoThemeManagerService extends SimpleThemeManagerService implemen @Override public Map getThemeProperties() { - String[] themePropertyNames = { "background_main_color", "background_highlight_color", "button_main_color_on", "button_highlight_color_on", "button_main_color_off", "button_highlight_color_off" }; + String[] themePropertyNames = {"text_main_color", "background_main_color", "background_highlight_color", "background_text_color", "button_main_color_on", "button_highlight_color_on", "button_text_color_on", "button_main_color_off", "button_highlight_color_off", "button_text_color_off", "admin_tab_main_color", "admin_tab_selected_color", "admin_tab_text_color"}; List themePropertyNamesList = Arrays.asList(themePropertyNames); List themeConfigurations = configurationRepo.getAllByType("lookAndFeel"); HashMap themeProperties = new HashMap(); diff --git a/src/main/resources/settings/SYSTEM_Defaults.json b/src/main/resources/settings/SYSTEM_Defaults.json index f99f3754d3..e13778ad1d 100644 --- a/src/main/resources/settings/SYSTEM_Defaults.json +++ b/src/main/resources/settings/SYSTEM_Defaults.json @@ -85,12 +85,18 @@ { "theme_path":"configuration/theme/" }, + { + "text_main_color":"#757575" + }, { "background_main_color":"#1b333f" }, { "background_highlight_color":"#43606e" }, + { + "background_text_color":"#ffffff" + }, { "button_main_color_on":"#1b333f" }, @@ -98,10 +104,25 @@ "button_highlight_color_on":"#43606e" }, { - "button_main_color_off":"#92aa9c" + "button_text_color_on":"#ffffff" + }, + { + "button_main_color_off":"#424D46" + }, + { + "button_highlight_color_off":"#697A70" + }, + { + "button_text_color_off":"#ffffff" + }, + { + "admin_tab_main_color":"#adbdaa" + }, + { + "admin_tab_selected_color":"#ffffff" }, { - "button_highlight_color_off":"#adbdaa" + "admin_tab_text_color":"#1D3541" }, { "left_logo":"resources/images/default-left-logo.png" diff --git a/src/main/webapp/app/resources/styles/sass/app.scss b/src/main/webapp/app/resources/styles/sass/app.scss index ffca4bb104..0eabe76af3 100644 --- a/src/main/webapp/app/resources/styles/sass/app.scss +++ b/src/main/webapp/app/resources/styles/sass/app.scss @@ -12,7 +12,7 @@ html { body { font-family: "Trebuchet MS", Verdana, Geneva, Arial, Helvetica, Sans-Serif; - color: #70706f; + color: $text_main_color; margin-right: 0 !important; padding-right: 0 !important; height: 100%; @@ -76,19 +76,18 @@ main footer { } .tab-nav li { - background: $button_highlight_color_off; + background: $admin_tab_main_color; padding: 0 10px; margin-right: 15px; min-width: 75px; text-align: center; - color: #1D3541; + color: $admin_tab_text_color; font-size: 1.75em; font-weight: bolder; display: inline-block; border-top-left-radius: 10px; border-top-right-radius: 10px; box-shadow: inset 0 -5px 7px -5px rgba(0, 0, 0, 0.75); - text-shadow: 0 0 10px rgba(255, 255, 245, 1), -1px -1px 0 rgba(250, 250, 235, 0.25), 1px 1px 0 rgba(250, 250, 235, 0.5); } .tab-nav li.settings-tab { @@ -101,8 +100,7 @@ main footer { .tab-nav li.active, .tab-nav li:hover { cursor: pointer; - background: #FFFFFF; - text-shadow: 0 0 0 #FFFFFF; + background: $admin_tab_selected_color; box-shadow: inset 0 0 0 #FFFFFF; } @@ -113,8 +111,7 @@ main footer { .tab-nav li a { height: 45px; color: inherit; - border-top-left-radius: 10px; - border-top-right-radius: 10px; + background-color:transparent !important; } .tab-nav li.settings-tab a { @@ -586,7 +583,7 @@ togglebutton { } .toggle-button .btn.active { - background-color: #a2ccb5; + background-color: #697A70; color: #FFFFFF; border: 1px solid #70706f; outline: none; @@ -684,26 +681,26 @@ h4 { padding-top: 35px; width: 250px; height: 150px; - color: #a6a6a6; + color: #696969; border-radius: 5px; transition: all 0.35s ease-in; } .trash-drop-zone.dragging { transition: all 0.35s ease-in; - border-color: #a6a6a6; + border-color: #696969; } .trash-drop-zone .glyphicon-trash { transition: all 0.35s ease-in; color: #fefefe; - text-shadow: 1px 0 5px #a6a6a6; + text-shadow: 1px 0 5px #696969; font-size: 70px; } .trash-drop-zone.dragging .glyphicon-trash { transition: all 0.35s ease-in; - color: #a6a6a6; + color: #696969; text-shadow: 1px 0 5px #fefefe; font-size: 70px; } @@ -715,20 +712,20 @@ h4 { padding-top: 35px; max-width: 250px; height: 150px; - color: #a6a6a6; + color: #696969; border-radius: 5px; transition: all 0.35s ease-in; } .upload-drop-zone.dragging-accept { transition: all 0.35s ease-in; - border-color: #a6a6a6; + border-color: #696969; } .upload-drop-zone .glyphicon-upload { transition: all 0.35s ease-in; color: #fefefe; - text-shadow: 1px 0 5px #a6a6a6; + text-shadow: 1px 0 5px #696969; font-size: 70px; } @@ -739,7 +736,7 @@ h4 { .upload-drop-zone.dragging .glyphicon-upload, .upload-drop-zone.reject .glyphicon-ban-circle { transition: all 0.35s ease-in; - color: #a6a6a6; + color: #696969; text-shadow: 1px 0 5px #fefefe; font-size: 70px; } @@ -956,6 +953,22 @@ input[type=color]:focus { /************************** * LOOK AND FEEL ACCORDION * ***************************/ +.look-and-feel-h1 { + font-size: 18px; + font-style: bold; + margin-bottom: .2em; +} + +.look-and-feel-h2 { + font-size: 14px; + margin-bottom: 1.5em; +} + +.look-and-feel-h1 .glyphicon.glyphicon-info-sign { + vertical-align: text-top; + font-size: 12px; +} + .look-and-feel .color-reset { text-indent: 0; font-size: 0.85em; @@ -972,11 +985,12 @@ input[type=color]:focus { } .look-and-feel .color-input { - height: 37px; + height: 42px; + min-width: 78px; } .look-and-feel .color-selector { - max-width: 200px; + max-width: 100px; } .look-and-feel label.color-selector-swatch { @@ -1194,17 +1208,17 @@ input[type=color]:focus { .triptych-panel .list-group-item:hover { cursor: pointer; - color: #70706f; + color: $text_main_color; background: #efefef; } .triptych-panel.previously-active .list-group-item.selected { - color: #70706f; + color: $text_main_color; background: #E6ECE8; } .triptych-panel .list-group-item.selected { - color: #fff; + color: $text_main_color; background: #92AA9C; } @@ -1423,6 +1437,7 @@ input[type=color]:focus { * NOTES * *********/ .note { + color: #474747; position: relative; max-width: 225px; padding: 15px 15px 35px 35px; diff --git a/src/main/webapp/app/resources/styles/sass/directives/_tooltip.scss b/src/main/webapp/app/resources/styles/sass/directives/_tooltip.scss index ed3ccf8c7a..b0c26e3b08 100644 --- a/src/main/webapp/app/resources/styles/sass/directives/_tooltip.scss +++ b/src/main/webapp/app/resources/styles/sass/directives/_tooltip.scss @@ -37,6 +37,7 @@ background: -webkit-linear-gradient(to bottom, rgba(31, 58, 71, 0.95), rgba(80, 114, 129, 0.95)); background: -ms-linear-gradient(to bottom, rgba(31, 58, 71, 0.95), rgba(80, 114, 129, 0.95)); background: linear-gradient(to bottom, rgba(31, 58, 71, 0.95), rgba(80, 114, 129, 0.95)); + opacity: 1 !important; } .tooltip .popover-content a, diff --git a/src/main/webapp/app/resources/styles/sass/overrides/_bootstrap.scss b/src/main/webapp/app/resources/styles/sass/overrides/_bootstrap.scss index cfa3fafc74..3b79d26f6d 100644 --- a/src/main/webapp/app/resources/styles/sass/overrides/_bootstrap.scss +++ b/src/main/webapp/app/resources/styles/sass/overrides/_bootstrap.scss @@ -6,10 +6,10 @@ // $gray-light: lighten($gray-base, 46.7%) !default; // #777 // $gray-lighter: lighten($gray-base, 93.5%) !default; // #eee -$brand-primary: darken(#428bca, 6.5%) !default; // #337ab7 +$brand-primary: darken(#367DC4, 6.5%) !default; // #337ab7 // $brand-success: #5cb85c !default; -// $brand-info: #5bc0de !default; +$brand-info: #357AB9 !default; // $brand-warning: #f0ad4e !default; -$brand-danger: #CD7674 !default; +$brand-danger: #C15453 !default; -$icon-font-path: "../fonts/bootstrap/" !default; +$icon-font-path: "../fonts/bootstrap/" !default; \ No newline at end of file diff --git a/src/main/webapp/app/resources/styles/sass/views/submission/_submissionDialog.scss b/src/main/webapp/app/resources/styles/sass/views/submission/_submissionDialog.scss index 50236b8309..24589b3d8b 100644 --- a/src/main/webapp/app/resources/styles/sass/views/submission/_submissionDialog.scss +++ b/src/main/webapp/app/resources/styles/sass/views/submission/_submissionDialog.scss @@ -18,7 +18,7 @@ submissiondialog div.dialog { } @media (min-width: 1540px) { submissiondialog div.dialog { - box-shadow: 3px 3px 10px -6px #000000; + box-shadow: 3px 3px 10px -6px #757575; } } diff --git a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html index 3fcc883e57..201ca5bf99 100644 --- a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html +++ b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html @@ -3,15 +3,51 @@
-
-

Background -
- -
-

+
+
Text + +
-
+
+
+
+ Main Color + + + +
+ +
+ # + + + + + +
+
+
+ +
+
Header/Footer Background + +
+
+ +
Main Color @@ -44,7 +80,6 @@

Background

-
Highlight Color @@ -55,7 +90,6 @@

Background

-
# Background ng-change="updateHexValue('lookAndFeel','background_highlight_color')"/> -
+
+ +
+
+ Text Color + + + +
+ +
+ # + + + + +
-
- -
-

Submission Step Button (On) -
- -
-

+
+
Submission Step Button (On) + +
-
+
Main Color @@ -102,7 +160,6 @@

Submission Step Button (On)

-
# Submission Step Button (On) ng-change="updateHexValue('lookAndFeel','button_main_color_on')"/> -
-
-
Highlight Color @@ -156,25 +210,50 @@

Submission Step Button (On) ng-change="updateHexValue('lookAndFeel','button_highlight_color_on')"/> +

+
+
+
+ Text Color + + + +
+ +
+ # + + + + +
-
- -
-

Submission Step Button (Off) -
- -
-

+
+
Submission Step Button (Off) + +
-
+
Main Color @@ -240,18 +319,148 @@

Submission Step Button (Off) ng-change="updateHexValue('lookAndFeel','button_highlight_color_off')"/> +

+
+
+
+ Text Color + + + +
+ +
+ # + + + + + +
+
+
+
+ +
+
Admin Navigation Tab + +
+
+ +
+
+
+ Main Color + + + +
+ +
+ # + + + + + + +
+ +
+ +
+
+ Selected Color + + +
+ +
+ # + + + + + +
+
+
+ Text Color + + + +
+ +
+ # + + + + +
+
-
-
@@ -259,11 +468,9 @@

Submission Step Button (Off)
-

Logos -
- -
-

+
Logos + +
From 8d7356fd3b5a4b2e1e7455617683d198cd8eace3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Mon, 24 Apr 2023 17:02:15 -0500 Subject: [PATCH 08/47] Open date picker on enter (#1725) Minor formatting cleanup --- .../app/views/inputtype/input-date.html | 7 ++-- .../app/views/inputtype/input-degreedate.html | 41 ++++++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/main/webapp/app/views/inputtype/input-date.html b/src/main/webapp/app/views/inputtype/input-date.html index cdc57d8ba8..8d0775c7f4 100644 --- a/src/main/webapp/app/views/inputtype/input-date.html +++ b/src/main/webapp/app/views/inputtype/input-date.html @@ -1,6 +1,6 @@
- - + + -
\ No newline at end of file +
diff --git a/src/main/webapp/app/views/inputtype/input-degreedate.html b/src/main/webapp/app/views/inputtype/input-degreedate.html index 8a4ec77477..842086b664 100644 --- a/src/main/webapp/app/views/inputtype/input-degreedate.html +++ b/src/main/webapp/app/views/inputtype/input-degreedate.html @@ -1,23 +1,24 @@
- - - - - - -
\ No newline at end of file + + + + + + +
From ce3905ba3ecaabb3c1c1d3ed2c958b189fec9802 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 25 Apr 2023 08:54:22 -0500 Subject: [PATCH 09/47] Issue 1582: Reset list view pagination and fix exposed pagination related problems. Change the behavior to reset the pagination when a filter is applied. This prevents the bug where the list is empty and the table is unusable when a filter is applied. Making this change exposed several related problems and bugs that have been deemed necessary to be fixed as part of this issue. A new `resetPagination()` function is created that performs the reset task. This required replacing duplicated code that also performs the pagination. This change exposed a bug where the `update()` function is always calling the database list view load even when unnecessary. This additional list load request in `update()` ends up altering the pagination and must be fixed to get this new behavior to work consistently. Preventing it from reloading the list when not needed also improves performance by removing an extra unnecessary request in certain places. Break apart the `update()` function, adding an additional function `processUpdate()`. This function performs the tasks needed. Breaking this up is required because there is an additional request to `ManagerSubmissionListColumnRepo.submissionListPageSize()` that alters the page size. The `ManagerSubmissionListColumnRepo.submissionListPageSize()` effectively reset the selected page count, causing a regression. The new behavior is to only call `ManagerSubmissionListColumnRepo.submissionListPageSize()` when there is no local session data. This design change maintains pre-existing behavior with the page count. This is another likely performance improvement where the page count is no longer fetched when not necessary. Despite the improvements, I still found a case where the page list is empty and the table is broken. An example would be data changes since pagination is set. It turns out that all of the data needed to determine if the selected pagination is correct is returned on the list response. The problem is that the list response is already loaded so even if the pagination data were to be corrected there is no row data to display. This is solved by making an extra request with the pagination data corrected using data from the first request. Recursion is completely undesirable and so this extra request is performed exactly once and then only in the specific situation where the first request is incorrect. Doing this required breaking apart the `queryGetData()` and adding a new parameter for forcing the page number. Removing a single row from the list view should not reset the pagination, unlike the other filters. When a filter that removes a single row is restored then the pagination must also not be reset. This preserves existing expected behavior. This exposed another bug is observed where when the pagination is restored page index may be incorrect. This is because the database stores the page numbers starting at 0 while the UI table is storing page numbers starting at 1. There are some cases where 1 is incorrectly added or not added. Fixing this ended up being necessary as part of solving the original issue requested to be fixed. The solution here is that when the value comes from the database, increment it by one. The value is preserved, unchanged, in all other cases. When removing a single row and that row is the last row for the page then the pagination must be updated. Change the current page number to the previous page in the case where the current page is not the first page (page index 0 as per DB or page index 1 as per UI). --- .../submission/submissionListController.js | 177 +++++++++++++----- 1 file changed, 131 insertions(+), 46 deletions(-) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index cf1c8edf19..974752e539 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -29,6 +29,8 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.fieldPredicates = FieldPredicateRepo.getAll(); + var rowFilterTitle = "Exclude"; + var ready = $q.all([SubmissionListColumnRepo.ready(), ManagerSubmissionListColumnRepo.ready(), EmailTemplateRepo.ready(), FieldPredicateRepo.ready()]); var updateChange = function(change) { @@ -51,25 +53,27 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle var start; var query = function () { + var pageNumber = $scope.page.number; + var pageCount = $scope.page.count; + + if (angular.isDefined(sessionStorage.getItem("list-page-number")) && sessionStorage.getItem("list-page-number") !== null) { + pageNumber = sessionStorage.getItem("list-page-number"); + } + + if (angular.isDefined(sessionStorage.getItem("list-page-size")) && sessionStorage.getItem("list-page-size") !== null) { + pageCount = sessionStorage.getItem("list-page-size"); + } + $scope.tableParams = new NgTableParams({ - page: $scope.page.number, - count: $scope.page.count + page: pageNumber, + count: pageCount }, { counts: $scope.page.options, total: $scope.page.totalElements, filterDelay: 0, getData: function (params) { start = window.performance.now(); - return SubmissionRepo.query($scope.userColumns, params.page() > 0 ? params.page() - 1 : params.page(), params.count()).then(function (response) { - angular.extend($scope.page, angular.fromJson(response.body).payload.ApiPage); - // NOTE: this causes way to many subscriptions!!! - // SubmissionRepo.addAll($scope.page.content); - params.total($scope.page.totalElements); - $scope.page.count = params.count(); - sessionStorage.setItem("list-page-size", $scope.page.count); - sessionStorage.setItem("list-page-number", $scope.page.number + 1); - return $scope.page.content; - }); + return queryGetData(params); }.bind(start) }); $scope.finished = function() { @@ -77,54 +81,111 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }.bind(start); }.bind(start); - var update = function () { + var queryGetData = function (params, forcePageNumber) { + var requestPage = 0; - SavedFilterRepo.reset(); + if (forcePageNumber === undefined) { + if (params.page() > 0) { + requestPage = params.page() - 1; + } + } else { + requestPage = forcePageNumber; + } - SubmissionListColumnRepo.reset(); + return SubmissionRepo.query($scope.userColumns, requestPage, params.count()).then(function (response) { + var page = angular.fromJson(response.body).payload.ApiPage; - ManagerSubmissionListColumnRepo.reset(); + // Forcibly fix invalid page and try again, but only once. + if (forcePageNumber === undefined && angular.isDefined(page.number) && angular.isDefined(page.totalPages)) { + var totalPages = parseInt(page.totalPages); + var pageNumber = parseInt(page.number); - $q.all([SavedFilterRepo.ready(), SubmissionListColumnRepo.ready(), ManagerSubmissionListColumnRepo.ready()]).then(function() { - ManagerSubmissionListColumnRepo.submissionListPageSize().then(function(response) { - var apiRes = angular.fromJson(response.body); - if(apiRes.meta.status === 'SUCCESS') { - $scope.page.count = sessionStorage.getItem("list-page-size") ? sessionStorage.getItem("list-page-size") : apiRes.payload.Integer; + if (!isNaN(totalPages) && !isNaN(pageNumber) && (pageNumber > totalPages || pageNumber < 0)) { + pageNumber = pageNumber > totalPages && totalPages > 0 ? totalPages - 1 : 0; + + console.warn("Invalid page number '" + page.number + "' detected, forcibly resetting to page '" + pageNumber + "' and trying again."); + + return queryGetData(params, pageNumber); } + } + + angular.extend($scope.page, page); + + // The service sets page number starting at 0, which needs to be incremented by 1 when provided. + if (angular.isDefined(page.number)) { + $scope.page.number++; + } + + params.total($scope.page.totalElements); + params.page($scope.page.number); + $scope.page.count = params.count(); + sessionStorage.setItem("list-page-size", $scope.page.count); + sessionStorage.setItem("list-page-number", $scope.page.number); - var managerFilterColumns = ManagerFilterColumnRepo.getAll(); - var submissionListColumns = SubmissionListColumnRepo.getAll(); + return $scope.page.content; + }); + } + + var update = function (reloadList) { + SavedFilterRepo.reset(); + SubmissionListColumnRepo.reset(); + ManagerSubmissionListColumnRepo.reset(); + + $q.all([SavedFilterRepo.ready(), SubmissionListColumnRepo.ready(), ManagerSubmissionListColumnRepo.ready()]).then(function() { - $scope.userColumns = angular.fromJson(angular.toJson(ManagerSubmissionListColumnRepo.getAll())); + // Only get the list size if/when there is no page count set. + if (angular.isUndefined(sessionStorage.getItem("list-page-size")) || sessionStorage.getItem("list-page-size") === null) { + ManagerSubmissionListColumnRepo.submissionListPageSize().then(function (response) { + var apiRes = angular.fromJson(response.body); - angular.forEach($scope.userColumns, function (userColumn) { - if ($scope.activeFilters.sortColumnTitle === userColumn.title) { - userColumn.sortOrder = 1; - userColumn.sort = $scope.activeFilters.sortDirection; + if (apiRes.meta.status === 'SUCCESS') { + $scope.page.count = apiRes.payload.Integer; + } else if (sessionStorage.getItem("list-page-size")) { + $scope.page.count = sessionStorage.getItem("list-page-size"); } + + processUpdate(reloadList); }); + } else { + processUpdate(reloadList); + } + }); + }; - $scope.excludedColumns = []; + var processUpdate = function (reloadList) { + var managerFilterColumns = ManagerFilterColumnRepo.getAll(); + var submissionListColumns = SubmissionListColumnRepo.getAll(); - angular.copy($scope.userColumns, $scope.excludedColumns); + $scope.userColumns = angular.fromJson(angular.toJson(ManagerSubmissionListColumnRepo.getAll())); - $scope.excludedColumns.push(SubmissionListColumnRepo.findByTitle('Search Box')); + angular.forEach($scope.userColumns, function (userColumn) { + if ($scope.activeFilters.sortColumnTitle === userColumn.title) { + userColumn.sortOrder = 1; + userColumn.sort = $scope.activeFilters.sortDirection; + } + }); - $scope.columns = angular.fromJson(angular.toJson($filter('orderBy')($filter('exclude')(submissionListColumns, $scope.excludedColumns, 'title'), 'title'))); + $scope.excludedColumns = []; - angular.extend(filterColumns, { - userFilterColumns: managerFilterColumns, - inactiveFilterColumns: $filter('orderBy')($filter('exclude')(submissionListColumns, managerFilterColumns, 'title'), 'title') - }); + angular.copy($scope.userColumns, $scope.excludedColumns); - query(); + $scope.excludedColumns.push(SubmissionListColumnRepo.findByTitle('Search Box')); - updateChange(false); - }); + $scope.columns = angular.fromJson(angular.toJson($filter('orderBy')($filter('exclude')(submissionListColumns, $scope.excludedColumns, 'title'), 'title'))); + + angular.extend(filterColumns, { + userFilterColumns: managerFilterColumns, + inactiveFilterColumns: $filter('orderBy')($filter('exclude')(submissionListColumns, managerFilterColumns, 'title'), 'title') }); + + if (reloadList === true) { + query(); + } + + updateChange(false); }; - update(); + update(true); var assignableUsers = UserRepo.getAssignableUsers(0, 0); var savedFilters = SavedFilterRepo.getAll(); @@ -210,10 +271,13 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle var addFilter = function (column, gloss) { + $scope.resetPagination(); + var filterValue = $scope.furtherFilterBy[column.title.split(" ").join("")]; if (filterValue !== null) { filterValue = filterValue.toString(); } + $scope.activeFilters.addFilter(column.title, filterValue, gloss, column.exactMatch).then(function () { $scope.furtherFilterBy[column.title.split(" ").join("")] = ""; query(); @@ -265,12 +329,17 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }); }; - $scope.addRowFilter = function ($index, row) { + $scope.addRowFilter = function ($index, row) { + // When removing the last row for a page, and the page number is the last + if ($scope.page.content.length == 1 && $scope.page.number > 0 && $scope.page.number == $scope.page.totalPages) { + sessionStorage.setItem("list-page-number", --$scope.page.number); + } + $scope.page.content.splice($index, 1); - var columnTitle = "Exclude"; + var value = row.id.toString(); var gloss = "Submission #" + row.id; - $scope.activeFilters.addFilter(columnTitle, value, gloss, true).then (function () { + $scope.activeFilters.addFilter(rowFilterTitle, value, gloss, true).then(function () { query(); }); }; @@ -635,12 +704,19 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }; $scope.removeFilterValue = function (criterionName, filterValue) { + // Reset filter except for when row filters are in use. + if (criterionName !== rowFilterTitle) { + $scope.resetPagination(); + } + $scope.activeFilters.removeFilter(criterionName, filterValue).then(function () { query(); }); }; $scope.clearFilters = function () { + $scope.resetPagination(); + $scope.activeFilters.clearFilters().then(function () { query(); }); @@ -697,6 +773,8 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }; $scope.removeFilter = function (filter) { + $scope.resetPagination(); + SavedFilterRepo.delete(filter).then(function () { SavedFilterRepo.reset(); }); @@ -722,7 +800,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.resetColumns = function () { ManagerSubmissionListColumnRepo.reset(); - update(); + update(true); $scope.closeModal(); updateChange(false); }; @@ -735,7 +813,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.saveColumns = function () { ManagerSubmissionListColumnRepo.updateSubmissionListColumns($scope.userColumns, $scope.page.count).then(function () { - $scope.page.number = 1; + $scope.resetPagination(); sessionStorage.setItem("list-page-size", $scope.page.count); $scope.resetColumns(); }); @@ -746,7 +824,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle for (var i in filterColumns.userFilterColumns) { delete filterColumns.userFilterColumns[i].status; } - update(); + update(false); $scope.closeModal(); }); }; @@ -895,6 +973,13 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.advancedfeaturesBox ]); + $scope.resetPagination = function() { + $scope.pageNumber = 0; + $scope.page.number = 1; + + sessionStorage.setItem("list-page-number", 1); + }; + }); }); From db2b4cacea96a29912138626fe1ed5985cb5d073 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 25 Apr 2023 10:04:07 -0500 Subject: [PATCH 10/47] Issue 1582: Fix white space tabbing. --- .../app/controllers/submission/submissionListController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index 974752e539..2169e768c9 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -147,7 +147,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle processUpdate(reloadList); }); } else { - processUpdate(reloadList); + processUpdate(reloadList); } }); }; From f10072798b6a88cad885ca3bfffc6eab507163e3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Tue, 25 Apr 2023 10:31:47 -0500 Subject: [PATCH 11/47] Issue 1714: Fix customize filters modal drag and drop behavior (#1722) * Refactor modal for consistency * Format modal view * Remove filter breaking drag and drop * Add filter to managed filter columns in controller * Improve save customize filters and columns response handlers --- .../submission/submissionListController.js | 30 +++++---- src/main/webapp/app/views/admin/list.html | 4 +- .../modals/submissions/customizeFilters.html | 62 +++++++++---------- ...odal.html => customizeSubmissionList.html} | 0 .../repos/mockManagerFilterColumnRepo.js | 4 ++ 5 files changed, 55 insertions(+), 45 deletions(-) rename src/main/webapp/app/views/modals/submissions/{customizeSubmissionListModal.html => customizeSubmissionList.html} (100%) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index cfe8455779..6f632a440f 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -81,6 +81,8 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle SavedFilterRepo.reset(); + ManagerFilterColumnRepo.reset(); + SubmissionListColumnRepo.reset(); ManagerSubmissionListColumnRepo.reset(); @@ -92,7 +94,10 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.page.count = sessionStorage.getItem("list-page-size") ? sessionStorage.getItem("list-page-size") : apiRes.payload.Integer; } - var managerFilterColumns = ManagerFilterColumnRepo.getAll(); + var managerFilterColumns = ManagerFilterColumnRepo.getAll().filter(function excludeSearchBox(slc) { + return slc.title !== 'Search Box'; + }); + var submissionListColumns = SubmissionListColumnRepo.getAll(); $scope.userColumns = angular.fromJson(angular.toJson(ManagerSubmissionListColumnRepo.getAll())); @@ -723,10 +728,8 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }; $scope.resetColumns = function () { - ManagerSubmissionListColumnRepo.reset(); update(); $scope.closeModal(); - updateChange(false); }; $scope.resetColumnsToDefault = function () { @@ -736,20 +739,23 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle }; $scope.saveColumns = function () { - ManagerSubmissionListColumnRepo.updateSubmissionListColumns($scope.userColumns, $scope.page.count).then(function () { - $scope.page.number = 1; - sessionStorage.setItem("list-page-size", $scope.page.count); - $scope.resetColumns(); + ManagerSubmissionListColumnRepo.updateSubmissionListColumns($scope.userColumns, $scope.page.count).then(function (res) { + var results = angular.fromJson(res.body); + if (results.meta.status === 'SUCCESS') { + $scope.page.number = 1; + sessionStorage.setItem("list-page-size", $scope.page.count); + $scope.resetColumns(); + } }); }; $scope.saveUserFilters = function () { - ManagerFilterColumnRepo.updateFilterColumns(filterColumns.userFilterColumns).then(function () { - for (var i in filterColumns.userFilterColumns) { - delete filterColumns.userFilterColumns[i].status; + ManagerFilterColumnRepo.updateFilterColumns(filterColumns.userFilterColumns).then(function (res) { + var results = angular.fromJson(res.body); + if (results.meta.status === 'SUCCESS') { + update(); + $scope.closeModal(); } - update(); - $scope.closeModal(); }); }; diff --git a/src/main/webapp/app/views/admin/list.html b/src/main/webapp/app/views/admin/list.html index 9841a38494..ef2cb64e8c 100644 --- a/src/main/webapp/app/views/admin/list.html +++ b/src/main/webapp/app/views/admin/list.html @@ -1,12 +1,12 @@
- +

List ETDs


- Customize view + Customize view diff --git a/src/main/webapp/app/views/modals/submissions/customizeFilters.html b/src/main/webapp/app/views/modals/submissions/customizeFilters.html index ab22382999..a2085f034b 100644 --- a/src/main/webapp/app/views/modals/submissions/customizeFilters.html +++ b/src/main/webapp/app/views/modals/submissions/customizeFilters.html @@ -1,39 +1,39 @@ diff --git a/src/main/webapp/app/views/modals/submissions/customizeSubmissionListModal.html b/src/main/webapp/app/views/modals/submissions/customizeSubmissionList.html similarity index 100% rename from src/main/webapp/app/views/modals/submissions/customizeSubmissionListModal.html rename to src/main/webapp/app/views/modals/submissions/customizeSubmissionList.html diff --git a/src/main/webapp/tests/mocks/repos/mockManagerFilterColumnRepo.js b/src/main/webapp/tests/mocks/repos/mockManagerFilterColumnRepo.js index f1863991b1..a742dc80ea 100644 --- a/src/main/webapp/tests/mocks/repos/mockManagerFilterColumnRepo.js +++ b/src/main/webapp/tests/mocks/repos/mockManagerFilterColumnRepo.js @@ -5,5 +5,9 @@ angular.module("mock.managerFilterColumnRepo", []).service("ManagerFilterColumnR return payloadPromise($q.defer(), angular.copy(repo.mockedList)); }; + repo.reset = function () { + return payloadPromise($q.defer()); + }; + return repo; }); From ab90c4fda4c024528ccd8a28960be14afa4a861d Mon Sep 17 00:00:00 2001 From: William Welling Date: Tue, 25 Apr 2023 10:31:56 -0500 Subject: [PATCH 12/47] Split and apply between condition when pipe in date filter (#1723) --- .../model/repo/impl/SubmissionRepoImpl.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java index 2642013089..6aead50eed 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java @@ -893,6 +893,14 @@ protected String getChannel() { * @return A constructed string builder appropriately casting the date. */ private StringBuilder buildDateFieldString(int id, String filter) { + if (filter.contains("|")) { + String[] dates = filter.split(Pattern.quote("|")); + return new StringBuilder() + .append("pfv").append(id) + .append(".value BETWEEN CAST('").append(dates[0]) + .append("' AS DATE) AND CAST('").append(dates[1]) + .append("' AS DATE)"); + } return new StringBuilder() .append("pfv").append(id) .append(".value = CAST('").append(filter) @@ -909,9 +917,18 @@ private StringBuilder buildDateFieldString(int id, String filter) { * @return A constructed string builder appropriately casting the date. */ private StringBuilder buildSubmissionDateFieldString(String column, String filter) { + if (filter.contains("|")) { + String[] dates = filter.split(Pattern.quote("|")); + return new StringBuilder() + .append("s.").append(column) + .append(" BETWEEN CAST('").append(dates[0]) + .append("' AS DATE) AND CAST('").append(dates[1]) + .append("' AS DATE)"); + } return new StringBuilder() .append("s.").append(column) - .append(" = CAST('").append(filter).append("' AS DATE)"); + .append(" = CAST('").append(filter) + .append("' AS DATE)"); } private class QueryStrings { From 9c1346b80cfabc8ca2fa256a797cc1d18443c018 Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Wed, 26 Apr 2023 09:15:26 -0500 Subject: [PATCH 13/47] set proper contrast and add configuration options --- .../config/constant/ConfigurationName.java | 10 +- .../service/VireoThemeManagerService.java | 2 +- .../resources/settings/SYSTEM_Defaults.json | 10 +- .../webapp/app/resources/styles/sass/app.scss | 10 +- .../views/submission/_studentSubmission.scss | 3 +- .../settings/application/lookAndFeel.html | 92 +++++++++++++++---- 6 files changed, 100 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java b/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java index 8e384a014c..4226c541dd 100644 --- a/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java +++ b/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java @@ -60,7 +60,10 @@ public class ConfigurationName { public final static String BACKGROUND_HIGHLIGHT_COLOR = "background_highlight_color"; /** Background text color */ - public final static String BACKGROUND_TEXT_COLOR = "background_text_color"; + public final static String BACKGROUND_MAIN_TEXT_COLOR = "background_main_text_color"; + + /** Background text color */ + public final static String BACKGROUND_HIGHLIGHTTEXT_COLOR = "background_highlight_text_color"; /** Submission Step Button main color when in "on" state */ public final static String BUTTON_MAIN_COLOR_ON = "button_main_color_on"; @@ -87,7 +90,10 @@ public class ConfigurationName { public final static String ADMIN_TAB_SELECTED_COLOR = "admin_tab_selected_color"; /** Admin navigation tab text color*/ - public final static String ADMIN_TAB_TEXT_COLOR = "admin_tab_text_color"; + public final static String ADMIN_TAB_MAIN_TEXT_COLOR = "admin_tab_main_text_color"; + + /** Admin navigation tab text color*/ + public final static String ADMIN_TAB_SELECTED_TEXT_COLOR = "admin_tab_selected_text_color"; /** Custom CSS */ public final static String LEFT_LOGO = "left_logo"; diff --git a/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java b/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java index 8fda3eaaba..9e6ca744bc 100644 --- a/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java +++ b/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java @@ -24,7 +24,7 @@ public class VireoThemeManagerService extends SimpleThemeManagerService implemen @Override public Map getThemeProperties() { - String[] themePropertyNames = {"text_main_color", "background_main_color", "background_highlight_color", "background_text_color", "button_main_color_on", "button_highlight_color_on", "button_text_color_on", "button_main_color_off", "button_highlight_color_off", "button_text_color_off", "admin_tab_main_color", "admin_tab_selected_color", "admin_tab_text_color"}; + String[] themePropertyNames = {"text_main_color", "background_main_color", "background_highlight_color", "background_main_text_color", "background_highlight_text_color", "button_main_color_on", "button_highlight_color_on", "button_text_color_on", "button_main_color_off", "button_highlight_color_off", "button_text_color_off", "admin_tab_main_color", "admin_tab_selected_color", "admin_tab_main_text_color", "admin_tab_selected_text_color"}; List themePropertyNamesList = Arrays.asList(themePropertyNames); List themeConfigurations = configurationRepo.getAllByType("lookAndFeel"); HashMap themeProperties = new HashMap(); diff --git a/src/main/resources/settings/SYSTEM_Defaults.json b/src/main/resources/settings/SYSTEM_Defaults.json index e13778ad1d..75ee3ba17f 100644 --- a/src/main/resources/settings/SYSTEM_Defaults.json +++ b/src/main/resources/settings/SYSTEM_Defaults.json @@ -95,7 +95,10 @@ "background_highlight_color":"#43606e" }, { - "background_text_color":"#ffffff" + "background_main_text_color":"#ffffff" + }, + { + "background_highlight_text_color":"#ffffff" }, { "button_main_color_on":"#1b333f" @@ -122,7 +125,10 @@ "admin_tab_selected_color":"#ffffff" }, { - "admin_tab_text_color":"#1D3541" + "admin_tab_main_text_color":"#1D3541" + }, + { + "admin_tab_selected_text_color":"#1D3541" }, { "left_logo":"resources/images/default-left-logo.png" diff --git a/src/main/webapp/app/resources/styles/sass/app.scss b/src/main/webapp/app/resources/styles/sass/app.scss index 0eabe76af3..bdbefe3825 100644 --- a/src/main/webapp/app/resources/styles/sass/app.scss +++ b/src/main/webapp/app/resources/styles/sass/app.scss @@ -81,7 +81,7 @@ main footer { margin-right: 15px; min-width: 75px; text-align: center; - color: $admin_tab_text_color; + color: $admin_tab_main_text_color; font-size: 1.75em; font-weight: bolder; display: inline-block; @@ -100,6 +100,7 @@ main footer { .tab-nav li.active, .tab-nav li:hover { cursor: pointer; + color: $admin_tab_selected_text_color; background: $admin_tab_selected_color; box-shadow: inset 0 0 0 #FFFFFF; } @@ -151,6 +152,7 @@ main footer { } .modal-header-primary { + color: $background_highlight_text_color; background-color: $background_highlight_color; } @@ -390,12 +392,12 @@ tr.submission-list-row:hover td span.glyphicon.glyphicon-remove-circle { .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:focus, .navbar-default .navbar-nav > .active > a:hover { - color: #fff; + color: $background_highlight_text_color; background-color: $background_highlight_color; } .navbar-default .navbar-nav > li > a { - color: #fff; + color: $background_highlight_text_color; } .navbar-default .navbar-brand { @@ -839,7 +841,7 @@ legend.legendborder { footer a, footer li, footer p { - color: #fff; + color: $background_main_text_color; font-size: 0.9em; } diff --git a/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss b/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss index 24323c2d6a..30e3dbd11a 100644 --- a/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss +++ b/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss @@ -70,7 +70,7 @@ padding: 10px 15px; border-radius: 4px; width: 100%; - color: white; + color: $button_text_color_off; background: $button_main_color_off; background: -moz-linear-gradient linear-gradient(to right, $button_main_color_off, $button_highlight_color_off); background: -webkit-linear-gradient(to right, $button_main_color_off, $button_highlight_color_off); @@ -82,6 +82,7 @@ .submission-workflow-step-navigation a .invisible-button:focus, .submission-workflow-step-navigation.active a .invisible-button { cursor: pointer; + color: $button_text_color_on; background: rgb(31, 58, 71); background: -moz-linear-gradient linear-gradient(to right, $button_main_color_on, $button_highlight_color_on); background: -webkit-linear-gradient(to right, $button_main_color_on, $button_highlight_color_on); diff --git a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html index 201ca5bf99..f29a7b0db6 100644 --- a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html +++ b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html @@ -112,10 +112,10 @@
- Text Color + Main Text Color + ng-click="resetConfiguration('lookAndFeel','background_main_text_color')">
@@ -124,17 +124,46 @@ # - +
+ +
+
+ Highlight Text Color + + + +
+ +
+ # + + + +
@@ -429,10 +458,10 @@
- Text Color + Main Text Color + ng-click="resetConfiguration('lookAndFeel','admin_tab_main_text_color')">
@@ -441,21 +470,50 @@ # -
- + +
+
+ Selected Text Color + + + +
+ +
+ # + + + + + +
+
From cf2673eae621ea8e0c59f6b0a89872e75b39c7fc Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 26 Apr 2023 09:20:14 -0500 Subject: [PATCH 14/47] Issue 1264: Use a single query to fetch filters for both user or if public. This both fixes the problem and likely improves performance. A performance improvement is assumed due to the change to a single database call and the lack of joining two arrays. --- .../tdl/vireo/controller/SubmissionListController.java | 9 +-------- .../tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java | 3 ++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java index 83f9440e35..d9a44230dc 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java @@ -281,14 +281,7 @@ public ApiResponse clearFilterCriteria(@WeaverUser User user) { @RequestMapping("/all-saved-filter-criteria") @PreAuthorize("hasRole('REVIEWER')") public ApiResponse getAllSaveFilterCriteria(@WeaverUser User user) { - List userSavedFilters = user.getSavedFilters(); - List publicSavedFilters = namedSearchFilterGroupRepo.findByPublicFlagTrue(); - - List allSavedFilters = new ArrayList(); - allSavedFilters.addAll(userSavedFilters); - allSavedFilters.addAll(publicSavedFilters); - - return new ApiResponse(SUCCESS, userSavedFilters); + return new ApiResponse(SUCCESS, namedSearchFilterGroupRepo.findByUserOrPublicFlagTrue(user)); } @RequestMapping(value = "/save-filter-criteria", method = POST) diff --git a/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java b/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java index 544ec59792..b67cf053d1 100644 --- a/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java +++ b/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java @@ -3,13 +3,14 @@ import java.util.List; import org.tdl.vireo.model.NamedSearchFilterGroup; +import org.tdl.vireo.model.User; import org.tdl.vireo.model.repo.custom.NamedSearchFilterGroupRepoCustom; import edu.tamu.weaver.data.model.repo.WeaverRepo; public interface NamedSearchFilterGroupRepo extends WeaverRepo, NamedSearchFilterGroupRepoCustom { - public List findByPublicFlagTrue(); + public List findByUserOrPublicFlagTrue(User user); public NamedSearchFilterGroup findByNameAndPublicFlagTrue(String name); From 402b3d54656714ca3f95b440a9bd13a285d87e77 Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Wed, 26 Apr 2023 09:38:04 -0500 Subject: [PATCH 15/47] refactored for clarity --- .../config/constant/ConfigurationName.java | 6 +-- .../service/VireoThemeManagerService.java | 2 +- .../resources/settings/SYSTEM_Defaults.json | 4 +- .../webapp/app/resources/styles/sass/app.scss | 8 +-- .../settings/application/lookAndFeel.html | 53 +++++++++---------- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java b/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java index 4226c541dd..c8381620f5 100644 --- a/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java +++ b/src/main/java/org/tdl/vireo/config/constant/ConfigurationName.java @@ -58,12 +58,12 @@ public class ConfigurationName { /** Background highlight color */ public final static String BACKGROUND_HIGHLIGHT_COLOR = "background_highlight_color"; - + /** Background text color */ - public final static String BACKGROUND_MAIN_TEXT_COLOR = "background_main_text_color"; + public final static String BACKGROUND_HEADER_TEXT_COLOR = "background_header_text_color"; /** Background text color */ - public final static String BACKGROUND_HIGHLIGHTTEXT_COLOR = "background_highlight_text_color"; + public final static String BACKGROUNT_FOOTER_TEXT_COLOR = "background_footer_text_color"; /** Submission Step Button main color when in "on" state */ public final static String BUTTON_MAIN_COLOR_ON = "button_main_color_on"; diff --git a/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java b/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java index 9e6ca744bc..fb96bca5cc 100644 --- a/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java +++ b/src/main/java/org/tdl/vireo/service/VireoThemeManagerService.java @@ -24,7 +24,7 @@ public class VireoThemeManagerService extends SimpleThemeManagerService implemen @Override public Map getThemeProperties() { - String[] themePropertyNames = {"text_main_color", "background_main_color", "background_highlight_color", "background_main_text_color", "background_highlight_text_color", "button_main_color_on", "button_highlight_color_on", "button_text_color_on", "button_main_color_off", "button_highlight_color_off", "button_text_color_off", "admin_tab_main_color", "admin_tab_selected_color", "admin_tab_main_text_color", "admin_tab_selected_text_color"}; + String[] themePropertyNames = {"text_main_color", "background_main_color", "background_highlight_color", "background_header_text_color", "background_footer_text_color", "button_main_color_on", "button_highlight_color_on", "button_text_color_on", "button_main_color_off", "button_highlight_color_off", "button_text_color_off", "admin_tab_main_color", "admin_tab_selected_color", "admin_tab_main_text_color", "admin_tab_selected_text_color"}; List themePropertyNamesList = Arrays.asList(themePropertyNames); List themeConfigurations = configurationRepo.getAllByType("lookAndFeel"); HashMap themeProperties = new HashMap(); diff --git a/src/main/resources/settings/SYSTEM_Defaults.json b/src/main/resources/settings/SYSTEM_Defaults.json index 75ee3ba17f..bea6e82458 100644 --- a/src/main/resources/settings/SYSTEM_Defaults.json +++ b/src/main/resources/settings/SYSTEM_Defaults.json @@ -95,10 +95,10 @@ "background_highlight_color":"#43606e" }, { - "background_main_text_color":"#ffffff" + "background_header_text_color":"#ffffff" }, { - "background_highlight_text_color":"#ffffff" + "background_footer_text_color":"#ffffff" }, { "button_main_color_on":"#1b333f" diff --git a/src/main/webapp/app/resources/styles/sass/app.scss b/src/main/webapp/app/resources/styles/sass/app.scss index bdbefe3825..efa7378053 100644 --- a/src/main/webapp/app/resources/styles/sass/app.scss +++ b/src/main/webapp/app/resources/styles/sass/app.scss @@ -152,7 +152,7 @@ main footer { } .modal-header-primary { - color: $background_highlight_text_color; + color: $background_header_text_color; background-color: $background_highlight_color; } @@ -392,12 +392,12 @@ tr.submission-list-row:hover td span.glyphicon.glyphicon-remove-circle { .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:focus, .navbar-default .navbar-nav > .active > a:hover { - color: $background_highlight_text_color; + color: $background_header_text_color; background-color: $background_highlight_color; } .navbar-default .navbar-nav > li > a { - color: $background_highlight_text_color; + color: $background_header_text_color; } .navbar-default .navbar-brand { @@ -841,7 +841,7 @@ legend.legendborder { footer a, footer li, footer p { - color: $background_main_text_color; + color: $background_footer_text_color; font-size: 0.9em; } diff --git a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html index f29a7b0db6..3a6f144957 100644 --- a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html +++ b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html @@ -42,7 +42,7 @@
-
Header/Footer Background +
Header/Footer
@@ -50,7 +50,7 @@
- Main Color + Background Main Color @@ -82,7 +82,7 @@
- Highlight Color + Background Highlight Color @@ -109,13 +109,12 @@
-
- Main Text Color + Header Text Color + ng-click="resetConfiguration('lookAndFeel','background_header_text_color')">
@@ -124,27 +123,27 @@ # -
-
+
- Highlight Text Color + Footer Text Color + ng-click="resetConfiguration('lookAndFeel','background_footer_text_color')">
@@ -153,17 +152,17 @@ # -
@@ -181,7 +180,7 @@
- Main Color + Background Main Color @@ -211,7 +210,7 @@
- Highlight Color + Background Highlight Color @@ -285,7 +284,7 @@
- Main Color + Background Main Color @@ -320,7 +319,7 @@
- Highlight Color + Background Highlight Color @@ -391,7 +390,7 @@
- Main Color + Background Main Color @@ -426,7 +425,7 @@
- Selected Color + Background Selected Color From 3f6e5a142f33c1f85a7ae0d51126809645e80607 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 26 Apr 2023 11:07:46 -0500 Subject: [PATCH 16/47] 1582: Redesign logic to avoid fetching from session storage multiple times. As per request of a PR reviewer this avoids checking the session storage multiple times. --- .../submission/submissionListController.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index c629cd3380..724a574204 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -53,20 +53,12 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle var start; var query = function () { - var pageNumber = $scope.page.number; - var pageCount = $scope.page.count; - - if (angular.isDefined(sessionStorage.getItem("list-page-number")) && sessionStorage.getItem("list-page-number") !== null) { - pageNumber = sessionStorage.getItem("list-page-number"); - } - - if (angular.isDefined(sessionStorage.getItem("list-page-size")) && sessionStorage.getItem("list-page-size") !== null) { - pageCount = sessionStorage.getItem("list-page-size"); - } + var sessionPageNumber = sessionStorage.getItem("list-page-number"); + var sessionPageSize = sessionStorage.getItem("list-page-size"); $scope.tableParams = new NgTableParams({ - page: pageNumber, - count: pageCount + page: angular.isDefined(sessionPageNumber) && sessionPageNumber !== null ? sessionPageNumber : $scope.page.number, + count: angular.isDefined(sessionPageSize) && sessionPageSize !== null ? sessionPageSize : $scope.page.count, }, { counts: $scope.page.options, total: $scope.page.totalElements, From 80e276f6fe4c855126d9ec09eff16cefc0fcc609 Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Wed, 26 Apr 2023 11:39:40 -0500 Subject: [PATCH 17/47] added debounce for colorpicker --- .../app/views/admin/settings/application/lookAndFeel.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html index 3fcc883e57..e400ea32dc 100644 --- a/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html +++ b/src/main/webapp/app/views/admin/settings/application/lookAndFeel.html @@ -1,4 +1,4 @@ -
+
From 7bc306ff51f6a8477c2f7bf9898cd72e5e85d48d Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Wed, 26 Apr 2023 11:47:52 -0500 Subject: [PATCH 18/47] check for null before reset --- src/main/webapp/app/controllers/settingsController.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/app/controllers/settingsController.js b/src/main/webapp/app/controllers/settingsController.js index ff903f361f..461356c4b8 100644 --- a/src/main/webapp/app/controllers/settingsController.js +++ b/src/main/webapp/app/controllers/settingsController.js @@ -251,7 +251,9 @@ vireo.controller("SettingsController", function ($controller, $injector, $scope, }; $scope.resetConfiguration = function (type, name) { - return $scope.settings.configurable[type][name].reset(); + if ($scope.settings.configurable[type][name].id) { + return $scope.settings.configurable[type][name].reset(); + } }; $scope.saveDegree = function (degree) { From 0820fce44bf02cb8c1d8a7e47ecb27bb180654d0 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 27 Apr 2023 09:33:52 -0500 Subject: [PATCH 19/47] Issue 1264: Take alternate approach for fetching saved filters. The previous commit (cf2673eae621ea8e0c59f6b0a89872e75b39c7fc) is around selecting all filters for user or all public. There are apparently filters that are not saved filters (which relates to a likely separate bug). Avoid using these by partially reverting the changes in the referenced commit. Select all public filters that are not associated with the requested user. Then join the array from the already loaded saved filters from the User entity. --- .../org/tdl/vireo/controller/SubmissionListController.java | 5 ++++- .../org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java index d9a44230dc..c641a806f3 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java @@ -281,7 +281,10 @@ public ApiResponse clearFilterCriteria(@WeaverUser User user) { @RequestMapping("/all-saved-filter-criteria") @PreAuthorize("hasRole('REVIEWER')") public ApiResponse getAllSaveFilterCriteria(@WeaverUser User user) { - return new ApiResponse(SUCCESS, namedSearchFilterGroupRepo.findByUserOrPublicFlagTrue(user)); + List all = namedSearchFilterGroupRepo.findByUserIsNotAndPublicFlagTrue(user); + all.addAll(user.getSavedFilters()); + + return new ApiResponse(SUCCESS, all); } @RequestMapping(value = "/save-filter-criteria", method = POST) diff --git a/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java b/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java index b67cf053d1..0708fea185 100644 --- a/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java +++ b/src/main/java/org/tdl/vireo/model/repo/NamedSearchFilterGroupRepo.java @@ -10,7 +10,7 @@ public interface NamedSearchFilterGroupRepo extends WeaverRepo, NamedSearchFilterGroupRepoCustom { - public List findByUserOrPublicFlagTrue(User user); + public List findByUserIsNotAndPublicFlagTrue(User user); public NamedSearchFilterGroup findByNameAndPublicFlagTrue(String name); From bb12ca57d7d66af1a1192a8d550e49d6fdf11601 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 27 Apr 2023 11:40:26 -0500 Subject: [PATCH 20/47] Issue 1731: Improve handling when attempting to delete filters. The failure may be happening due to problems with finding the filter in the saved filters and it not being there. Add sanity checks and then only attempt the save when the filter actually exists in the saved filter for the current user. Otherwise, return a failure. Rename the `removeFilter` into `removeSaveFilter` to be less confusing and more consistent with similar functions in the UI. This depends on commit 0820fce44bf02cb8c1d8a7e47ecb27bb180654d0 and is based off of the branch for the PR #1736 that contains the referenced commit. --- .../controller/SubmissionListController.java | 21 +++++----- .../submission/submissionListController.js | 4 +- .../submissions/removeExistingFilters.html | 40 +++++++++---------- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java index c641a806f3..8f5e38ae4c 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java @@ -4,10 +4,12 @@ import static edu.tamu.weaver.response.ApiStatus.SUCCESS; import static org.springframework.web.bind.annotation.RequestMethod.POST; -import java.util.ArrayList; +import edu.tamu.weaver.auth.annotation.WeaverUser; +import edu.tamu.weaver.response.ApiResponse; +import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel; import java.util.List; import java.util.Map; - +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,10 +35,6 @@ import org.tdl.vireo.model.repo.UserRepo; import org.tdl.vireo.service.DefaultSubmissionListColumnService; -import edu.tamu.weaver.auth.annotation.WeaverUser; -import edu.tamu.weaver.response.ApiResponse; -import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel; - @RestController @RequestMapping("/submission-list") public class SubmissionListController { @@ -182,9 +180,14 @@ public ApiResponse getSavedFilters(@WeaverUser User user) { @PreAuthorize("hasRole('REVIEWER')") @RequestMapping(value = "/remove-saved-filter", method = POST) public ApiResponse removeSavedFilter(@WeaverUser User user, @WeaverValidatedModel NamedSearchFilterGroup savedFilter) { - user.getSavedFilters().remove(savedFilter); - user = userRepo.save(user); - return new ApiResponse(SUCCESS, user.getActiveFilter()); + if (user.getSavedFilters().contains(savedFilter)) { + user.getSavedFilters().remove(savedFilter); + user = userRepo.save(user); + + return new ApiResponse(SUCCESS, user.getActiveFilter()); + } + + return new ApiResponse(ERROR, "Cannot not find filter."); } @PreAuthorize("hasRole('REVIEWER')") diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index cf1c8edf19..4697788495 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -696,7 +696,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle updateChange(false); }; - $scope.removeFilter = function (filter) { + $scope.removeSaveFilter = function (filter) { SavedFilterRepo.delete(filter).then(function () { SavedFilterRepo.reset(); }); @@ -888,7 +888,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle "resetSaveUserFilters": $scope.resetSaveFilter, "applyFilter": $scope.applyFilter, "resetRemoveFilters": $scope.resetRemoveFilters, - "removeFilter": $scope.removeFilter, + "removeSaveFilter": $scope.removeSaveFilter, "getUserById": $scope.getUserById }, $scope.furtherFilterBy, diff --git a/src/main/webapp/app/views/modals/submissions/removeExistingFilters.html b/src/main/webapp/app/views/modals/submissions/removeExistingFilters.html index ae0ad0b0df..2414858782 100644 --- a/src/main/webapp/app/views/modals/submissions/removeExistingFilters.html +++ b/src/main/webapp/app/views/modals/submissions/removeExistingFilters.html @@ -5,28 +5,24 @@
-
- - - - - - - - - - - - - -
- {{column}} -
- - {{filter.name}}{{filter.columnsFlag}}{{box.getUserById(filter.user).firstName}} {{box.getUserById(filter.user).lastName}} {{filter.publicFlag ? 'public':'private'}} filter
-
- diff --git a/src/main/webapp/app/views/inputtype/input-contact.html b/src/main/webapp/app/views/inputtype/input-contact.html index 73f3770cfd..80591e9b4f 100644 --- a/src/main/webapp/app/views/inputtype/input-contact.html +++ b/src/main/webapp/app/views/inputtype/input-contact.html @@ -15,7 +15,7 @@ - +

@@ -32,7 +32,7 @@ typeahead-no-results="noResults" typeahead-on-select="saveWithCV(fieldValue, $item)"/> - +
\ No newline at end of file diff --git a/src/main/webapp/app/views/inputtype/input-contact_select.html b/src/main/webapp/app/views/inputtype/input-contact_select.html index 530bdde75c..5bedf8b1dc 100644 --- a/src/main/webapp/app/views/inputtype/input-contact_select.html +++ b/src/main/webapp/app/views/inputtype/input-contact_select.html @@ -17,7 +17,7 @@
@@ -29,7 +29,7 @@ placeholder="{{fieldValue.contacts[0]}}" disabled> - +
diff --git a/src/main/webapp/app/views/inputtype/input-date.html b/src/main/webapp/app/views/inputtype/input-date.html index 8d0775c7f4..95bdf2666a 100644 --- a/src/main/webapp/app/views/inputtype/input-date.html +++ b/src/main/webapp/app/views/inputtype/input-date.html @@ -18,7 +18,7 @@ readonly stringtodate/> - +
diff --git a/src/main/webapp/app/views/inputtype/input-degreedate.html b/src/main/webapp/app/views/inputtype/input-degreedate.html index 842086b664..1212f98447 100644 --- a/src/main/webapp/app/views/inputtype/input-degreedate.html +++ b/src/main/webapp/app/views/inputtype/input-degreedate.html @@ -18,7 +18,7 @@ readonly stringtodate/> - +
diff --git a/src/main/webapp/app/views/inputtype/input-email.html b/src/main/webapp/app/views/inputtype/input-email.html index 90546f8e1a..129b4c89e2 100644 --- a/src/main/webapp/app/views/inputtype/input-email.html +++ b/src/main/webapp/app/views/inputtype/input-email.html @@ -8,7 +8,7 @@ uib-typeahead="word.name as word.name for word in profile.controlledVocabulary.dictionary | filter: { name: $viewValue }" typeahead-on-select="saveWithCV(fieldValue, $item)"/> - +
\ No newline at end of file diff --git a/src/main/webapp/app/views/inputtype/input-file.html b/src/main/webapp/app/views/inputtype/input-file.html index 818a61ecfb..cf4f682064 100644 --- a/src/main/webapp/app/views/inputtype/input-file.html +++ b/src/main/webapp/app/views/inputtype/input-file.html @@ -2,7 +2,7 @@
- + @@ -41,7 +41,7 @@
- + diff --git a/src/main/webapp/app/views/inputtype/input-orcid.html b/src/main/webapp/app/views/inputtype/input-orcid.html index 6820ce4571..c55d1dce44 100644 --- a/src/main/webapp/app/views/inputtype/input-orcid.html +++ b/src/main/webapp/app/views/inputtype/input-orcid.html @@ -9,7 +9,7 @@ uib-typeahead="word.name as word.name for word in profile.controlledVocabulary.dictionary | filter: { name: $viewValue }" typeahead-on-select="saveWithCV(fieldValue, $item)"/> - +
\ No newline at end of file diff --git a/src/main/webapp/app/views/inputtype/input-radio.html b/src/main/webapp/app/views/inputtype/input-radio.html index f5e72696d6..1175cb6be9 100644 --- a/src/main/webapp/app/views/inputtype/input-radio.html +++ b/src/main/webapp/app/views/inputtype/input-radio.html @@ -14,7 +14,7 @@
{{word.name}}
{{word.definition}}
- +
diff --git a/src/main/webapp/app/views/inputtype/input-select.html b/src/main/webapp/app/views/inputtype/input-select.html index 3f62e56212..0922c3ded1 100644 --- a/src/main/webapp/app/views/inputtype/input-select.html +++ b/src/main/webapp/app/views/inputtype/input-select.html @@ -17,7 +17,7 @@
diff --git a/src/main/webapp/app/views/inputtype/input-tel.html b/src/main/webapp/app/views/inputtype/input-tel.html index 51d7307f0e..43e25a21a0 100644 --- a/src/main/webapp/app/views/inputtype/input-tel.html +++ b/src/main/webapp/app/views/inputtype/input-tel.html @@ -9,7 +9,7 @@ uib-typeahead="word.name as word.name for word in profile.controlledVocabulary.dictionary | filter: { name: $viewValue }" typeahead-on-select="saveWithCV(fieldValue, $item)"/> - +
\ No newline at end of file diff --git a/src/main/webapp/app/views/inputtype/input-text.html b/src/main/webapp/app/views/inputtype/input-text.html index 9b89f41a73..bef4750052 100644 --- a/src/main/webapp/app/views/inputtype/input-text.html +++ b/src/main/webapp/app/views/inputtype/input-text.html @@ -9,7 +9,7 @@ uib-typeahead="word.name as word.name for word in profile.controlledVocabulary.dictionary | filter: { name: $viewValue } | orderBy:'name'" typeahead-on-select="saveWithCV(fieldValue, $item)"/> - + diff --git a/src/main/webapp/app/views/inputtype/input-textarea.html b/src/main/webapp/app/views/inputtype/input-textarea.html index 09480e84a8..a027a6d4ea 100644 --- a/src/main/webapp/app/views/inputtype/input-textarea.html +++ b/src/main/webapp/app/views/inputtype/input-textarea.html @@ -6,7 +6,7 @@ ng-blur="save(fieldValue)" ng-disabled="fieldValue.updating"> - + \ No newline at end of file diff --git a/src/main/webapp/app/views/inputtype/input-url.html b/src/main/webapp/app/views/inputtype/input-url.html index c4cabf5dc8..8672cd4932 100644 --- a/src/main/webapp/app/views/inputtype/input-url.html +++ b/src/main/webapp/app/views/inputtype/input-url.html @@ -9,7 +9,7 @@ ng-disabled="fieldValue.updating" uib-typeahead="word.name as word.name for word in profile.controlledVocabulary.dictionary | filter: { name: $viewValue }"/> - + From e8ad32546343e57dc5029239b639a55e7e050ed7 Mon Sep 17 00:00:00 2001 From: Christopher Starcher Date: Fri, 28 Apr 2023 13:55:45 -0500 Subject: [PATCH 24/47] added tabindex to submission notes --- .../resources/organization/SYSTEM_Organization_Definition.json | 2 +- src/main/webapp/app/views/submission/submission.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/organization/SYSTEM_Organization_Definition.json b/src/main/resources/organization/SYSTEM_Organization_Definition.json index e02949061d..1e90a9ed21 100644 --- a/src/main/resources/organization/SYSTEM_Organization_Definition.json +++ b/src/main/resources/organization/SYSTEM_Organization_Definition.json @@ -18,7 +18,7 @@ "originalNotes":[ { "name":"name", - "text":"Your name should appear as it does on your title page. You can use Unicode characters, if your computer supports them", + "text":"Your name should appear as it does on your title page. You can use Unicode characters, if your computer supports them.", "originatingWorkflowStep":{ "name":"Verify Personal Information" } diff --git a/src/main/webapp/app/views/submission/submission.html b/src/main/webapp/app/views/submission/submission.html index 6cfc590069..f88040e33a 100644 --- a/src/main/webapp/app/views/submission/submission.html +++ b/src/main/webapp/app/views/submission/submission.html @@ -50,7 +50,7 @@

Submission ({{submission.organization.name}})

  • - +
From b2c538c5c9c7d99a18c9f8c2c47b8cc98c01a260 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Fri, 28 Apr 2023 11:24:44 -0500 Subject: [PATCH 25/47] Issue 1667: Reduce cost of the COUNT query for the submission list dynamic query. This helps with the performance problem. The COUNT query only needs the ID and does not need group by or any of the columns. The sub-queries with their joins are causing problems. If any WHERE condition is needed, use a single join query rather than a sub-query. This is safe because ORDER BY is not needed in the count query. The non-COUNT query should also not add any sub-queries unless those sub-queries have a WHERE condition or a ORDER BY clause association with it. This does not address the problems with the non-COUNT query. This does not solve the problem at hand, instead it is progress towards the solution. This adds additional debug logging to show the timings between the COUNT, non-COUNT, and other queries. --- .../controller/SubmissionListController.java | 10 +- .../model/repo/impl/SubmissionRepoImpl.java | 411 ++++++++++++------ 2 files changed, 270 insertions(+), 151 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java index 83f9440e35..679b149d6e 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java @@ -4,10 +4,12 @@ import static edu.tamu.weaver.response.ApiStatus.SUCCESS; import static org.springframework.web.bind.annotation.RequestMethod.POST; +import edu.tamu.weaver.auth.annotation.WeaverUser; +import edu.tamu.weaver.response.ApiResponse; +import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel; import java.util.ArrayList; import java.util.List; import java.util.Map; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,10 +35,6 @@ import org.tdl.vireo.model.repo.UserRepo; import org.tdl.vireo.service.DefaultSubmissionListColumnService; -import edu.tamu.weaver.auth.annotation.WeaverUser; -import edu.tamu.weaver.response.ApiResponse; -import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel; - @RestController @RequestMapping("/submission-list") public class SubmissionListController { @@ -284,7 +282,7 @@ public ApiResponse getAllSaveFilterCriteria(@WeaverUser User user) { List userSavedFilters = user.getSavedFilters(); List publicSavedFilters = namedSearchFilterGroupRepo.findByPublicFlagTrue(); - List allSavedFilters = new ArrayList(); + List allSavedFilters = new ArrayList<>(); allSavedFilters.addAll(userSavedFilters); allSavedFilters.addAll(publicSavedFilters); diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java index 2642013089..374890521c 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java @@ -337,20 +337,30 @@ public List batchDynamicSubmissionQuery(NamedSearchFilterGroup activ @Override public Page pageableDynamicSubmissionQuery(NamedSearchFilterGroup activeFilter, List submissionListColums, Pageable pageable) throws ExecutionException { + long startTime = System.nanoTime(); + QueryStrings queryBuilder = craftDynamicSubmissionQuery(activeFilter, submissionListColums, pageable); Long total = jdbcTemplate.queryForObject(queryBuilder.getCountQuery(), Long.class); - List ids = jdbcTemplate.query(queryBuilder.getQuery(), new RowMapper() { + logger.debug("Count query for dynamic query took " + ((System.nanoTime() - startTime) / 1000000000.0) + " seconds"); + startTime = System.nanoTime(); + + List ids = jdbcTemplate.query(queryBuilder.getQuery(), new RowMapper<>() { public Long mapRow(ResultSet rs, int rowNum) throws SQLException { return rs.getLong("ID"); } }); - List submissions = new ArrayList(); + logger.debug("ID query for dynamic query took " + ((System.nanoTime() - startTime) / 1000000000.0) + " seconds"); + startTime = System.nanoTime(); + + List submissions = new ArrayList<>(); List unordered = submissionRepo.findAllById(ids); + logger.debug("Find all query for dynamic query took " + ((System.nanoTime() - startTime) / 1000000000.0) + " seconds"); + // order them for (Long id : ids) { for (Submission sub : unordered) { @@ -370,7 +380,7 @@ public Long mapRow(ResultSet rs, int rowNum) throws SQLException { private QueryStrings craftDynamicSubmissionQuery(NamedSearchFilterGroup activeFilter, List submissionListColums, Pageable pageable) { // set up storage for user's preferred columns - Set allColumnSearchFilters = new HashSet(); + Set allColumnSearchFilters = new HashSet<>(); // get all the possible columns, some of which we will make visible List allSubmissionListColumns = submissionListColumnRepo.findAll(); @@ -406,7 +416,7 @@ private QueryStrings craftDynamicSubmissionQuery(NamedSearchFilterGroup activeFi } // sort all submission list columns by sort order provided by users submission list columns - Collections.sort(allSubmissionListColumns, new Comparator() { + Collections.sort(allSubmissionListColumns, new Comparator<>() { @Override public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { return svc1.getSortOrder().compareTo(svc2.getSortOrder()); @@ -415,17 +425,20 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { StringBuilder sqlSelectBuilder = new StringBuilder("SELECT DISTINCT s.id,"); - StringBuilder sqlCountSelectBuilder = new StringBuilder("SELECT COUNT(DISTINCT s.id) FROM submission s "); + StringBuilder sqlCountSelectBuilder = new StringBuilder(); - Map> sqlColumnsBuilders = new HashMap>(); + Map> sqlColumnsBuilders = new HashMap<>(); + Map> sqlCountWhereFilterBuilders = new HashMap<>(); + Map sqlCountWherePredicate = new HashMap<>(); StringBuilder sqlJoinsBuilder = new StringBuilder(); - StringBuilder sqlWhereBuilder; + StringBuilder sqlBuilder; + StringBuilder sqlCountBuilder; StringBuilder sqlWheresExcludeBuilder = new StringBuilder(); StringBuilder sqlOrderBysBuilder = new StringBuilder(); ArrayList sqlWhereBuilderList; - ArrayList sqlAllColumnsWhereBuilderList = new ArrayList(); + ArrayList sqlAllColumnsWhereBuilderList = new ArrayList<>(); int n = 0; @@ -457,61 +470,88 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); + sqlCountBuilder = new StringBuilder(); switch (submissionListColumn.getInputType().getName()) { case "INPUT_DEGREEDATE": // Column's values are of type 'MMMM yyyy' (in SQL date format would be 'Month YYYY'). - sqlWhereBuilder.append("LOWER(pfv").append(n).append(".value) = LOWER('").append(filterString).append("')"); + sqlBuilder.append("LOWER(pfv").append(n).append(".value) = LOWER('").append(filterString).append("')"); + sqlCountBuilder.append("LOWER(fv.value) = LOWER('").append(filterString).append("')"); break; case "INPUT_DATE": // Column's values are of type 'yyyy-mm-dd' as required by the SQL standard to represent a date without time. if (filterString.contains("|")) { // Date Range String[] dates = filterString.split(Pattern.quote("|")); - sqlWhereBuilder + sqlBuilder .append("CAST(pfv").append(n) .append(".value AS DATE) BETWEEN CAST('").append(dates[0]) .append("' AS DATE) AND CAST('").append(dates[1]) .append("' AS DATE)"); + sqlCountBuilder + .append("CAST(fv.value AS DATE) BETWEEN CAST('").append(dates[0]) + .append("' AS DATE) AND CAST('").append(dates[1]) + .append("' AS DATE)"); } else { // Date Match - sqlWhereBuilder.append("pfv").append(n).append(".value = '").append(filterString).append("'"); + sqlBuilder.append("pfv").append(n).append(".value = '").append(filterString).append("'"); + sqlCountBuilder.append("fv.value = '").append(filterString).append("'"); } break; case "INPUT_CHECKBOX": - sqlWhereBuilder.append("pfv").append(n).append(".value = '").append(filterString).append("'"); + sqlBuilder.append("pfv").append(n).append(".value = '").append(filterString).append("'"); + sqlCountBuilder.append("fv.value = '").append(filterString).append("'"); // Column's values are a boolean if (!Boolean.valueOf(filterString)) { - sqlWhereBuilderList.add(sqlWhereBuilder); - sqlWhereBuilder = new StringBuilder(); + sqlWhereBuilderList.add(sqlBuilder); + + if (!sqlCountWherePredicate.containsKey(predicateId)) { + sqlCountWherePredicate.put(predicateId, new StringBuilder()); + } + + sqlCountWherePredicate.get(predicateId).append(" (").append(sqlCountBuilder).append(") OR"); + + sqlBuilder = new StringBuilder(); + sqlBuilder.append(" pfv").append(n).append(".value IS NULL"); - sqlWhereBuilder.append(" pfv").append(n).append(".value IS NULL"); + sqlCountBuilder = new StringBuilder(); + sqlCountBuilder.append(" fv.value IS NULL"); } + break; default: // Column's values can be handled by this default if (submissionListColumn.getExactMatch()) { // perform exact match - sqlWhereBuilder.append("pfv").append(n).append(".value = '").append(filterString).append("'"); + sqlBuilder.append("pfv").append(n).append(".value = '").append(filterString).append("'"); + sqlCountBuilder.append("fv.value = '").append(filterString).append("'"); } else { // perform like when input from text field - sqlWhereBuilder.append("LOWER(pfv").append(n).append(".value) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlBuilder.append("LOWER(pfv").append(n).append(".value) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlCountBuilder.append("LOWER(fv.value) LIKE '%").append(filterString.toLowerCase()).append("%'"); } + break; } - if (sqlWhereBuilder.length() > 0) { - sqlWhereBuilderList.add(sqlWhereBuilder); + if (sqlBuilder.length() > 0) { + sqlWhereBuilderList.add(sqlBuilder); + + if (!sqlCountWherePredicate.containsKey(predicateId)) { + sqlCountWherePredicate.put(predicateId, new StringBuilder()); + } + + sqlCountWherePredicate.get(predicateId).append(" (").append(sqlCountBuilder).append(") OR"); } } // all column search filter for (String filterString : allColumnSearchFilters) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("LOWER(pfv").append(n).append(".value) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(pfv").append(n).append(".value) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); } n++; @@ -521,43 +561,48 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { case "id": if (submissionListColumn.getSortOrder() > 0) { - setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " s.id"); + setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, null); } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("s").append(".id = ").append(filterString); - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("s").append(".id = ").append(filterString); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "id").add(sqlBuilder); } break; case "submissionStatus.name": + sqlBuilder = new StringBuilder() + .append("\nLEFT JOIN submission_status ss ON ss.id=s.submission_status_id"); - sqlJoinsBuilder.append("\nLEFT JOIN submission_status ss ON ss.id=s.submission_status_id"); + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); if (submissionListColumn.getSortOrder() > 0) { setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " ss.name"); } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); if (submissionListColumn.getExactMatch()) { - sqlWhereBuilder.append("ss").append(".name = '").append(filterString).append("'"); + sqlBuilder.append("ss").append(".name = '").append(filterString).append("'"); } else { // TODO: determine if status will ever be search using a like - sqlWhereBuilder.append("LOWER(ss").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlBuilder.append("LOWER(ss").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); } - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "submissionStatus.name").add(sqlBuilder); } // all column search filter for (String filterString : allColumnSearchFilters) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("LOWER(ss").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(ss").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); } break; @@ -565,7 +610,11 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { case "organization.name": if (sqlJoinsBuilder.indexOf("LEFT JOIN organization o ON o.id=s.organization_id") == -1) { - sqlJoinsBuilder.append("\nLEFT JOIN organization o ON o.id=s.organization_id"); + sqlBuilder = new StringBuilder() + .append("\nLEFT JOIN organization o ON o.id=s.organization_id"); + + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); } if (submissionListColumn.getSortOrder() > 0) { @@ -573,140 +622,154 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); if (submissionListColumn.getExactMatch()) { - sqlWhereBuilder.append("o").append(".name = '").append(filterString).append("'"); + sqlBuilder.append("o").append(".name = '").append(filterString).append("'"); } else { // TODO: determine if organization name will ever be // search using a like - sqlWhereBuilder.append("LOWER(o").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlBuilder.append("LOWER(o").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); } - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "organization.name").add(sqlBuilder); } // all column search filter for (String filterString : allColumnSearchFilters) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("LOWER(o").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(o").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); } break; case "organization.category.name": + sqlBuilder = new StringBuilder(); if (sqlJoinsBuilder.indexOf("LEFT JOIN organization o ON o.id=s.organization_id") == -1) { - sqlJoinsBuilder.append("\nLEFT JOIN organization o ON o.id=s.organization_id"); + sqlBuilder.append("\nLEFT JOIN organization o ON o.id=s.organization_id"); } - sqlJoinsBuilder.append("\nLEFT JOIN organization_category oc ON oc.id=o.category_id"); + sqlBuilder.append("\nLEFT JOIN organization_category oc ON oc.id=o.category_id"); + + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); if (submissionListColumn.getSortOrder() > 0) { setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " oc.name"); } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); if (submissionListColumn.getExactMatch()) { - sqlWhereBuilder.append("oc").append(".name = '").append(filterString).append("'"); + sqlBuilder.append("oc").append(".name = '").append(filterString).append("'"); } else { // TODO: determine if organization category name // will ever be search using a like - sqlWhereBuilder.append("LOWER(oc").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlBuilder.append("LOWER(oc").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); } - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "organization.category.name").add(sqlBuilder); } // all column search filter for (String filterString : allColumnSearchFilters) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("LOWER(oc").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(oc").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); } break; case "assignee.email": + sqlBuilder = new StringBuilder() + .append("\nLEFT JOIN weaver_users a ON a.id=s.assignee_id"); - sqlJoinsBuilder.append("\nLEFT JOIN weaver_users a ON a.id=s.assignee_id"); + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); if (submissionListColumn.getSortOrder() > 0) { setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " a.email"); } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); if (filterString == null) { - sqlWhereBuilder.append("a").append(".email IS NULL"); + sqlBuilder.append("a").append(".email IS NULL"); } else if (submissionListColumn.getExactMatch()) { - sqlWhereBuilder.append("a").append(".email = '").append(filterString).append("'"); + sqlBuilder.append("a").append(".email = '").append(filterString).append("'"); } else { - sqlWhereBuilder.append("LOWER(a").append(".email) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlBuilder.append("LOWER(a").append(".email) LIKE '%").append(filterString.toLowerCase()).append("%'"); } - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "assignee.email").add(sqlBuilder); } // all column search filter for (String filterString : allColumnSearchFilters) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("LOWER(a").append(".email) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(a").append(".email) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); } break; case "embargoTypes.name": - // @formatter:off - sqlJoinsBuilder.append("\nLEFT JOIN") - .append("\n (SELECT e.id, e.name, semt.submission_id") - .append("\n FROM embargo e") - .append("\n LEFT JOIN submission_embargo_types semt") - .append("\n ON semt.embargo_types_id=e.id) embs") - .append("\n ON embs.submission_id=s.id"); - // @formatter:on + sqlBuilder = new StringBuilder() + .append("\nLEFT JOIN") + .append("\n (SELECT e.id, e.name, semt.submission_id") + .append("\n FROM embargo e") + .append("\n LEFT JOIN submission_embargo_types semt") + .append("\n ON semt.embargo_types_id=e.id) embs") + .append("\n ON embs.submission_id=s.id"); + + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); if (submissionListColumn.getSortOrder() > 0) { setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " embs.name"); } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); - sqlWhereBuilder.append(" embs").append(".name = '").append(filterString).append("'"); + sqlBuilder.append(" embs").append(".name = '").append(filterString).append("'"); if (filterString.equals("None")) { - sqlWhereBuilderList.add(sqlWhereBuilder); - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("embs.id IS NULL"); + sqlWhereBuilderList.add(sqlBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("embs.id IS NULL"); } - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "embargoTypes.name").add(sqlBuilder); } // all column search filter for (String filterString : allColumnSearchFilters) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("LOWER(embs").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(embs").append(".name) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); } break; case "lastEvent": - // @formatter:off - - sqlJoinsBuilder.append("\nLEFT JOIN") - .append("\n (SELECT al.id, al.action_date, al.entry, al.action_logs_id") - .append("\n FROM action_log al") - .append("\n WHERE (al.action_logs_id = id)") - .append("\n ORDER BY al.action_date DESC") - .append("\n LIMIT 1) als") - .append("\n ON action_logs_id = s.submission_status_id"); - // @formatter:on + sqlBuilder = new StringBuilder() + .append("\nLEFT JOIN") + .append("\n (SELECT al.id, al.action_date, al.entry, al.action_logs_id") + .append("\n FROM action_log al") + .append("\n WHERE (al.action_logs_id = id)") + .append("\n ORDER BY al.action_date DESC") + .append("\n LIMIT 1) als") + .append("\n ON action_logs_id = s.submission_status_id"); + + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); // TODO: finish sqlWheresBuilder. @@ -735,7 +798,9 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilderList.add(buildSubmissionDateFieldString("submission_date", filterString)); + sqlBuilder = buildSubmissionDateFieldString("submission_date", filterString); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "submissionDate").add(sqlBuilder); } break; @@ -746,7 +811,9 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilderList.add(buildSubmissionDateFieldString("approve_application_date", filterString)); + sqlBuilder = buildSubmissionDateFieldString("approve_application_date", filterString); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "approveApplicationDate").add(sqlBuilder); } break; @@ -757,7 +824,9 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilderList.add(buildSubmissionDateFieldString("approve_advisor_date", filterString)); + sqlBuilder = buildSubmissionDateFieldString("approve_advisor_date", filterString); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "approveAdvisorDate").add(sqlBuilder); } break; @@ -768,25 +837,29 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilderList.add(buildSubmissionDateFieldString("approve_embargo_date", filterString)); + sqlBuilder = buildSubmissionDateFieldString("approve_embargo_date", filterString); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "approveEmbargoDate").add(sqlBuilder); } break; case "customActionValues": + sqlBuilder = new StringBuilder() + .append("\nLEFT JOIN") + .append("\n (SELECT submission_id, value, label") + .append("\n FROM submission_custom_action_values scav") + .append("\n LEFT JOIN custom_action_value cav ON scav.custom_action_values_id = cav .id") + .append("\n LEFT JOIN custom_action_definition cad ON cav.definition_id = cad.id) scavcavcad") + .append("\n ON scavcavcad.submission_id = s.id"); - // @formatter:off - sqlJoinsBuilder.append("\nLEFT JOIN") - .append("\n (SELECT submission_id, value, label") - .append("\n FROM submission_custom_action_values scav") - .append("\n LEFT JOIN custom_action_value cav ON scav.custom_action_values_id = cav .id") - .append("\n LEFT JOIN custom_action_definition cad ON cav.definition_id = cad.id) scavcavcad") - .append("\n ON scavcavcad.submission_id = s.id"); - // @formatter:on + sqlJoinsBuilder.append(sqlBuilder); + sqlCountSelectBuilder.append(sqlBuilder); for (String filterString : submissionListColumn.getFilters()) { - sqlWhereBuilder = new StringBuilder(); - sqlWhereBuilder.append("scavcavcad.value = true AND scavcavcad.label = '" + filterString + "'"); - sqlWhereBuilderList.add(sqlWhereBuilder); + sqlBuilder = new StringBuilder(); + sqlBuilder.append("scavcavcad.value = true AND scavcavcad.label = '" + filterString + "'"); + sqlWhereBuilderList.add(sqlBuilder); + getFromBuildersMap(sqlCountWhereFilterBuilders, "customActionValues").add(sqlBuilder); } break; @@ -800,9 +873,10 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } } - // complete select clause + // Complete the select clause. sqlSelectBuilder.setLength(sqlSelectBuilder.length() - 1); sqlSelectBuilder.append(" FROM submission s"); + sqlCountSelectBuilder.insert(0, "SELECT COUNT(DISTINCT s.id) FROM submission s"); // if ordering, complete order by clause and strip the tailing comma if (sqlOrderBysBuilder.length() > 0) { @@ -811,46 +885,94 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } // build WHERE query such that OR is used for conditions inside a column and AND is used across each different column. - sqlWhereBuilder = new StringBuilder(); + sqlBuilder = new StringBuilder(); if (sqlColumnsBuilders.size() > 0 || sqlAllColumnsWhereBuilderList.size() > 0 || sqlWheresExcludeBuilder.length() > 0) { - sqlWhereBuilder.append("\nWHERE "); + sqlBuilder.append("\nWHERE "); for (Entry> list : sqlColumnsBuilders.entrySet()) { - sqlWhereBuilder.append("("); + sqlBuilder.append("("); for (StringBuilder builder : list.getValue()) { - sqlWhereBuilder.append("(").append(builder).append(") OR "); + sqlBuilder.append("(").append(builder).append(") OR "); } - // remove last " OR". - sqlWhereBuilder.setLength(sqlWhereBuilder.length() - 4); + // remove last " OR ". + sqlBuilder.setLength(sqlBuilder.length() - 4); - sqlWhereBuilder.append(") AND "); + sqlBuilder.append(") AND "); } if (sqlAllColumnsWhereBuilderList.size() > 0) { - sqlWhereBuilder.append("("); + sqlBuilder.append("("); for (StringBuilder builder : sqlAllColumnsWhereBuilderList) { - sqlWhereBuilder.append("(").append(builder).append(") OR "); + sqlBuilder.append("(").append(builder).append(") OR "); } - // remove last " OR". - sqlWhereBuilder.setLength(sqlWhereBuilder.length() - 4); + // remove last " OR ". + sqlBuilder.setLength(sqlBuilder.length() - 4); - sqlWhereBuilder.append(") AND "); + sqlBuilder.append(") AND "); } if (sqlWheresExcludeBuilder.length() > 0) { - sqlWhereBuilder.append("(").append(sqlWheresExcludeBuilder).append(")"); + sqlBuilder.append("(").append(sqlWheresExcludeBuilder).append(")"); + } else { + // remove last " AND " + sqlBuilder.setLength(sqlBuilder.length() - 5); + } + } + + if (sqlCountWherePredicate.size() > 0 || sqlCountWhereFilterBuilders.size() > 0 || sqlWheresExcludeBuilder.length() > 0) { + + // Conditions are AND across different predicates but are OR within the same predicate. + if (sqlCountWherePredicate.size() > 0) { + sqlCountSelectBuilder.append("\nLEFT JOIN submission_field_values sfv ON s.id = sfv.submission_id"); + sqlCountSelectBuilder.append("\nINNER JOIN field_value fv ON sfv.field_values_id = fv.id"); + sqlCountSelectBuilder.append("\nWHERE"); + + sqlCountWherePredicate.forEach((id, filter) -> { + if (filter.length() > 0) { + // Remove the last " OR". + filter.setLength(filter.length() - 3); + + sqlCountSelectBuilder + .append("\n(fv.field_predicate_id = ").append(id) + .append(" AND (").append(filter).append("))"); + } + }); + + sqlCountSelectBuilder.append(" AND"); + } else { + sqlCountSelectBuilder.append("\nWHERE"); + } + + // Conditions are AND across different filters and OR within the same filter. + if (sqlCountWhereFilterBuilders.size() > 0) { + sqlCountWhereFilterBuilders.forEach((key, list) -> { + sqlCountSelectBuilder.append(" ("); + + list.forEach(filter -> { + sqlCountSelectBuilder.append(" (").append(filter).append(") OR"); + }); + + // Remove the last " OR". + sqlCountSelectBuilder.setLength(sqlCountSelectBuilder.length() - 3); + + sqlCountSelectBuilder.append(")\n AND"); + }); + } + + if (sqlWheresExcludeBuilder.length() > 0) { + sqlCountSelectBuilder.append("\n(").append(sqlWheresExcludeBuilder).append(")"); } else { // remove last " AND" - sqlWhereBuilder.setLength(sqlWhereBuilder.length() - 5); + sqlCountSelectBuilder.setLength(sqlCountSelectBuilder.length() - 4); } } - String sqlQuery = sqlSelectBuilder.toString() + sqlJoinsBuilder.toString() + sqlWhereBuilder.toString(); - String sqlCountQuery = sqlCountSelectBuilder.toString() + sqlJoinsBuilder.toString() + sqlWhereBuilder.toString(); + String sqlQuery = sqlSelectBuilder.toString() + sqlJoinsBuilder.toString() + sqlBuilder.toString(); + String sqlCountQuery = sqlCountSelectBuilder.toString(); if (pageable != null) { // determine the offset and limit of the query @@ -867,17 +989,14 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } public void setColumnOrdering(Sort sort, StringBuilder sqlSelectBuilder, StringBuilder sqlOrderBysBuilder, String value) { - sqlSelectBuilder.append(value).append(","); - switch (sort) { - case ASC: - sqlOrderBysBuilder.append(value).append(" ASC,"); - break; - case DESC: - sqlOrderBysBuilder.append(value).append(" DESC,"); - break; - default: - break; - } + if (sort == Sort.ASC || sort == Sort.DESC) { + // Allow sqlSelectBuilder to be NULL to easily facilitate not appending "s.id". + if (sqlSelectBuilder != null) { + sqlSelectBuilder.append(value).append(","); + } + + sqlOrderBysBuilder.append(value).append(" ").append(sort.name()).append(","); + } } @Override @@ -885,20 +1004,6 @@ protected String getChannel() { return "/channel/submission"; } - /** - * Build a date field string given some filter. - * - * @param id The ID to append to the field name alias. - * @param filter The filter. - * @return A constructed string builder appropriately casting the date. - */ - private StringBuilder buildDateFieldString(int id, String filter) { - return new StringBuilder() - .append("pfv").append(id) - .append(".value = CAST('").append(filter) - .append("' AS DATE)"); - } - /** * Build a submission date field string given some filter. * @@ -914,6 +1019,22 @@ private StringBuilder buildSubmissionDateFieldString(String column, String filte .append(" = CAST('").append(filter).append("' AS DATE)"); } + /** + * Get the builders list array for some key, initializing that key if not found. + * + * @param map The map of builders to select from. + * @param key The identifier. + * + * @return An array of the builders for the given key. + */ + private ArrayList getFromBuildersMap(Map> map, String key) { + if (!map.containsKey(key)) { + map.put(key, new ArrayList()); + } + + return map.get(key); + } + private class QueryStrings { private final String countQuery; From 4459c0e15d21d5f7592545e4d657bb778df2e5a7 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 1 May 2023 09:49:05 -0500 Subject: [PATCH 26/47] Issue 1667: The user settings active filter is EAGER. This is believed to be the primary cause of the performance problem observed when a user has an active filter. The performance cost can be seen ot only on the submission list but on just about any other page so long as a filter was made active of the submission list at one point in time. --- src/main/java/org/tdl/vireo/model/User.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/model/User.java b/src/main/java/org/tdl/vireo/model/User.java index e84aadb92c..ff1ded4b8f 100644 --- a/src/main/java/org/tdl/vireo/model/User.java +++ b/src/main/java/org/tdl/vireo/model/User.java @@ -5,6 +5,7 @@ import static javax.persistence.CascadeType.REFRESH; import static javax.persistence.CascadeType.REMOVE; import static javax.persistence.FetchType.EAGER; +import static javax.persistence.FetchType.LAZY; import java.util.ArrayList; import java.util.Collection; @@ -121,7 +122,7 @@ public class User extends AbstractWeaverUserDetails { @ManyToMany(cascade = { REFRESH }, fetch = EAGER) private List filterColumns; - @ManyToOne(cascade = { REFRESH, MERGE }, fetch = EAGER, optional = true) + @ManyToOne(cascade = { REFRESH, MERGE }, fetch = LAZY, optional = true) private NamedSearchFilterGroup activeFilter; @Fetch(FetchMode.SELECT) From 1f5e0cb19e07f02407b0ef62c1a390ee10c2813f Mon Sep 17 00:00:00 2001 From: William Welling Date: Mon, 1 May 2023 13:11:55 -0500 Subject: [PATCH 27/47] Switching NamedSearchFilterGroup ManyToMany with SubmissionListColumn to LAZY fetch (#1749) --- src/main/java/org/tdl/vireo/model/NamedSearchFilterGroup.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/model/NamedSearchFilterGroup.java b/src/main/java/org/tdl/vireo/model/NamedSearchFilterGroup.java index e273c41f7c..3a4fb8a959 100644 --- a/src/main/java/org/tdl/vireo/model/NamedSearchFilterGroup.java +++ b/src/main/java/org/tdl/vireo/model/NamedSearchFilterGroup.java @@ -3,6 +3,7 @@ import static javax.persistence.CascadeType.MERGE; import static javax.persistence.CascadeType.REFRESH; import static javax.persistence.FetchType.EAGER; +import static javax.persistence.FetchType.LAZY; import java.util.ArrayList; import java.util.HashSet; @@ -63,7 +64,7 @@ public class NamedSearchFilterGroup extends ValidatingBaseEntity { private Sort sortDirection; @OrderColumn - @ManyToMany(cascade = { REFRESH, MERGE }, fetch = EAGER) + @ManyToMany(cascade = { REFRESH, MERGE }, fetch = LAZY) private List savedColumns; @Fetch(FetchMode.SELECT) From f5c1a5b92f1129da36e4e2742e7751d7dad45d02 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 1 May 2023 14:19:05 -0500 Subject: [PATCH 28/47] Issue 1667: The non-count query should not join the sub-queries if not necessary. The query is designed to only return the submission ids. The individual columns are added in the SELECT line because, for whatever reason, SQL requires that anything in the ORDER BY to be in the column. There are, therefore, two cases when the sub-query must be joined: 1. When there is a condition for the WHERE clause (the filters). 2. When the ORDER BY is in use for what would be represented in that sub-query. In all other cases, the non-COUNT SELECT query can be made similar to the COUNT query such that only the required sub-queries are joined. Another query is made later on in the code that might pull in the required columns. That query is passed the submission ids that come from this query. --- .../model/repo/impl/SubmissionRepoImpl.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java index 374890521c..2772b4d8c1 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java @@ -457,13 +457,16 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { Long predicateId = fieldPredicateRepo.findByValue(submissionListColumn.getPredicate()).getId(); // @formatter:off - sqlJoinsBuilder.append("\nLEFT JOIN") - .append("\n (SELECT sfv").append(n).append(".submission_id, fv").append(n).append(".*") - .append("\n FROM submission_field_values sfv").append(n) - .append("\n LEFT JOIN field_value fv").append(n).append(" ON fv").append(n).append(".id=sfv").append(n).append(".field_values_id ") - .append("\n WHERE fv").append(n).append(".field_predicate_id=").append(predicateId).append(") pfv").append(n) - .append("\n ON pfv").append(n).append(".submission_id=s.id"); - // @formatter:on + if (submissionListColumn.getSortOrder() > 0 || submissionListColumn.getFilters().size() > 0) { + sqlJoinsBuilder + .append("\nLEFT JOIN") + .append("\n (SELECT sfv").append(n).append(".submission_id, fv").append(n).append(".*") + .append("\n FROM submission_field_values sfv").append(n) + .append("\n LEFT JOIN field_value fv").append(n) + .append(" ON fv").append(n).append(".id=sfv").append(n).append(".field_values_id ") + .append("\n WHERE fv").append(n).append(".field_predicate_id=").append(predicateId).append(") pfv").append(n) + .append("\n ON pfv").append(n).append(".submission_id=s.id"); + } if (submissionListColumn.getSortOrder() > 0) { setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " pfv" + n + ".value"); @@ -547,14 +550,16 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } } - // all column search filter - for (String filterString : allColumnSearchFilters) { - sqlBuilder = new StringBuilder(); - sqlBuilder.append("LOWER(pfv").append(n).append(".value) LIKE '%").append(filterString.toLowerCase()).append("%'"); - sqlAllColumnsWhereBuilderList.add(sqlBuilder); - } + if (submissionListColumn.getSortOrder() > 0 || submissionListColumn.getFilters().size() > 0) { + // all column search filter + for (String filterString : allColumnSearchFilters) { + sqlBuilder = new StringBuilder(); + sqlBuilder.append("LOWER(pfv").append(n).append(".value) LIKE '%").append(filterString.toLowerCase()).append("%'"); + sqlAllColumnsWhereBuilderList.add(sqlBuilder); + } - n++; + n++; + } break; From 5db449725ea722c2e2a44f67e3e91def8fe6e882 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 2 May 2023 08:28:59 -0500 Subject: [PATCH 29/47] Issue 1667: Use explicit code to handle exception case rather than a NULL check. The ORDER BY still needs the value name which would be getting a NULL in that case. Therefore, it makes more sense to manually set the order by for `s.id` rather than complicate the function further by adding more logic to it. --- .../vireo/model/repo/impl/SubmissionRepoImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java index 374890521c..6206d17df9 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java @@ -561,7 +561,11 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { case "id": if (submissionListColumn.getSortOrder() > 0) { - setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, null); + // The s.id is already on the submission, such just add it to the order by rather than call setColumnOrdering(). + Sort sort = submissionListColumn.getSort(); + if (sort == Sort.ASC || sort == Sort.DESC) { + sqlOrderBysBuilder.append(" s.id ").append(sort.name()).append(","); + } } for (String filterString : submissionListColumn.getFilters()) { @@ -990,13 +994,9 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { public void setColumnOrdering(Sort sort, StringBuilder sqlSelectBuilder, StringBuilder sqlOrderBysBuilder, String value) { if (sort == Sort.ASC || sort == Sort.DESC) { - // Allow sqlSelectBuilder to be NULL to easily facilitate not appending "s.id". - if (sqlSelectBuilder != null) { - sqlSelectBuilder.append(value).append(","); - } - + sqlSelectBuilder.append(value).append(","); sqlOrderBysBuilder.append(value).append(" ").append(sort.name()).append(","); - } + } } @Override From 0fc2d22be149bb5b1dd6b7eb9d9bf86bdd1e1880 Mon Sep 17 00:00:00 2001 From: William Welling Date: Wed, 3 May 2023 14:25:19 -0500 Subject: [PATCH 30/47] Reset columns to default after clearing filters Ensure successful response is handled in https://github.com/TexasDigitalLibrary/Vireo/pull/1758 --- .../app/controllers/submission/submissionListController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index cf1c8edf19..2cb8e2c394 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -642,7 +642,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.clearFilters = function () { $scope.activeFilters.clearFilters().then(function () { - query(); + $scope.resetColumnsToDefault(); }); }; From 936e3161e9ffcddd6c1e6269e83ac098dba099b9 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 3 May 2023 14:37:04 -0500 Subject: [PATCH 31/47] Issue 1667: Place the AND in the correct location. An over sight resulted in having the AND in the wrong location. This causes a regression where having multiple filters could produce an SQL exception. --- .../org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java index 074e0a3cea..bbb68a641d 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java @@ -947,11 +947,9 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { sqlCountSelectBuilder .append("\n(fv.field_predicate_id = ").append(id) - .append(" AND (").append(filter).append("))"); + .append(" AND (").append(filter).append(")) AND"); } }); - - sqlCountSelectBuilder.append(" AND"); } else { sqlCountSelectBuilder.append("\nWHERE"); } From 665919a8dcdb43581ccbfeac5ccd196c8713b732 Mon Sep 17 00:00:00 2001 From: William Welling Date: Wed, 3 May 2023 16:17:32 -0500 Subject: [PATCH 32/47] Use anonymous download from file service Additional use link styled span to avoid multiple event handlers --- package.json | 2 +- .../app/directives/reviewSubmissionFieldsDirective.js | 3 +++ src/main/webapp/app/model/submission.js | 2 +- .../styles/sass/views/submission/_submissionAdvisor.scss | 6 ++++++ .../webapp/app/views/directives/reviewSubmissionFields.html | 2 +- 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 447b647e19..1af784793c 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "build": "wvr build --clean" }, "dependencies": { - "@wvr/core": "2.2.4", + "@wvr/core": "git@github.com:TAMULib/Weaver-UI-Core.git#wwelling-patch-1", "angular-ui-tinymce": "0.0.19", "file-saver": "2.0.5", "ng-csv": "0.3.6", diff --git a/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js b/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js index 89bfcbd191..a7c271f828 100644 --- a/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js +++ b/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js @@ -56,9 +56,12 @@ vireo.directive('reviewsubmissionsfields', function ($location, InputTypes, Fiel }; $scope.getFile = function (fieldValue) { + console.log(fieldValue); $scope.submission.fileInfo(fieldValue).then(function (data) { + console.log(data); fieldValue.fileInfo = angular.fromJson(data.body).payload.ObjectNode; $scope.submission.file(fieldValue.value).then(function (data) { + console.log(data); saveAs(new Blob([data], { type: fieldValue.fileInfo.type }), fieldValue.fileInfo.name); diff --git a/src/main/webapp/app/model/submission.js b/src/main/webapp/app/model/submission.js index 2dc938dd89..3caceb95cf 100644 --- a/src/main/webapp/app/model/submission.js +++ b/src/main/webapp/app/model/submission.js @@ -514,7 +514,7 @@ var submissionModel = function ($filter, $q, ActionLog, FieldValue, FileService, 'uri': uri } }); - var promise = FileService.download(this.getMapping().file); + var promise = FileService.anonymousDownload(this.getMapping().file); return promise; }; diff --git a/src/main/webapp/app/resources/styles/sass/views/submission/_submissionAdvisor.scss b/src/main/webapp/app/resources/styles/sass/views/submission/_submissionAdvisor.scss index f207cf02fc..7f1b4734da 100644 --- a/src/main/webapp/app/resources/styles/sass/views/submission/_submissionAdvisor.scss +++ b/src/main/webapp/app/resources/styles/sass/views/submission/_submissionAdvisor.scss @@ -6,3 +6,9 @@ margin-left: 0; margin-right: 0; } + +.file-link { + color: #337ab7; + cursor: pointer; + text-decoration: none; +} diff --git a/src/main/webapp/app/views/directives/reviewSubmissionFields.html b/src/main/webapp/app/views/directives/reviewSubmissionFields.html index 8f3ffd04a8..04aed31c5d 100644 --- a/src/main/webapp/app/views/directives/reviewSubmissionFields.html +++ b/src/main/webapp/app/views/directives/reviewSubmissionFields.html @@ -21,7 +21,7 @@

{{fv.contacts[0]}} - {{fv.fileInfo.name}} + {{fv.fileInfo.name}} From d9b8dcbe7d2ac1b90b2ab4042eefae2d6074c3a9 Mon Sep 17 00:00:00 2001 From: William Welling Date: Wed, 3 May 2023 16:28:12 -0500 Subject: [PATCH 33/47] Update mock file service and submission unit test --- src/main/webapp/tests/mocks/services/mockFileService.js | 7 ++++++- src/main/webapp/tests/unit/models/submissionTest.js | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/tests/mocks/services/mockFileService.js b/src/main/webapp/tests/mocks/services/mockFileService.js index 7ba89596dc..0636337bd8 100644 --- a/src/main/webapp/tests/mocks/services/mockFileService.js +++ b/src/main/webapp/tests/mocks/services/mockFileService.js @@ -1,7 +1,12 @@ angular.module("mock.fileService", []).service("FileService", function ($q) { var service = mockService($q); - service.download = function (submission, fieldValue) { + service.download = function (req) { + var download = {}; + return download; + }; + + service.anonymousDownload = function (req) { var download = {}; return download; }; diff --git a/src/main/webapp/tests/unit/models/submissionTest.js b/src/main/webapp/tests/unit/models/submissionTest.js index 864b6f0413..d620fc5640 100644 --- a/src/main/webapp/tests/unit/models/submissionTest.js +++ b/src/main/webapp/tests/unit/models/submissionTest.js @@ -292,12 +292,12 @@ describe('model: Submission', function () { scope.$apply(); }); it('file should call FileService', function () { - spyOn(FileService, "download"); + spyOn(FileService, "anonymousDownload"); model.file("uri"); scope.$apply(); - expect(FileService.download).toHaveBeenCalled(); + expect(FileService.anonymousDownload).toHaveBeenCalled(); }); it('fileInfo should call WsApi', function () { var fieldValue = new mockFieldValue(q); From 06a7a926105cc0a248fc311a8c79ffb95e5c3867 Mon Sep 17 00:00:00 2001 From: William Welling Date: Wed, 3 May 2023 16:29:06 -0500 Subject: [PATCH 34/47] Cleanup console logs --- .../webapp/app/directives/reviewSubmissionFieldsDirective.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js b/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js index a7c271f828..89bfcbd191 100644 --- a/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js +++ b/src/main/webapp/app/directives/reviewSubmissionFieldsDirective.js @@ -56,12 +56,9 @@ vireo.directive('reviewsubmissionsfields', function ($location, InputTypes, Fiel }; $scope.getFile = function (fieldValue) { - console.log(fieldValue); $scope.submission.fileInfo(fieldValue).then(function (data) { - console.log(data); fieldValue.fileInfo = angular.fromJson(data.body).payload.ObjectNode; $scope.submission.file(fieldValue.value).then(function (data) { - console.log(data); saveAs(new Blob([data], { type: fieldValue.fileInfo.type }), fieldValue.fileInfo.name); From 2d89e53a60cb90bf04b8ea45b45cb3f4c8857a57 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 3 May 2023 16:28:11 -0500 Subject: [PATCH 35/47] Issue 1757: Sort Graduation Semester (Month Year Format Dates) as a date type. When sorting as a string, the sort produces unwanted results as described by the issue. Given the current design, it should have been simple to add a CAST to the ORDER BY for the appropriate date field. Several problems make this more complicated than otherwise would be hoped for: 1. The column needed to be changed is a field predicate associated with field_values rather than being a date on submission. 2. Postgresql doesn't cast "Month Year" format to a date. 3. Postgresql doesn't support the specific case of casting on a column in the SELECT clause when DISTINCT is in use. A separate function with documentation is added to explain the situation. When sorting by the Graduation Semester (which is also called "Degree Date"), a new column is added to the SELECT clause to provide the Graduation Semester casted to a date type. The ORDER BY then select his special date column for sorting rather than the original value column. --- .../model/repo/impl/SubmissionRepoImpl.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java index 074e0a3cea..ba12a18fb4 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/SubmissionRepoImpl.java @@ -469,7 +469,11 @@ public int compare(SubmissionListColumn svc1, SubmissionListColumn svc2) { } if (submissionListColumn.getSortOrder() > 0) { - setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " pfv" + n + ".value"); + if (submissionListColumn.getInputType().getName().equals("INPUT_DEGREEDATE")) { + setColumnOrderingForMonthYearDateFormat(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " pfv" + n); + } else { + setColumnOrdering(submissionListColumn.getSort(), sqlSelectBuilder, sqlOrderBysBuilder, " pfv" + n + ".value"); + } } for (String filterString : submissionListColumn.getFilters()) { @@ -1004,6 +1008,35 @@ public void setColumnOrdering(Sort sort, StringBuilder sqlSelectBuilder, StringB } } + /** + * Handle case where Postgresql requires help casting the date string to a date type. + * + * Some SQL engines can directly cast the "Month Year" format to a date but postgresql cannot. + * Because of this limitation in Postgresql, all dates cannot be cast. + * Instead, the "Month Year" formatted data must be handled as an exception case. + * + * This converts the "Month Year" format into a "Month Day, Year" format to make Postgresql happy. + * Then this converts that date resulting string into a date type for proper SQL sorting. + * + * This would also be easier to add the cast on the ORDER BY and not need to add a column in the select clause. + * However, another Postgresql problem prevents this from working when DISTINCT is in use. + * Postgresql will falsely claim that pfv0.value is not in the SELECT clause when it actually is while DISTINCT is present. + * + * @param sort The sort direction. + * @param sqlSelectBuilder The SQL select builder string. + * @param sqlOrderBysBuilder The SQL order by builder string. + * @param table The table to select from when joining on the assumption that the value is "table".value. + */ + public void setColumnOrderingForMonthYearDateFormat(Sort sort, StringBuilder sqlSelectBuilder, StringBuilder sqlOrderBysBuilder, String table) { + if (sort == Sort.ASC || sort == Sort.DESC) { + sqlSelectBuilder + .append(table).append(".value,") + .append(" cast(replace(").append(table).append(".value, ' ', ' 1, ') as date) as").append(table).append("_date,"); + + sqlOrderBysBuilder.append(table).append("_date ").append(sort.name()).append(","); + } + } + @Override protected String getChannel() { return "/channel/submission"; From 7672d8a508757382a8859b08ed1f29c7eb181a16 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 4 May 2023 10:45:23 -0500 Subject: [PATCH 36/47] Revert reset columns on clear filter --- .../app/controllers/submission/submissionListController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/controllers/submission/submissionListController.js b/src/main/webapp/app/controllers/submission/submissionListController.js index 2cb8e2c394..cf1c8edf19 100644 --- a/src/main/webapp/app/controllers/submission/submissionListController.js +++ b/src/main/webapp/app/controllers/submission/submissionListController.js @@ -642,7 +642,7 @@ vireo.controller("SubmissionListController", function (NgTableParams, $controlle $scope.clearFilters = function () { $scope.activeFilters.clearFilters().then(function () { - $scope.resetColumnsToDefault(); + query(); }); }; From 36cb89523afebd01af497608c8f7b16c0afabf18 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 4 May 2023 10:45:54 -0500 Subject: [PATCH 37/47] Replace customize view with two buttons to customize columns and default columns --- .../resources/styles/sass/views/admin/_view.scss | 3 +++ src/main/webapp/app/views/admin/list.html | 14 +++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/resources/styles/sass/views/admin/_view.scss b/src/main/webapp/app/resources/styles/sass/views/admin/_view.scss index ce371266c2..2cb0b007be 100644 --- a/src/main/webapp/app/resources/styles/sass/views/admin/_view.scss +++ b/src/main/webapp/app/resources/styles/sass/views/admin/_view.scss @@ -212,3 +212,6 @@ div .item-view div.row h1 span.spinning { color: #555; } +.list-view-table-controls { + margin-bottom: 5px; +} diff --git a/src/main/webapp/app/views/admin/list.html b/src/main/webapp/app/views/admin/list.html index 9841a38494..5ecafe977c 100644 --- a/src/main/webapp/app/views/admin/list.html +++ b/src/main/webapp/app/views/admin/list.html @@ -5,8 +5,16 @@

List ETDs

-
- Customize view +
+ +
+ + +
@@ -30,7 +38,7 @@

List ETDs

{{getCustomActionLabelById(ca.definition.id)}} -
+
From c5cc5edb02155724d6dcac4806a70ed73358e6c6 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 4 May 2023 10:46:18 -0500 Subject: [PATCH 38/47] Reuse server.port property for convinience --- src/main/resources/application.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 17a9341694..ee87b0aed8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -114,7 +114,7 @@ info: app: - url: http://localhost:9000 + url: http://localhost:${server.port} # value generated from property assets.uri # either defined in pom.xml or via package argument @@ -142,7 +142,7 @@ app: # edu.tamu.weaver.auth.service.CryptoService secret: verysecretsecret # edu.tamu.weaver.filter.CorsFilter - allow-access: http://localhost:9000 + allow-access: http://localhost:${server.port} # edu.tamu.weaver.email.config.WeaverEmailConfig email: From 9acdc8c919a2cb7702aaf1247953a9fbb904c466 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 4 May 2023 10:52:35 -0500 Subject: [PATCH 39/47] Trying to handle unnecessary merge conflict --- src/main/webapp/app/views/admin/list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/views/admin/list.html b/src/main/webapp/app/views/admin/list.html index 5ecafe977c..39c86c64ac 100644 --- a/src/main/webapp/app/views/admin/list.html +++ b/src/main/webapp/app/views/admin/list.html @@ -5,7 +5,7 @@

List ETDs

-
+