Updating to support possible value searching

This commit is contained in:
2022-10-10 16:42:49 -05:00
parent 262038bc87
commit c43a8998ec
16 changed files with 1312 additions and 25 deletions

View File

@ -28,6 +28,7 @@ import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@ -46,6 +47,7 @@ import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
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.actions.values.SearchPossibleValueSourceAction;
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
import com.kingsrook.qqq.backend.core.exceptions.QAuthenticationException;
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
@ -76,10 +78,13 @@ 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.actions.values.SearchPossibleValueSourceInput;
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceOutput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
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.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.session.QSession;
import com.kingsrook.qqq.backend.core.modules.authentication.Auth0AuthenticationModule;
@ -277,6 +282,7 @@ public class QJavalinImplementation
get("/count", QJavalinImplementation::dataCount);
get("/export", QJavalinImplementation::dataExportWithoutFilename);
get("/export/{filename}", QJavalinImplementation::dataExportWithFilename);
get("/possibleValues/{fieldName}", QJavalinImplementation::possibleValues);
// todo - add put and/or patch at this level (without a primaryKey) to do a bulk update based on primaryKeys in the records.
path("/{primaryKey}", () ->
@ -864,6 +870,64 @@ public class QJavalinImplementation
/*******************************************************************************
**
*******************************************************************************/
private static void possibleValues(Context context)
{
try
{
String tableName = context.pathParam("table");
String fieldName = context.pathParam("fieldName");
String searchTerm = context.queryParam("searchTerm");
String ids = context.queryParam("ids");
QTableMetaData table = qInstance.getTable(tableName);
if(table == null)
{
throw (new QNotFoundException("Could not find table named " + tableName + " in this instance."));
}
QFieldMetaData field;
try
{
field = table.getField(fieldName);
}
catch(Exception e)
{
throw (new QNotFoundException("Could not find field named " + fieldName + " in table " + tableName + "."));
}
if(!StringUtils.hasContent(field.getPossibleValueSourceName()))
{
throw (new QNotFoundException("Field " + fieldName + " in table " + tableName + " is not associated with a possible value source."));
}
SearchPossibleValueSourceInput input = new SearchPossibleValueSourceInput(qInstance);
setupSession(context, input);
input.setPossibleValueSourceName(field.getPossibleValueSourceName());
input.setSearchTerm(searchTerm);
if(StringUtils.hasContent(ids))
{
List<Serializable> idList = new ArrayList<>(Arrays.asList(ids.split(",")));
input.setIdList(idList);
}
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceAction().execute(input);
Map<String, Object> result = new HashMap<>();
result.put("options", output.getResults());
context.result(JsonUtils.toJson(result));
}
catch(Exception e)
{
handleException(context, e);
}
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -497,4 +497,57 @@ class QJavalinImplementationTest extends QJavalinTestBase
assertNotNull(jsonObject.getJSONObject("chartData"));
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testPossibleValueUnfiltered()
{
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/possibleValues/partnerPersonId").asString();
assertEquals(200, response.getStatus());
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
assertNotNull(jsonObject);
assertNotNull(jsonObject.getJSONArray("options"));
assertEquals(5, jsonObject.getJSONArray("options").length());
assertEquals(1, jsonObject.getJSONArray("options").getJSONObject(0).getInt("id"));
assertEquals("Darin Kelkhoff (1)", jsonObject.getJSONArray("options").getJSONObject(0).getString("label"));
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testPossibleValueWithSearchTerm()
{
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/possibleValues/partnerPersonId?searchTerm=Chamber").asString();
assertEquals(200, response.getStatus());
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
assertNotNull(jsonObject);
assertNotNull(jsonObject.getJSONArray("options"));
assertEquals(1, jsonObject.getJSONArray("options").length());
assertEquals("Tim Chamberlain (3)", jsonObject.getJSONArray("options").getJSONObject(0).getString("label"));
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testPossibleValueWithIds()
{
HttpResponse<String> response = Unirest.get(BASE_URL + "/data/person/possibleValues/partnerPersonId?ids=4,5").asString();
assertEquals(200, response.getStatus());
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
assertNotNull(jsonObject);
assertNotNull(jsonObject.getJSONArray("options"));
assertEquals(2, jsonObject.getJSONArray("options").length());
assertEquals(4, jsonObject.getJSONArray("options").getJSONObject(0).getInt("id"));
assertEquals(5, jsonObject.getJSONArray("options").getJSONObject(1).getInt("id"));
}
}

View File

@ -25,28 +25,31 @@ package com.kingsrook.qqq.backend.javalin;
import java.io.InputStream;
import java.sql.Connection;
import java.util.List;
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep;
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.modules.authentication.metadata.QAuthenticationMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
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.processes.QBackendStepMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.QAuthenticationMetaData;
import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager;
import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData;
@ -123,6 +126,7 @@ public class TestUtils
qInstance.addProcess(defineProcessSimpleSleep());
qInstance.addProcess(defineProcessScreenThenSleep());
qInstance.addProcess(defineProcessSimpleThrow());
qInstance.addPossibleValueSource(definePossibleValueSourcePerson());
defineWidgets(qInstance);
return (qInstance);
}
@ -181,6 +185,8 @@ public class TestUtils
return new QTableMetaData()
.withName("person")
.withLabel("Person")
.withRecordLabelFormat("%s %s")
.withRecordLabelFields("firstName", "lastName")
.withBackendName(defineBackend().getName())
.withPrimaryKeyField("id")
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
@ -189,6 +195,7 @@ public class TestUtils
.withField(new QFieldMetaData("firstName", QFieldType.STRING).withBackendName("first_name"))
.withField(new QFieldMetaData("lastName", QFieldType.STRING).withBackendName("last_name"))
.withField(new QFieldMetaData("birthDate", QFieldType.DATE).withBackendName("birth_date"))
.withField(new QFieldMetaData("partnerPersonId", QFieldType.INTEGER).withBackendName("partner_person_id").withPossibleValueSourceName("person"))
.withField(new QFieldMetaData("email", QFieldType.STRING));
}
@ -268,6 +275,22 @@ public class TestUtils
/*******************************************************************************
**
*******************************************************************************/
private static QPossibleValueSource definePossibleValueSourcePerson()
{
return (new QPossibleValueSource()
.withName("person")
.withType(QPossibleValueSourceType.TABLE)
.withTableName("person")
.withValueFormatAndFields(PVSValueFormatAndFields.LABEL_PARENS_ID)
.withOrderByField("id")
);
}
/*******************************************************************************
** Define a process with just one step that sleeps
*******************************************************************************/

View File

@ -29,7 +29,8 @@ CREATE TABLE person
first_name VARCHAR(80) NOT NULL,
last_name VARCHAR(80) NOT NULL,
birth_date DATE,
email VARCHAR(250) NOT NULL
email VARCHAR(250) NOT NULL,
partner_person_id INT
);
INSERT INTO person (id, first_name, last_name, birth_date, email) VALUES (1, 'Darin', 'Kelkhoff', '1980-05-31', 'darin.kelkhoff@gmail.com');