From f77f7c1e5f09a8dd95ad6c07f6b858d3e5af3903 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 18 Nov 2021 15:36:16 +0000 Subject: [PATCH 01/18] Add dynamic filter component --- .../design/AppPreview/componentStructure.json | 3 +- packages/client/manifest.json | 11 ++ .../app/dynamic-filter/DynamicFilter.svelte | 37 ++++ .../app/dynamic-filter/FilterModal.svelte | 176 ++++++++++++++++++ .../components/app/dynamic-filter/index.js | 1 + packages/client/src/components/app/index.js | 1 + 6 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte create mode 100644 packages/client/src/components/app/dynamic-filter/FilterModal.svelte create mode 100644 packages/client/src/components/app/dynamic-filter/index.js diff --git a/packages/builder/src/components/design/AppPreview/componentStructure.json b/packages/builder/src/components/design/AppPreview/componentStructure.json index 357ea5a7be..b237347c44 100644 --- a/packages/builder/src/components/design/AppPreview/componentStructure.json +++ b/packages/builder/src/components/design/AppPreview/componentStructure.json @@ -67,6 +67,7 @@ "icon", "embed" ] - } + }, + "dynamicfilter" ] diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 050ac4a63a..ba7f95e42e 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2623,6 +2623,17 @@ } ] }, + "dynamicfilter": { + "name": "Dynamic Filter", + "icon": "FilterEdit", + "settings": [ + { + "type": "dataProvider", + "label": "Provider", + "key": "dataProvider" + } + ] + }, "tableblock": { "block": true, "name": "Table block", diff --git a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte new file mode 100644 index 0000000000..6cd0d2be5b --- /dev/null +++ b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte @@ -0,0 +1,37 @@ + + +
+ + + + + + +
diff --git a/packages/client/src/components/app/dynamic-filter/FilterModal.svelte b/packages/client/src/components/app/dynamic-filter/FilterModal.svelte new file mode 100644 index 0000000000..99b9a1a6f6 --- /dev/null +++ b/packages/client/src/components/app/dynamic-filter/FilterModal.svelte @@ -0,0 +1,176 @@ + + + +
+ + + {#if !filters?.length} + Add your first filter expression. + {:else} + Results are filtered to only those which match all of the following + constraints. + {/if} + + {#if filters?.length} +
+ {#each filters as filter, idx} + onOperatorChange(filter, e.detail)} + placeholder={null} + /> + {#if ["string", "longform", "number"].includes(filter.type)} + + {:else if ["options", "array"].includes(filter.type)} + + {:else if filter.type === "boolean"} + + {:else if filter.type === "datetime"} + + {:else} + + {/if} + duplicateFilter(filter.id)} + /> + removeFilter(filter.id)} + /> + {/each} +
+ {/if} +
+ +
+
+
+
+ + diff --git a/packages/client/src/components/app/dynamic-filter/index.js b/packages/client/src/components/app/dynamic-filter/index.js new file mode 100644 index 0000000000..5ac7d31730 --- /dev/null +++ b/packages/client/src/components/app/dynamic-filter/index.js @@ -0,0 +1 @@ +export { default as dynamicfilter } from "./DynamicFilter.svelte" diff --git a/packages/client/src/components/app/index.js b/packages/client/src/components/app/index.js index 92725f0738..f5d085e97b 100644 --- a/packages/client/src/components/app/index.js +++ b/packages/client/src/components/app/index.js @@ -33,6 +33,7 @@ export * from "./charts" export * from "./forms" export * from "./table" export * from "./blocks" +export * from "./dynamic-filter" // Deprecated component left for compatibility in old apps export { default as navigation } from "./deprecated/Navigation.svelte" From 34a00df86b5c3f9d523ef9d3ac22ed578f911250 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 18 Nov 2021 15:43:51 +0000 Subject: [PATCH 02/18] Add settings to dynamic filter to control button text and allowed filter fields --- packages/client/manifest.json | 12 +++++++++ .../app/dynamic-filter/DynamicFilter.svelte | 27 ++++++++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index ba7f95e42e..da1d87c5ab 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -2631,6 +2631,18 @@ "type": "dataProvider", "label": "Provider", "key": "dataProvider" + }, + { + "type": "multifield", + "label": "Allowed filter fields", + "key": "allowedFields", + "placeholder": "All fields" + }, + { + "type": "text", + "label": "Button text", + "key": "buttonText", + "defaultValue": "Edit filters" } ] }, diff --git a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte index 6cd0d2be5b..80a1b919bb 100644 --- a/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte +++ b/packages/client/src/components/app/dynamic-filter/DynamicFilter.svelte @@ -4,17 +4,32 @@ import FilterModal from "./FilterModal.svelte" export let dataProvider + export let allowedFields + export let buttonText const component = getContext("component") const { styleable } = getContext("sdk") - $: schema = dataProvider?.schema - $: schemaFields = Object.values(schema || {}) - let modal let tmpFilters = [] let filters = [] + $: schema = dataProvider?.schema + $: schemaFields = getSchemaFields(schema, allowedFields) + $: text = buttonText || "Edit filters" + + const getSchemaFields = (schema, allowedFields) => { + let clonedSchema = {} + if (!allowedFields?.length) { + clonedSchema = schema + } else { + allowedFields?.forEach(field => { + clonedSchema[field] = schema[field] + }) + } + return Object.values(clonedSchema || {}) + } + const openEditor = () => { tmpFilters = [...filters] modal.show() @@ -26,11 +41,11 @@
- - + From 33e5e198b7bb333017c30bc2f2e7f990f4f74d89 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 18 Nov 2021 18:41:37 +0000 Subject: [PATCH 03/18] Refactor how extending data provider queries works to support multiple extensions per key --- .../src/components/app/DataProvider.svelte | 17 +++++---- .../src/components/app/DateRangePicker.svelte | 38 ++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/packages/client/src/components/app/DataProvider.svelte b/packages/client/src/components/app/DataProvider.svelte index 08f2fb06cd..e9d306cc3b 100644 --- a/packages/client/src/components/app/DataProvider.svelte +++ b/packages/client/src/components/app/DataProvider.svelte @@ -275,11 +275,10 @@ allRows = res.rows } - const addQueryExtension = (key, operator, field, value) => { - if (!key || !operator || !field) { + const addQueryExtension = (key, extension) => { + if (!key || !extension) { return } - const extension = { operator, field, value } queryExtensions = { ...queryExtensions, [key]: extension } } @@ -295,11 +294,13 @@ const extendQuery = (defaultQuery, extensions) => { const extensionValues = Object.values(extensions || {}) let extendedQuery = { ...defaultQuery } - extensionValues.forEach(({ operator, field, value }) => { - extendedQuery[operator] = { - ...extendedQuery[operator], - [field]: value, - } + extensionValues.forEach(extension => { + Object.entries(extension || {}).forEach(([operator, fields]) => { + extendedQuery[operator] = { + ...extendedQuery[operator], + ...fields, + } + }) }) if (JSON.stringify(query) !== JSON.stringify(extendedQuery)) { diff --git a/packages/client/src/components/app/DateRangePicker.svelte b/packages/client/src/components/app/DateRangePicker.svelte index 651a19abc4..9f3207d4d2 100644 --- a/packages/client/src/components/app/DateRangePicker.svelte +++ b/packages/client/src/components/app/DateRangePicker.svelte @@ -13,15 +13,6 @@ const component = getContext("component") const { styleable, ActionTypes, getAction } = getContext("sdk") - - $: addExtension = getAction( - dataProvider?.id, - ActionTypes.AddDataProviderQueryExtension - ) - $: removeExtension = getAction( - dataProvider?.id, - ActionTypes.RemoveDataProviderQueryExtension - ) const options = [ "Last 1 day", "Last 7 days", @@ -32,10 +23,24 @@ ] let value = options.includes(defaultValue) ? defaultValue : "Last 30 days" - $: queryExtension = getQueryExtension(value) - $: addExtension?.($component.id, "range", field, queryExtension) + $: dataProviderId = dataProvider?.id + $: addExtension = getAction( + dataProviderId, + ActionTypes.AddDataProviderQueryExtension + ) + $: removeExtension = getAction( + dataProviderId, + ActionTypes.RemoveDataProviderQueryExtension + ) + $: queryExtension = getQueryExtension(field, value) + $: addExtension?.($component.id, queryExtension) + + const getQueryExtension = (field, value) => { + if (!field || !value) { + return null + } + console.log("getting extension for " + value) - const getQueryExtension = value => { let low = dayjs.utc().subtract(1, "year") let high = dayjs.utc().add(1, "day") @@ -51,7 +56,14 @@ low = dayjs.utc().subtract(6, "months") } - return { low: low.format(), high: high.format() } + return { + range: { + [field]: { + low: low.format(), + high: high.format(), + }, + }, + } } onDestroy(() => { From b7b424b7f89d8eaca2e02b1fc297b35b315c08b8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 18 Nov 2021 20:31:00 +0000 Subject: [PATCH 04/18] Add modal container to top level of client apps --- packages/client/src/components/ClientApp.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 119a26800f..98dec9667b 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -121,6 +121,9 @@ -->
+ +