From 9ab83a08a6ad686d884d5e2d8fad509c89e944b7 Mon Sep 17 00:00:00 2001
From: kevmodrome <kevin@kevmodro.me>
Date: Fri, 9 Oct 2020 11:23:42 +0200
Subject: [PATCH] adds options type support to grid component

---
 .../src/DataGrid/Component.svelte             |  20 ++--
 .../src/DataGrid/Select/Wrapper.svelte        |  17 +++
 .../src/DataGrid/customRenderer.js            | 110 ++++++++++++------
 3 files changed, 106 insertions(+), 41 deletions(-)
 create mode 100644 packages/standard-components/src/DataGrid/Select/Wrapper.svelte

diff --git a/packages/standard-components/src/DataGrid/Component.svelte b/packages/standard-components/src/DataGrid/Component.svelte
index fb323aca79..b0d19a2004 100644
--- a/packages/standard-components/src/DataGrid/Component.svelte
+++ b/packages/standard-components/src/DataGrid/Component.svelte
@@ -1,7 +1,7 @@
 <script>
   // Import valueSetters and custom renderers
   import { number } from "./valueSetters"
-  import renderers from "./customRenderer"
+  import { getRenderer } from "./customRenderer"
 
   // These maps need to be set up to handle whatever types that are used in the models.
   const setters = new Map([["number", number]])
@@ -28,7 +28,6 @@
       const jsonModel = await _bb.api.get(`/api/models/${datasource.modelId}`)
       model = await jsonModel.json()
       const { schema } = model
-      console.log(schema)
       if (!isEmpty(datasource)) {
         data = await fetchData(datasource)
         columnDefs = Object.keys(schema).map((key, i) => {
@@ -40,11 +39,12 @@
             field: key,
             hide: shouldHideField(key),
             sortable: true,
-            editable:
-              schema[key].type !== "boolean" &&
-              schema[key].type !== "attachment",
-            cellRenderer: renderers.get(schema[key].type),
-            autoHeight: schema[key].type === "attachment",
+            editable: isEditable(schema[key].type),
+            cellRenderer: getRenderer(
+              schema[key].type, // type
+              schema[key].constraints.inclusion // options
+            ),
+            autoHeight: true,
           }
         })
       }
@@ -52,6 +52,12 @@
     }
   })
 
+  const isEditable = type =>
+    type !== "boolean" &&
+    type !== "options" &&
+    type !== "attachment" &&
+    type !== "datetime"
+
   const shouldHideField = name => {
     if (name.startsWith("_")) return true
     // always 'record'
diff --git a/packages/standard-components/src/DataGrid/Select/Wrapper.svelte b/packages/standard-components/src/DataGrid/Select/Wrapper.svelte
new file mode 100644
index 0000000000..4c4a8eaf21
--- /dev/null
+++ b/packages/standard-components/src/DataGrid/Select/Wrapper.svelte
@@ -0,0 +1,17 @@
+<script>
+  import { Select } from "@budibase/bbui"
+  import { createEventDispatcher } from "svelte"
+  const dispatch = createEventDispatcher()
+
+  export let value
+  export let options
+
+  $: dispatch("change", value)
+</script>
+
+<Select label={false} bind:value>
+  <option value="">Choose an option</option>
+  {#each options as option}
+    <option value={option}>{option}</option>
+  {/each}
+</Select>
diff --git a/packages/standard-components/src/DataGrid/customRenderer.js b/packages/standard-components/src/DataGrid/customRenderer.js
index 1b9bec0aae..5ecc74466b 100644
--- a/packages/standard-components/src/DataGrid/customRenderer.js
+++ b/packages/standard-components/src/DataGrid/customRenderer.js
@@ -2,52 +2,94 @@
 // https://www.ag-grid.com/javascript-grid-cell-rendering-components/
 
 import AttachmentCell from './AttachmentCell/Button.svelte'
+import Select from './Select/Wrapper.svelte'
 import { DatePicker } from "@budibase/bbui"
 
-export default new Map([
+const renderers = new Map([
     ["boolean", booleanRenderer],
     ["attachment", attachmentRenderer],
     ["datetime", dateRenderer],
+    ["options", optionsRenderer],
 ])
 
-function booleanRenderer(params) {
-    const toggle = (e) => {
-        params.value = !params.value
-        params.setValue(e.currentTarget.checked)
-    }
-    let input = document.createElement("input")
-    input.type = "checkbox"
-    input.checked = params.value
-    input.addEventListener("click", toggle)
-
-    return input
-}
-function attachmentRenderer(params) {
-    const container = document.createElement("div")
-
-    const attachmentInstance = new AttachmentCell({
-        target: container,
-        props: {
-            files: params.value || [],
+function booleanRenderer(options) {
+    return params => {
+        const toggle = (e) => {
+            params.value = !params.value
+            params.setValue(e.currentTarget.checked)
         }
-    });
+        let input = document.createElement("input")
+        input.type = "checkbox"
+        input.checked = params.value
+        input.addEventListener("click", toggle)
 
-    return container
-}
-function dateRenderer(params) {
-    const container = document.createElement("div")
-    const toggle = (e) => {
-        params.setValue(e.detail[0][0])
+        return input
     }
+}
+function attachmentRenderer(options) {
+    return params => {
+        const container = document.createElement("div")
 
-    const datePickerInstance = new DatePicker({
-        target: container,
-        props: {
-            value: params.value,
+        const attachmentInstance = new AttachmentCell({
+            target: container,
+            props: {
+                files: params.value || [],
+            }
+        });
+
+        return container
+    }
+}
+function dateRenderer(options) {
+    return params => {
+        const container = document.createElement("div")
+        const toggle = (e) => {
+            params.setValue(e.detail[0][0])
         }
-    });
 
-    datePickerInstance.$on('change', toggle)
+        const datePickerInstance = new DatePicker({
+            target: container,
+            props: {
+                value: params.value,
+            }
+        });
 
-    return container
+        datePickerInstance.$on('change', toggle)
+
+        return container
+    }
+}
+
+
+function optionsRenderer(options) {
+    return params => {
+        const container = document.createElement("div")
+        const change = (e) => {
+            params.setValue(e.detail)
+        }
+
+        const selectInstance = new Select({
+            target: container,
+            props: {
+                value: params.value,
+                options
+            }
+        });
+
+        selectInstance.$on('change', change)
+
+        return container
+    }
+}
+
+export function getRenderer(type, options) {
+    // Complicated thing to set options for renderers
+    let customRenderer
+    if (type === "options" || type === 'datetime') {
+        customRenderer = renderers.get(type)(options)
+    } else {
+        let rendererGenerator = renderers.get(type)
+        customRenderer = rendererGenerator ? rendererGenerator() : false
+    }
+    return customRenderer
 }
\ No newline at end of file