diff --git a/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/FirestorePlugin.java b/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/FirestorePlugin.java index babf75f6f2..76e0ebe7f5 100644 --- a/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/FirestorePlugin.java +++ b/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/FirestorePlugin.java @@ -17,6 +17,7 @@ import com.google.cloud.firestore.CollectionReference; import com.google.cloud.firestore.DocumentReference; import com.google.cloud.firestore.DocumentSnapshot; import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.Query; import com.google.cloud.firestore.QueryDocumentSnapshot; import com.google.cloud.firestore.QuerySnapshot; import com.google.cloud.firestore.WriteResult; @@ -132,7 +133,7 @@ public class FirestorePlugin extends BasePlugin { if (method.isDocumentLevel()) { return handleDocumentLevelMethod(connection, path, method, mapBody); } else { - return handleCollectionLevelMethod(connection, path, method, properties); + return handleCollectionLevelMethod(connection, path, method, properties, mapBody); } }) .subscribeOn(scheduler); @@ -221,15 +222,33 @@ public class FirestorePlugin extends BasePlugin { Firestore connection, String path, com.external.plugins.Method method, - List properties + List properties, + Map mapBody ) { + final CollectionReference collection = connection.collection(path); + + if (method == Method.GET_COLLECTION) { + return methodGetCollection(collection, properties); + + } else if (method == Method.ADD_TO_COLLECTION) { + return methodAddToCollection(collection, mapBody); + + } + + return Mono.error(new AppsmithPluginException( + AppsmithPluginError.PLUGIN_ERROR, + "Unsupported collection-level command: " + method + )); + } + + private Mono methodGetCollection(CollectionReference query, List properties) { final String orderBy = properties.size() > 1 && properties.get(1) != null ? properties.get(1).getValue() : null; final int limit = properties.size() > 2 && properties.get(2) != null ? Integer.parseInt(properties.get(2).getValue()) : 10; final String queryFieldPath = properties.size() > 3 && properties.get(3) != null ? properties.get(3).getValue() : null; final Op operator = properties.size() > 4 && properties.get(4) != null ? Op.valueOf(properties.get(4).getValue()) : null; final String queryValue = properties.size() > 5 && properties.get(5) != null ? properties.get(5).getValue() : null; - return Mono.just(connection.collection(path)) + return Mono.just(query) // Apply ordering, if provided. .map(query1 -> StringUtils.isEmpty(orderBy) ? query1 : query1.orderBy(orderBy)) // Apply where condition, if provided. @@ -285,17 +304,7 @@ public class FirestorePlugin extends BasePlugin { // Apply limit, always provided, since without it we can inadvertently end up processing too much data. .map(query1 -> query1.limit(limit)) // Run the Firestore query to get a Future of the results. - .flatMap(query1 -> { - switch (method) { - case GET_COLLECTION: - return Mono.just(query1.get()); - default: - return Mono.error(new AppsmithPluginException( - AppsmithPluginError.PLUGIN_ERROR, - "Unknown collection method: " + method.toString() + "." - )); - } - }) + .map(Query::get) // Consume the future to get the actual results. .flatMap(resultFuture -> { try { @@ -315,7 +324,35 @@ public class FirestorePlugin extends BasePlugin { result.setIsExecutionSuccess(true); System.out.println( Thread.currentThread().getName() - + ": In the Firestore Plugin, got action execution result" + + ": In the Firestore Plugin, got action execution result for get collection" + ); + return Mono.just(result); + }); + } + + private Mono methodAddToCollection(CollectionReference collection, Map mapBody) { + return Mono.justOrEmpty(collection.add(mapBody)) + .flatMap(future -> { + try { + return Mono.just(future.get()); + } catch (InterruptedException | ExecutionException e) { + return Mono.error(new AppsmithPluginException( + AppsmithPluginError.PLUGIN_ERROR, + e.getMessage() + )); + } + }) + .flatMap(opResult -> { + ActionExecutionResult result = new ActionExecutionResult(); + try { + result.setBody(resultToMap(opResult)); + } catch (AppsmithPluginException e) { + return Mono.error(e); + } + result.setIsExecutionSuccess(true); + System.out.println( + Thread.currentThread().getName() + + ": In the Firestore Plugin, got action execution result for add to collection" ); return Mono.just(result); }); @@ -344,6 +381,13 @@ public class FirestorePlugin extends BasePlugin { } return documents; + } else if (objResult instanceof DocumentReference) { + DocumentReference documentReference = (DocumentReference) objResult; + Map resultMap = new HashMap<>(); + resultMap.put("id", documentReference.getId()); + resultMap.put("path", documentReference.getPath()); + return resultMap; + } else { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_ERROR, diff --git a/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/Method.java b/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/Method.java index 086bc8953f..c3a27ee743 100644 --- a/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/Method.java +++ b/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/plugins/Method.java @@ -5,6 +5,7 @@ public enum Method { GET_COLLECTION(false, false), SET_DOCUMENT(true, true), CREATE_DOCUMENT(true, true), + ADD_TO_COLLECTION(false, true), UPDATE_DOCUMENT(true, true), DELETE_DOCUMENT(true, false), ; diff --git a/app/server/appsmith-plugins/firestorePlugin/src/main/resources/editor.json b/app/server/appsmith-plugins/firestorePlugin/src/main/resources/editor.json index 38e261a5b0..97f2e828ee 100644 --- a/app/server/appsmith-plugins/firestorePlugin/src/main/resources/editor.json +++ b/app/server/appsmith-plugins/firestorePlugin/src/main/resources/editor.json @@ -34,6 +34,10 @@ "label": "Create Document", "value": "CREATE_DOCUMENT" }, + { + "label": "Add Document to Collection", + "value": "ADD_TO_COLLECTION" + }, { "label": "Update Document", "value": "UPDATE_DOCUMENT" diff --git a/app/server/appsmith-plugins/firestorePlugin/src/test/java/com/external/plugins/FirestorePluginTest.java b/app/server/appsmith-plugins/firestorePlugin/src/test/java/com/external/plugins/FirestorePluginTest.java index f76044d967..386d38ae9a 100644 --- a/app/server/appsmith-plugins/firestorePlugin/src/test/java/com/external/plugins/FirestorePluginTest.java +++ b/app/server/appsmith-plugins/firestorePlugin/src/test/java/com/external/plugins/FirestorePluginTest.java @@ -25,6 +25,7 @@ import java.util.concurrent.ExecutionException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** @@ -204,4 +205,27 @@ public class FirestorePluginTest { .verifyComplete(); } + @Test + public void testAddToCollection() { + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setPath("changing"); + + actionConfiguration.setPluginSpecifiedTemplates(List.of(new Property("method", "ADD_TO_COLLECTION"))); + + actionConfiguration.setBody("{\n" + + " \"question\": \"What is the answer to life, universe and everything else?\",\n" + + " \"answer\": 42\n" + + "}"); + + Mono resultMono = pluginExecutor + .execute(firestoreConnection, dsConfig, actionConfiguration); + + StepVerifier.create(resultMono) + .assertNext(result -> { + assertTrue(result.getIsExecutionSuccess()); + assertNotNull(firestoreConnection.document("changing/" + ((Map) result.getBody()).get("id"))); + }) + .verifyComplete(); + } + }