feat: Smart Substitution for Google Sheets Plugin (#7397)

This commit is contained in:
Trisha Anand 2021-09-14 18:34:49 +05:30 committed by GitHub
parent 8f294c8868
commit ef2f2d7751
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 222 additions and 15 deletions

View File

@ -1,7 +1,10 @@
package com.external.plugins;
import com.appsmith.external.dtos.ExecuteActionDTO;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.appsmith.external.helpers.DataTypeStringUtils;
import com.appsmith.external.helpers.MustacheHelper;
import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.ActionExecutionResult;
import com.appsmith.external.models.DatasourceConfiguration;
@ -10,6 +13,7 @@ import com.appsmith.external.models.OAuth2;
import com.appsmith.external.models.Property;
import com.appsmith.external.plugins.BasePlugin;
import com.appsmith.external.plugins.PluginExecutor;
import com.appsmith.external.plugins.SmartSubstitutionInterface;
import com.external.config.GoogleSheetsMethodStrategy;
import com.external.config.Method;
import com.external.config.MethodConfig;
@ -26,9 +30,15 @@ import reactor.core.Exceptions;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.lang.Boolean.TRUE;
public class GoogleSheetsPlugin extends BasePlugin {
// Setting max content length. This would've been coming from `spring.codec.max-in-memory-size` property if the
@ -44,12 +54,83 @@ public class GoogleSheetsPlugin extends BasePlugin {
@Slf4j
@Extension
public static class GoogleSheetsPluginExecutor implements PluginExecutor<Void> {
public static class GoogleSheetsPluginExecutor implements PluginExecutor<Void>, SmartSubstitutionInterface {
private static final int SMART_JSON_SUBSTITUTION_INDEX = 13;
private static final Set<String> jsonFields = new HashSet<>(Arrays.asList(
"rowObject",
"rowObjects"
));
@Override
public Mono<ActionExecutionResult> execute(Void connection,
DatasourceConfiguration datasourceConfiguration,
ActionConfiguration actionConfiguration) {
public Mono<ActionExecutionResult> executeParameterized(Void connection,
ExecuteActionDTO executeActionDTO,
DatasourceConfiguration datasourceConfiguration,
ActionConfiguration actionConfiguration) {
Boolean smartBsonSubstitution;
final List<Property> properties = actionConfiguration.getPluginSpecifiedTemplates();
List<Map.Entry<String, String>> parameters = new ArrayList<>();
// Default smart substitution to true
if (CollectionUtils.isEmpty(properties)) {
smartBsonSubstitution = true;
} else if (properties.size() > SMART_JSON_SUBSTITUTION_INDEX &&
properties.get(SMART_JSON_SUBSTITUTION_INDEX) != null) {
Object ssubValue = properties.get(SMART_JSON_SUBSTITUTION_INDEX).getValue();
if (ssubValue instanceof Boolean) {
smartBsonSubstitution = (Boolean) ssubValue;
} else if (ssubValue instanceof String) {
smartBsonSubstitution = Boolean.parseBoolean((String) ssubValue);
} else {
smartBsonSubstitution = true;
}
} else {
smartBsonSubstitution = true;
}
try {
// Smartly substitute in Json fields and replace all the bindings with values.
if (TRUE.equals(smartBsonSubstitution)) {
properties.stream().parallel().forEach(property -> {
if (property.getValue() != null) {
String propertyValue = String.valueOf(property.getValue());
String propertyKey = property.getKey();
if (jsonFields.contains(propertyKey)) {
// First extract all the bindings in order
List<String> mustacheKeysInOrder = MustacheHelper.extractMustacheKeysInOrder(propertyValue);
// Replace all the bindings with a placeholder
String updatedValue = MustacheHelper.replaceMustacheWithPlaceholder(propertyValue, mustacheKeysInOrder);
updatedValue = (String) smartSubstitutionOfBindings(updatedValue,
mustacheKeysInOrder,
executeActionDTO.getParams(),
parameters);
property.setValue(updatedValue);
}
}
});
}
} catch (AppsmithPluginException e) {
// Initializing object for error condition
ActionExecutionResult errorResult = new ActionExecutionResult();
errorResult.setStatusCode(AppsmithPluginError.PLUGIN_ERROR.getAppErrorCode().toString());
errorResult.setIsExecutionSuccess(false);
errorResult.setErrorInfo(e);
return Mono.just(errorResult);
}
prepareConfigurationsForExecution(executeActionDTO, actionConfiguration, datasourceConfiguration);
return this.executeCommon(connection, datasourceConfiguration, actionConfiguration);
}
public Mono<ActionExecutionResult> executeCommon(Void connection,
DatasourceConfiguration datasourceConfiguration,
ActionConfiguration actionConfiguration) {
// Initializing object for error condition
ActionExecutionResult errorResult = new ActionExecutionResult();
@ -163,6 +244,12 @@ public class GoogleSheetsPlugin extends BasePlugin {
});
}
@Override
public Mono<ActionExecutionResult> execute(Void connection, DatasourceConfiguration datasourceConfiguration, ActionConfiguration actionConfiguration) {
// Unused function
return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, "Unsupported Operation"));
}
@Override
public Mono<Void> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
return Mono.empty();
@ -191,5 +278,16 @@ public class GoogleSheetsPlugin extends BasePlugin {
actionConfiguration.setPluginSpecifiedTemplates(pluginSpecifiedTemplates);
return execute(null, datasourceConfiguration, actionConfiguration);
}
@Override
public Object substituteValueInInput(int index,
String binding,
String value,
Object input,
List<Map.Entry<String, String>> insertedParams,
Object... args) {
String jsonBody = (String) input;
return DataTypeStringUtils.jsonSmartReplacementPlaceholderWithValue(jsonBody, value, insertedParams);
}
}
}

View File

@ -381,12 +381,48 @@
"label": "Row Object",
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[9].value",
"controlType": "QUERY_DYNAMIC_TEXT",
"evaluationSubstitutionType": "SMART_SUBSTITUTE",
"hidden": {
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
"comparison": "NOT_IN",
"value": [
"APPEND",
"UPDATE"
"conditionType": "OR",
"conditions" : [
{
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
"comparison": "NOT_IN",
"value": [
"APPEND",
"UPDATE"
]
},
{
"path": "actionConfiguration.pluginSpecifiedTemplates[13].value",
"comparison": "EQUALS",
"value": false
}
]
},
"placeholderText": "{{\n {\n ...Table1.selectedRow, \n columnName: Input1.text\n }\n}}"
},
{
"label": "Row Object",
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[9].value",
"controlType": "QUERY_DYNAMIC_TEXT",
"evaluationSubstitutionType": "TEMPLATE",
"hidden": {
"conditionType": "OR",
"conditions":[
{
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
"comparison": "NOT_IN",
"value": [
"APPEND",
"UPDATE"
]
},
{
"path": "actionConfiguration.pluginSpecifiedTemplates[13].value",
"comparison": "EQUALS",
"value": true
}
]
},
"placeholderText": "{{\n {\n ...Table1.selectedRow, \n columnName: Input1.text\n }\n}}"
@ -402,13 +438,50 @@
"label": "Row Objects",
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[10].value",
"controlType": "QUERY_DYNAMIC_TEXT",
"evaluationSubstitutionType": "PARAMETER",
"hidden": {
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
"comparison": "NOT_IN",
"value": [
"CREATE",
"BULK_APPEND",
"BULK_UPDATE"
"conditionType": "OR",
"conditions" : [
{
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
"comparison": "NOT_IN",
"value": [
"CREATE",
"BULK_APPEND",
"BULK_UPDATE"
]
},
{
"path": "actionConfiguration.pluginSpecifiedTemplates[13].value",
"comparison": "EQUALS",
"value": false
}
]
},
"placeholderText": "{{\n Table1.selectedRows.map((row) => {\n return { ...row, columnName: Input1.text }\n })\n}}"
},
{
"label": "Row Objects",
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[10].value",
"controlType": "QUERY_DYNAMIC_TEXT",
"evaluationSubstitutionType": "TEMPLATE",
"hidden": {
"conditionType": "OR",
"conditions" : [
{
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
"comparison": "NOT_IN",
"value": [
"CREATE",
"BULK_APPEND",
"BULK_UPDATE"
]
},
{
"path": "actionConfiguration.pluginSpecifiedTemplates[13].value",
"comparison": "EQUALS",
"value": true
}
]
},
"placeholderText": "{{\n Table1.selectedRows.map((row) => {\n return { ...row, columnName: Input1.text }\n })\n}}"

View File

@ -0,0 +1,36 @@
{
"setting": [
{
"sectionName": "",
"id": 1,
"children": [
{
"label": "Run query on page load",
"configProperty": "executeOnLoad",
"controlType": "SWITCH",
"info": "Will refresh data each time the page is loaded"
},
{
"label": "Request confirmation before running query",
"configProperty": "confirmBeforeExecute",
"controlType": "SWITCH",
"info": "Ask confirmation from the user each time before refreshing data"
},
{
"label": "Smart JSON Substitution",
"info": "Turning on this property fixes the JSON substitution of bindings in the Row objects by adding/removing quotes intelligently and reduces developer errors",
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[13].value",
"controlType": "SWITCH",
"initialValue": true
},
{
"label": "Query timeout (in milliseconds)",
"info": "Maximum time after which the query will return",
"configProperty": "actionConfiguration.timeoutInMillisecond",
"controlType": "INPUT_TEXT",
"dataType": "NUMBER"
}
]
}
]
}