From e1ca85c7460dcef2b1dd417e98b25c9d2d9ca894 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 23 Jan 2024 14:08:01 -0600 Subject: [PATCH 1/4] CE-798 - Add calls to supplementalTableMetaData.validate; move UnsafeLambda out of here to utils.lambdas package --- .../core/instances/QInstanceValidator.java | 21 ++++------- .../tables/QSupplementalTableMetaData.java | 13 +++++++ .../core/utils/lambdas/UnsafeLambda.java | 37 +++++++++++++++++++ 3 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/lambdas/UnsafeLambda.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java index 725b9c4d..8d901b30 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java @@ -75,6 +75,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.AssociatedScript; import com.kingsrook.qqq.backend.core.model.metadata.tables.Association; import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin; import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QSupplementalTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.Tier; import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey; @@ -86,6 +87,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.cache.CacheUseCase; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.ValueUtils; +import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeLambda; /******************************************************************************* @@ -492,6 +494,11 @@ public class QInstanceValidator validateTableRecordSecurityLocks(qInstance, table); validateTableAssociations(qInstance, table); validateExposedJoins(qInstance, joinGraph, table); + + for(QSupplementalTableMetaData supplementalTableMetaData : CollectionUtils.nonNullMap(table.getSupplementalMetaData()).values()) + { + supplementalTableMetaData.validate(qInstance, table, this); + } }); } } @@ -1765,20 +1772,6 @@ public class QInstanceValidator - /******************************************************************************* - ** - *******************************************************************************/ - @FunctionalInterface - interface UnsafeLambda - { - /******************************************************************************* - ** - *******************************************************************************/ - void run() throws Exception; - } - - - /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QSupplementalTableMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QSupplementalTableMetaData.java index d0dc48e4..6c36388b 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QSupplementalTableMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/QSupplementalTableMetaData.java @@ -22,6 +22,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.tables; +import com.kingsrook.qqq.backend.core.instances.QInstanceValidator; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; @@ -69,4 +70,16 @@ public abstract class QSupplementalTableMetaData // noop in base class // //////////////////////// } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public void validate(QInstance qInstance, QTableMetaData tableMetaData, QInstanceValidator qInstanceValidator) + { + //////////////////////// + // noop in base class // + //////////////////////// + } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/lambdas/UnsafeLambda.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/lambdas/UnsafeLambda.java new file mode 100644 index 00000000..f74ba61e --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/lambdas/UnsafeLambda.java @@ -0,0 +1,37 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2022. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.utils.lambdas; + + +/******************************************************************************* + ** + *******************************************************************************/ +@FunctionalInterface +public interface UnsafeLambda +{ + + /******************************************************************************* + ** + *******************************************************************************/ + void run() throws Exception; + +} From 0dd7f5e1d2ef6b0851eaf2867da7b19caf437ca7 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 30 Jan 2024 09:34:13 -0600 Subject: [PATCH 2/4] CE-793 - rename saved-filter to saved-view; add check for duplicate names (on insert & rename) in save process. --- .../core/model/automation/TableTrigger.java | 4 +- .../SavedView.java} | 41 ++-- .../SavedViewsMetaDataProvider.java} | 47 +++-- .../DeleteSavedViewProcess.java} | 24 +-- .../QuerySavedViewProcess.java} | 34 ++-- .../StoreSavedViewProcess.java} | 82 ++++++-- .../savedfilters/SavedFilterProcessTests.java | 143 ------------- .../savedviews/SavedViewProcessTests.java | 189 ++++++++++++++++++ 8 files changed, 330 insertions(+), 234 deletions(-) rename qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/{savedfilters/SavedFilter.java => savedviews/SavedView.java} (89%) rename qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/{savedfilters/SavedFiltersMetaDataProvider.java => savedviews/SavedViewsMetaDataProvider.java} (60%) rename qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/{savedfilters/DeleteSavedFilterProcess.java => savedviews/DeleteSavedViewProcess.java} (82%) rename qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/{savedfilters/QuerySavedFilterProcess.java => savedviews/QuerySavedViewProcess.java} (81%) rename qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/{savedfilters/StoreSavedFilterProcess.java => savedviews/StoreSavedViewProcess.java} (55%) delete mode 100644 qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/SavedFilterProcessTests.java create mode 100644 qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/SavedViewProcessTests.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/automation/TableTrigger.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/automation/TableTrigger.java index a3c82b4f..e8b04e65 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/automation/TableTrigger.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/automation/TableTrigger.java @@ -28,7 +28,7 @@ import com.kingsrook.qqq.backend.core.model.data.QField; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecordEntity; import com.kingsrook.qqq.backend.core.model.metadata.tables.TablesPossibleValueSourceMetaDataProvider; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFilter; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedView; import com.kingsrook.qqq.backend.core.model.scripts.Script; @@ -51,7 +51,7 @@ public class TableTrigger extends QRecordEntity @QField(possibleValueSourceName = TablesPossibleValueSourceMetaDataProvider.NAME) private String tableName; - @QField(possibleValueSourceName = SavedFilter.TABLE_NAME) + @QField(possibleValueSourceName = SavedView.TABLE_NAME) private Integer filterId; @QField(possibleValueSourceName = Script.TABLE_NAME) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedfilters/SavedFilter.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedView.java similarity index 89% rename from qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedfilters/SavedFilter.java rename to qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedView.java index 9263b5d5..fe382185 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedfilters/SavedFilter.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedView.java @@ -1,6 +1,6 @@ /* * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2023. Kingsrook, LLC + * Copyright (C) 2021-2024. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -package com.kingsrook.qqq.backend.core.model.savedfilters; +package com.kingsrook.qqq.backend.core.model.savedviews; import java.time.Instant; @@ -32,9 +32,9 @@ import com.kingsrook.qqq.backend.core.model.data.QRecordEntity; /******************************************************************************* ** Entity bean for the saved filter table *******************************************************************************/ -public class SavedFilter extends QRecordEntity +public class SavedView extends QRecordEntity { - public static final String TABLE_NAME = "savedFilter"; + public static final String TABLE_NAME = "savedView"; @QField(isEditable = false) private Integer id; @@ -55,7 +55,7 @@ public class SavedFilter extends QRecordEntity private String userId; @QField(isEditable = false) - private String filterJson; + private String viewJson; @@ -63,7 +63,7 @@ public class SavedFilter extends QRecordEntity ** Constructor ** *******************************************************************************/ - public SavedFilter() + public SavedView() { } @@ -73,7 +73,7 @@ public class SavedFilter extends QRecordEntity ** Constructor ** *******************************************************************************/ - public SavedFilter(QRecord qRecord) throws QException + public SavedView(QRecord qRecord) throws QException { populateFromQRecord(qRecord); } @@ -172,7 +172,7 @@ public class SavedFilter extends QRecordEntity ** Fluent setter for label ** *******************************************************************************/ - public SavedFilter withLabel(String label) + public SavedView withLabel(String label) { this.label = label; return (this); @@ -206,7 +206,7 @@ public class SavedFilter extends QRecordEntity ** Fluent setter for tableName ** *******************************************************************************/ - public SavedFilter withTableName(String tableName) + public SavedView withTableName(String tableName) { this.tableName = tableName; return (this); @@ -240,7 +240,7 @@ public class SavedFilter extends QRecordEntity ** Fluent setter for userId ** *******************************************************************************/ - public SavedFilter withUserId(String userId) + public SavedView withUserId(String userId) { this.userId = userId; return (this); @@ -249,34 +249,31 @@ public class SavedFilter extends QRecordEntity /******************************************************************************* - ** Getter for filterJson - ** + ** Getter for viewJson *******************************************************************************/ - public String getFilterJson() + public String getViewJson() { - return filterJson; + return (this.viewJson); } /******************************************************************************* - ** Setter for filterJson - ** + ** Setter for viewJson *******************************************************************************/ - public void setFilterJson(String filterJson) + public void setViewJson(String viewJson) { - this.filterJson = filterJson; + this.viewJson = viewJson; } /******************************************************************************* - ** Fluent setter for filterJson - ** + ** Fluent setter for viewJson *******************************************************************************/ - public SavedFilter withFilterJson(String filterJson) + public SavedView withViewJson(String viewJson) { - this.filterJson = filterJson; + this.viewJson = viewJson; return (this); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedfilters/SavedFiltersMetaDataProvider.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java similarity index 60% rename from qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedfilters/SavedFiltersMetaDataProvider.java rename to qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java index 0347db77..47edc611 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedfilters/SavedFiltersMetaDataProvider.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java @@ -1,6 +1,6 @@ /* * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2022. Kingsrook, LLC + * Copyright (C) 2021-2024. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ @@ -19,25 +19,31 @@ * along with this program. If not, see . */ -package com.kingsrook.qqq.backend.core.model.savedfilters; +package com.kingsrook.qqq.backend.core.model.savedviews; +import java.util.List; import java.util.function.Consumer; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType; +import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment; +import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PVSValueFormatAndFields; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; -import com.kingsrook.qqq.backend.core.processes.implementations.savedfilters.DeleteSavedFilterProcess; -import com.kingsrook.qqq.backend.core.processes.implementations.savedfilters.QuerySavedFilterProcess; -import com.kingsrook.qqq.backend.core.processes.implementations.savedfilters.StoreSavedFilterProcess; +import com.kingsrook.qqq.backend.core.model.metadata.tables.Tier; +import com.kingsrook.qqq.backend.core.processes.implementations.savedviews.DeleteSavedViewProcess; +import com.kingsrook.qqq.backend.core.processes.implementations.savedviews.QuerySavedViewProcess; +import com.kingsrook.qqq.backend.core.processes.implementations.savedviews.StoreSavedViewProcess; /******************************************************************************* ** *******************************************************************************/ -public class SavedFiltersMetaDataProvider +public class SavedViewsMetaDataProvider { @@ -46,11 +52,11 @@ public class SavedFiltersMetaDataProvider *******************************************************************************/ public void defineAll(QInstance instance, String backendName, Consumer backendDetailEnricher) throws QException { - instance.addTable(defineSavedFilterTable(backendName, backendDetailEnricher)); - instance.addPossibleValueSource(defineSavedFilterPossibleValueSource()); - instance.addProcess(QuerySavedFilterProcess.getProcessMetaData()); - instance.addProcess(StoreSavedFilterProcess.getProcessMetaData()); - instance.addProcess(DeleteSavedFilterProcess.getProcessMetaData()); + instance.addTable(defineSavedViewTable(backendName, backendDetailEnricher)); + instance.addPossibleValueSource(defineSavedViewPossibleValueSource()); + instance.addProcess(QuerySavedViewProcess.getProcessMetaData()); + instance.addProcess(StoreSavedViewProcess.getProcessMetaData()); + instance.addProcess(DeleteSavedViewProcess.getProcessMetaData()); } @@ -58,16 +64,21 @@ public class SavedFiltersMetaDataProvider /******************************************************************************* ** *******************************************************************************/ - private QTableMetaData defineSavedFilterTable(String backendName, Consumer backendDetailEnricher) throws QException + private QTableMetaData defineSavedViewTable(String backendName, Consumer backendDetailEnricher) throws QException { QTableMetaData table = new QTableMetaData() - .withName(SavedFilter.TABLE_NAME) - .withLabel("Saved Filter") + .withName(SavedView.TABLE_NAME) + .withLabel("Saved View") .withRecordLabelFormat("%s") .withRecordLabelFields("label") .withBackendName(backendName) .withPrimaryKeyField("id") - .withFieldsFromEntity(SavedFilter.class); + .withFieldsFromEntity(SavedView.class) + .withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "label"))) + .withSection(new QFieldSection("data", new QIcon().withName("text_snippet"), Tier.T2, List.of("userId", "tableName", "viewJson"))) + .withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate"))); + + table.getField("viewJson").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR).withValue(AdornmentType.CodeEditorValues.languageMode("json"))); if(backendDetailEnricher != null) { @@ -82,12 +93,12 @@ public class SavedFiltersMetaDataProvider /******************************************************************************* ** *******************************************************************************/ - private QPossibleValueSource defineSavedFilterPossibleValueSource() + private QPossibleValueSource defineSavedViewPossibleValueSource() { return new QPossibleValueSource() - .withName(SavedFilter.TABLE_NAME) + .withName(SavedView.TABLE_NAME) .withType(QPossibleValueSourceType.TABLE) - .withTableName(SavedFilter.TABLE_NAME) + .withTableName(SavedView.TABLE_NAME) .withValueFormatAndFields(PVSValueFormatAndFields.LABEL_ONLY) .withOrderByField("label"); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/DeleteSavedFilterProcess.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/DeleteSavedViewProcess.java similarity index 82% rename from qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/DeleteSavedFilterProcess.java rename to qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/DeleteSavedViewProcess.java index a0a6f1f8..8ff2fc06 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/DeleteSavedFilterProcess.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/DeleteSavedViewProcess.java @@ -1,6 +1,6 @@ /* * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2023. Kingsrook, LLC + * Copyright (C) 2021-2024. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -package com.kingsrook.qqq.backend.core.processes.implementations.savedfilters; +package com.kingsrook.qqq.backend.core.processes.implementations.savedviews; import java.util.List; @@ -34,15 +34,15 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFilter; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedView; /******************************************************************************* - ** Process used by the delete filter dialog + ** Process used by the delete view dialog *******************************************************************************/ -public class DeleteSavedFilterProcess implements BackendStep +public class DeleteSavedViewProcess implements BackendStep { - private static final QLogger LOG = QLogger.getLogger(DeleteSavedFilterProcess.class); + private static final QLogger LOG = QLogger.getLogger(DeleteSavedViewProcess.class); @@ -52,10 +52,10 @@ public class DeleteSavedFilterProcess implements BackendStep public static QProcessMetaData getProcessMetaData() { return (new QProcessMetaData() - .withName("deleteSavedFilter") + .withName("deleteSavedView") .withStepList(List.of( new QBackendStepMetaData() - .withCode(new QCodeReference(DeleteSavedFilterProcess.class)) + .withCode(new QCodeReference(DeleteSavedViewProcess.class)) .withName("delete") ))); } @@ -72,16 +72,16 @@ public class DeleteSavedFilterProcess implements BackendStep try { - Integer savedFilterId = runBackendStepInput.getValueInteger("id"); + Integer savedViewId = runBackendStepInput.getValueInteger("id"); DeleteInput input = new DeleteInput(); - input.setTableName(SavedFilter.TABLE_NAME); - input.setPrimaryKeys(List.of(savedFilterId)); + input.setTableName(SavedView.TABLE_NAME); + input.setPrimaryKeys(List.of(savedViewId)); new DeleteAction().execute(input); } catch(Exception e) { - LOG.warn("Error deleting saved filter", e); + LOG.warn("Error deleting saved view", e); throw (e); } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/QuerySavedFilterProcess.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/QuerySavedViewProcess.java similarity index 81% rename from qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/QuerySavedFilterProcess.java rename to qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/QuerySavedViewProcess.java index dc50ed17..f4f57516 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/QuerySavedFilterProcess.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/QuerySavedViewProcess.java @@ -1,6 +1,6 @@ /* * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2023. Kingsrook, LLC + * Copyright (C) 2021-2024. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ @@ -19,7 +19,7 @@ * along with this program. If not, see . */ -package com.kingsrook.qqq.backend.core.processes.implementations.savedfilters; +package com.kingsrook.qqq.backend.core.processes.implementations.savedviews; import java.io.Serializable; @@ -43,15 +43,15 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFilter; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedView; /******************************************************************************* - ** Process used by the saved filter dialogs + ** Process used by the saved view dialogs *******************************************************************************/ -public class QuerySavedFilterProcess implements BackendStep +public class QuerySavedViewProcess implements BackendStep { - private static final QLogger LOG = QLogger.getLogger(QuerySavedFilterProcess.class); + private static final QLogger LOG = QLogger.getLogger(QuerySavedViewProcess.class); @@ -61,10 +61,10 @@ public class QuerySavedFilterProcess implements BackendStep public static QProcessMetaData getProcessMetaData() { return (new QProcessMetaData() - .withName("querySavedFilter") + .withName("querySavedView") .withStepList(List.of( new QBackendStepMetaData() - .withCode(new QCodeReference(QuerySavedFilterProcess.class)) + .withCode(new QCodeReference(QuerySavedViewProcess.class)) .withName("query") ))); } @@ -81,36 +81,36 @@ public class QuerySavedFilterProcess implements BackendStep try { - Integer savedFilterId = runBackendStepInput.getValueInteger("id"); - if(savedFilterId != null) + Integer savedViewId = runBackendStepInput.getValueInteger("id"); + if(savedViewId != null) { GetInput input = new GetInput(); - input.setTableName(SavedFilter.TABLE_NAME); - input.setPrimaryKey(savedFilterId); + input.setTableName(SavedView.TABLE_NAME); + input.setPrimaryKey(savedViewId); GetOutput output = new GetAction().execute(input); runBackendStepOutput.addRecord(output.getRecord()); - runBackendStepOutput.addValue("savedFilter", output.getRecord()); - runBackendStepOutput.addValue("savedFilterList", (Serializable) List.of(output.getRecord())); + runBackendStepOutput.addValue("savedView", output.getRecord()); + runBackendStepOutput.addValue("savedViewList", (Serializable) List.of(output.getRecord())); } else { String tableName = runBackendStepInput.getValueString("tableName"); QueryInput input = new QueryInput(); - input.setTableName(SavedFilter.TABLE_NAME); + input.setTableName(SavedView.TABLE_NAME); input.setFilter(new QQueryFilter() .withCriteria(new QFilterCriteria("tableName", QCriteriaOperator.EQUALS, tableName)) .withOrderBy(new QFilterOrderBy("label"))); QueryOutput output = new QueryAction().execute(input); runBackendStepOutput.setRecords(output.getRecords()); - runBackendStepOutput.addValue("savedFilterList", (Serializable) output.getRecords()); + runBackendStepOutput.addValue("savedViewList", (Serializable) output.getRecords()); } } catch(Exception e) { - LOG.warn("Error deleting saved filter", e); + LOG.warn("Error querying for saved views", e); throw (e); } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/StoreSavedFilterProcess.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/StoreSavedViewProcess.java similarity index 55% rename from qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/StoreSavedFilterProcess.java rename to qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/StoreSavedViewProcess.java index 37bc167e..26974f55 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/StoreSavedFilterProcess.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/StoreSavedViewProcess.java @@ -1,6 +1,6 @@ /* * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2023. Kingsrook, LLC + * Copyright (C) 2021-2024. Kingsrook, LLC * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States * contact@kingsrook.com * https://github.com/Kingsrook/ @@ -19,37 +19,45 @@ * along with this program. If not, see . */ -package com.kingsrook.qqq.backend.core.processes.implementations.savedfilters; +package com.kingsrook.qqq.backend.core.processes.implementations.savedviews; import java.io.Serializable; -import java.util.ArrayList; import java.util.List; import com.kingsrook.qqq.backend.core.actions.ActionHelper; import com.kingsrook.qqq.backend.core.actions.processes.BackendStep; import com.kingsrook.qqq.backend.core.actions.tables.InsertAction; +import com.kingsrook.qqq.backend.core.actions.tables.QueryAction; import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction; +import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException; import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput; import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFilter; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedView; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; /******************************************************************************* - ** Process used by the saved filter dialog + ** Process used by the saved view dialog *******************************************************************************/ -public class StoreSavedFilterProcess implements BackendStep +public class StoreSavedViewProcess implements BackendStep { - private static final QLogger LOG = QLogger.getLogger(StoreSavedFilterProcess.class); + private static final QLogger LOG = QLogger.getLogger(StoreSavedViewProcess.class); @@ -59,10 +67,10 @@ public class StoreSavedFilterProcess implements BackendStep public static QProcessMetaData getProcessMetaData() { return (new QProcessMetaData() - .withName("storeSavedFilter") + .withName("storeSavedView") .withStepList(List.of( new QBackendStepMetaData() - .withCode(new QCodeReference(StoreSavedFilterProcess.class)) + .withCode(new QCodeReference(StoreSavedViewProcess.class)) .withName("store") ))); } @@ -79,39 +87,73 @@ public class StoreSavedFilterProcess implements BackendStep try { + String userId = QContext.getQSession().getUser().getIdReference(); + String tableName = runBackendStepInput.getValueString("tableName"); + String label = runBackendStepInput.getValueString("label"); + QRecord qRecord = new QRecord() .withValue("id", runBackendStepInput.getValueInteger("id")) - .withValue("label", runBackendStepInput.getValueString("label")) - .withValue("tableName", runBackendStepInput.getValueString("tableName")) - .withValue("filterJson", runBackendStepInput.getValueString("filterJson")) - .withValue("userId", runBackendStepInput.getSession().getUser().getIdReference()); + .withValue("viewJson", runBackendStepInput.getValueString("viewJson")) + .withValue("label", label) + .withValue("tableName", tableName) + .withValue("userId", userId); - List savedFilterList = new ArrayList<>(); + List savedViewList; if(qRecord.getValueInteger("id") == null) { + checkForDuplicates(userId, tableName, label, null); + InsertInput input = new InsertInput(); - input.setTableName(SavedFilter.TABLE_NAME); + input.setTableName(SavedView.TABLE_NAME); input.setRecords(List.of(qRecord)); InsertOutput output = new InsertAction().execute(input); - savedFilterList = output.getRecords(); + savedViewList = output.getRecords(); } else { + checkForDuplicates(userId, tableName, label, qRecord.getValueInteger("id")); + UpdateInput input = new UpdateInput(); - input.setTableName(SavedFilter.TABLE_NAME); + input.setTableName(SavedView.TABLE_NAME); input.setRecords(List.of(qRecord)); UpdateOutput output = new UpdateAction().execute(input); - savedFilterList = output.getRecords(); + savedViewList = output.getRecords(); } - runBackendStepOutput.addValue("savedFilterList", (Serializable) savedFilterList); + runBackendStepOutput.addValue("savedViewList", (Serializable) savedViewList); } catch(Exception e) { - LOG.warn("Error storing data saved filter", e); + LOG.warn("Error storing saved view", e); throw (e); } } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private static void checkForDuplicates(String userId, String tableName, String label, Integer id) throws QException + { + QueryInput queryInput = new QueryInput(); + queryInput.setTableName(SavedView.TABLE_NAME); + queryInput.setFilter(new QQueryFilter( + new QFilterCriteria("userId", QCriteriaOperator.EQUALS, userId), + new QFilterCriteria("tableName", QCriteriaOperator.EQUALS, tableName), + new QFilterCriteria("label", QCriteriaOperator.EQUALS, label))); + + if(id != null) + { + queryInput.getFilter().addCriteria(new QFilterCriteria("id", QCriteriaOperator.NOT_EQUALS, id)); + } + + QueryOutput queryOutput = new QueryAction().execute(queryInput); + if(CollectionUtils.nullSafeHasContents(queryOutput.getRecords())) + { + throw (new QUserFacingException("You already have a saved view on this table with this name.")); + } + } } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/SavedFilterProcessTests.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/SavedFilterProcessTests.java deleted file mode 100644 index d3c0bf5b..00000000 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedfilters/SavedFilterProcessTests.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * QQQ - Low-code Application Framework for Engineers. - * Copyright (C) 2021-2023. Kingsrook, LLC - * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States - * contact@kingsrook.com - * https://github.com/Kingsrook/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package com.kingsrook.qqq.backend.core.processes.implementations.savedfilters; - - -import java.util.List; -import com.kingsrook.qqq.backend.core.BaseTest; -import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction; -import com.kingsrook.qqq.backend.core.context.QContext; -import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput; -import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator; -import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria; -import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; -import com.kingsrook.qqq.backend.core.model.data.QRecord; -import com.kingsrook.qqq.backend.core.model.metadata.QInstance; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFiltersMetaDataProvider; -import com.kingsrook.qqq.backend.core.utils.JsonUtils; -import com.kingsrook.qqq.backend.core.utils.TestUtils; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - - -/******************************************************************************* - ** Unit test for all saved filter processes - *******************************************************************************/ -class SavedFilterProcessTests extends BaseTest -{ - - /******************************************************************************* - ** - *******************************************************************************/ - @Test - void test() throws QException - { - QInstance qInstance = QContext.getQInstance(); - new SavedFiltersMetaDataProvider().defineAll(qInstance, TestUtils.MEMORY_BACKEND_NAME, null); - String tableName = TestUtils.TABLE_NAME_PERSON_MEMORY; - - { - /////////////////////////////////////////// - // query - should be no filters to start // - /////////////////////////////////////////// - RunProcessInput runProcessInput = new RunProcessInput(); - runProcessInput.setProcessName(QuerySavedFilterProcess.getProcessMetaData().getName()); - runProcessInput.addValue("tableName", tableName); - RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); - assertEquals(0, ((List) runProcessOutput.getValues().get("savedFilterList")).size()); - } - - Integer savedFilterId; - { - //////////////////////// - // store a new filter // - //////////////////////// - RunProcessInput runProcessInput = new RunProcessInput(); - runProcessInput.setProcessName(StoreSavedFilterProcess.getProcessMetaData().getName()); - runProcessInput.addValue("label", "My Filter"); - runProcessInput.addValue("tableName", tableName); - runProcessInput.addValue("filterJson", JsonUtils.toJson(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.EQUALS, 47)))); - RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); - List savedFilterList = (List) runProcessOutput.getValues().get("savedFilterList"); - assertEquals(1, savedFilterList.size()); - savedFilterId = savedFilterList.get(0).getValueInteger("id"); - assertNotNull(savedFilterId); - } - - { - //////////////////////////////////// - // query - should find our filter // - //////////////////////////////////// - RunProcessInput runProcessInput = new RunProcessInput(); - runProcessInput.setProcessName(QuerySavedFilterProcess.getProcessMetaData().getName()); - runProcessInput.addValue("tableName", tableName); - RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); - List savedFilterList = (List) runProcessOutput.getValues().get("savedFilterList"); - assertEquals(1, savedFilterList.size()); - assertEquals(1, savedFilterList.get(0).getValueInteger("id")); - assertEquals("My Filter", savedFilterList.get(0).getValueString("label")); - } - - { - /////////////////////// - // update our filter // - /////////////////////// - RunProcessInput runProcessInput = new RunProcessInput(); - runProcessInput.setProcessName(StoreSavedFilterProcess.getProcessMetaData().getName()); - runProcessInput.addValue("id", savedFilterId); - runProcessInput.addValue("label", "My Updated Filter"); - runProcessInput.addValue("tableName", tableName); - runProcessInput.addValue("filterJson", JsonUtils.toJson(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.EQUALS, 47)))); - RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); - List savedFilterList = (List) runProcessOutput.getValues().get("savedFilterList"); - assertEquals(1, savedFilterList.size()); - assertEquals(1, savedFilterList.get(0).getValueInteger("id")); - assertEquals("My Updated Filter", savedFilterList.get(0).getValueString("label")); - } - - { - /////////////////////// - // delete our filter // - /////////////////////// - RunProcessInput runProcessInput = new RunProcessInput(); - runProcessInput.setProcessName(DeleteSavedFilterProcess.getProcessMetaData().getName()); - runProcessInput.addValue("id", savedFilterId); - RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); - } - - { - //////////////////////////////////////// - // query - should be no filters again // - //////////////////////////////////////// - RunProcessInput runProcessInput = new RunProcessInput(); - runProcessInput.setProcessName(QuerySavedFilterProcess.getProcessMetaData().getName()); - runProcessInput.addValue("tableName", tableName); - RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); - assertEquals(0, ((List) runProcessOutput.getValues().get("savedFilterList")).size()); - } - - } - -} \ No newline at end of file diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/SavedViewProcessTests.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/SavedViewProcessTests.java new file mode 100644 index 00000000..f4474bef --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/processes/implementations/savedviews/SavedViewProcessTests.java @@ -0,0 +1,189 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.processes.implementations.savedviews; + + +import java.util.List; +import com.kingsrook.qqq.backend.core.BaseTest; +import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction; +import com.kingsrook.qqq.backend.core.context.QContext; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria; +import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; +import com.kingsrook.qqq.backend.core.model.data.QRecord; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedViewsMetaDataProvider; +import com.kingsrook.qqq.backend.core.utils.JsonUtils; +import com.kingsrook.qqq.backend.core.utils.TestUtils; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +/******************************************************************************* + ** Unit test for all saved view processes + *******************************************************************************/ +class SavedViewProcessTests extends BaseTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test() throws QException + { + QInstance qInstance = QContext.getQInstance(); + new SavedViewsMetaDataProvider().defineAll(qInstance, TestUtils.MEMORY_BACKEND_NAME, null); + String tableName = TestUtils.TABLE_NAME_PERSON_MEMORY; + + { + ///////////////////////////////////////// + // query - should be no views to start // + ///////////////////////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(QuerySavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("tableName", tableName); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + assertEquals(0, ((List) runProcessOutput.getValues().get("savedViewList")).size()); + } + + Integer savedViewId; + { + ////////////////////// + // store a new view // + ////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(StoreSavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("label", "My View"); + runProcessInput.addValue("tableName", tableName); + runProcessInput.addValue("viewJson", JsonUtils.toJson(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.EQUALS, 47)))); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + List savedViewList = (List) runProcessOutput.getValues().get("savedViewList"); + assertEquals(1, savedViewList.size()); + savedViewId = savedViewList.get(0).getValueInteger("id"); + assertNotNull(savedViewId); + + ////////////////////////////////////////////////////////////////// + // try to store it again - should throw a "duplicate" exception // + ////////////////////////////////////////////////////////////////// + assertThatThrownBy(() -> new RunProcessAction().execute(runProcessInput)) + .isInstanceOf(QUserFacingException.class) + .hasMessageContaining("already have a saved view"); + } + + { + /////////////////////////////////// + // query - should find our views // + /////////////////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(QuerySavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("tableName", tableName); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + List savedViewList = (List) runProcessOutput.getValues().get("savedViewList"); + assertEquals(1, savedViewList.size()); + assertEquals(1, savedViewList.get(0).getValueInteger("id")); + assertEquals("My View", savedViewList.get(0).getValueString("label")); + } + + { + ///////////////////// + // update our view // + ///////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(StoreSavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("id", savedViewId); + runProcessInput.addValue("label", "My Updated View"); + runProcessInput.addValue("tableName", tableName); + runProcessInput.addValue("viewJson", JsonUtils.toJson(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.EQUALS, 47)))); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + List savedViewList = (List) runProcessOutput.getValues().get("savedViewList"); + assertEquals(1, savedViewList.size()); + assertEquals(1, savedViewList.get(0).getValueInteger("id")); + assertEquals("My Updated View", savedViewList.get(0).getValueString("label")); + } + + Integer anotherSavedViewId; + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // store a second one w/ different name (will be used below in update-dupe-check use-case) // + ///////////////////////////////////////////////////////////////////////////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(StoreSavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("label", "My Second View"); + runProcessInput.addValue("tableName", tableName); + runProcessInput.addValue("viewJson", JsonUtils.toJson(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.EQUALS, 47)))); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + List savedViewList = (List) runProcessOutput.getValues().get("savedViewList"); + anotherSavedViewId = savedViewList.get(0).getValueInteger("id"); + } + + { + ///////////////////////////////////////////////// + // try to rename the second to match the first // + ///////////////////////////////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(StoreSavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("id", anotherSavedViewId); + runProcessInput.addValue("label", "My Updated View"); + runProcessInput.addValue("tableName", tableName); + runProcessInput.addValue("viewJson", JsonUtils.toJson(new QQueryFilter(new QFilterCriteria("id", QCriteriaOperator.EQUALS, 47)))); + + ////////////////////////////////////////// + // should throw a "duplicate" exception // + ////////////////////////////////////////// + assertThatThrownBy(() -> new RunProcessAction().execute(runProcessInput)) + .isInstanceOf(QUserFacingException.class) + .hasMessageContaining("already have a saved view"); + } + + { + ////////////////////// + // delete our views // + ////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(DeleteSavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("id", savedViewId); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + + runProcessInput.addValue("id", anotherSavedViewId); + runProcessOutput = new RunProcessAction().execute(runProcessInput); + } + + { + ////////////////////////////////////// + // query - should be no views again // + ////////////////////////////////////// + RunProcessInput runProcessInput = new RunProcessInput(); + runProcessInput.setProcessName(QuerySavedViewProcess.getProcessMetaData().getName()); + runProcessInput.addValue("tableName", tableName); + RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput); + assertEquals(0, ((List) runProcessOutput.getValues().get("savedViewList")).size()); + } + + } + +} \ No newline at end of file From 18e1852ce49b9504c9581f32c5a24bae3d99b913 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 30 Jan 2024 09:45:46 -0600 Subject: [PATCH 3/4] CE-793 - rename saved-filter to saved-view in tests --- .../polling/PollingAutomationPerTableRunner.java | 11 +++++++---- .../com/kingsrook/qqq/backend/javalin/TestUtils.java | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java index bf411630..88602fc4 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java @@ -65,13 +65,14 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.Automatio import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.QTableAutomationDetails; import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.TableAutomationAction; import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.TriggerEvent; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFilter; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedView; import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder; import org.apache.commons.lang.NotImplementedException; +import org.json.JSONObject; import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; @@ -388,13 +389,15 @@ public class PollingAutomationPerTableRunner implements Runnable if(filterId != null) { GetInput getInput = new GetInput(); - getInput.setTableName(SavedFilter.TABLE_NAME); + getInput.setTableName(SavedView.TABLE_NAME); getInput.setPrimaryKey(filterId); GetOutput getOutput = new GetAction().execute(getInput); if(getOutput.getRecord() != null) { - SavedFilter savedFilter = new SavedFilter(getOutput.getRecord()); - filter = JsonUtils.toObject(savedFilter.getFilterJson(), QQueryFilter.class); + SavedView savedView = new SavedView(getOutput.getRecord()); + JSONObject viewJson = new JSONObject(savedView.getViewJson()); + JSONObject queryFilter = viewJson.getJSONObject("queryFilter"); + filter = JsonUtils.toObject(queryFilter.toString(), QQueryFilter.class); } } diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java index 0245e235..430f72ae 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java @@ -66,7 +66,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView; import com.kingsrook.qqq.backend.core.model.metadata.reporting.ReportType; import com.kingsrook.qqq.backend.core.model.metadata.tables.AssociatedScript; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; -import com.kingsrook.qqq.backend.core.model.savedfilters.SavedFiltersMetaDataProvider; +import com.kingsrook.qqq.backend.core.model.savedviews.SavedViewsMetaDataProvider; import com.kingsrook.qqq.backend.core.model.scripts.ScriptsMetaDataProvider; import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep; import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; @@ -157,7 +157,7 @@ public class TestUtils qInstance.addBackend(defineMemoryBackend()); try { - new SavedFiltersMetaDataProvider().defineAll(qInstance, defineMemoryBackend().getName(), null); + new SavedViewsMetaDataProvider().defineAll(qInstance, defineMemoryBackend().getName(), null); new ScriptsMetaDataProvider().defineAll(qInstance, defineMemoryBackend().getName(), null); } catch(Exception e) From 459510bba4b53f51987374c60aa5039ac49b0116 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 30 Jan 2024 15:08:47 -0600 Subject: [PATCH 4/4] CE-793 - make defineSavedViewTable public --- .../core/model/savedviews/SavedViewsMetaDataProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java index 47edc611..2581e67d 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedviews/SavedViewsMetaDataProvider.java @@ -64,7 +64,7 @@ public class SavedViewsMetaDataProvider /******************************************************************************* ** *******************************************************************************/ - private QTableMetaData defineSavedViewTable(String backendName, Consumer backendDetailEnricher) throws QException + public QTableMetaData defineSavedViewTable(String backendName, Consumer backendDetailEnricher) throws QException { QTableMetaData table = new QTableMetaData() .withName(SavedView.TABLE_NAME)