From 3a8dcbe22f229a00b9e3a2a481f1a7f7bda77948 Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Wed, 1 Nov 2023 12:55:28 +0100 Subject: [PATCH] New combobox implementation --- package-lock.json | 30 +++++- package.json | 2 +- .../components/Fields/ComboboxField.tsx | 100 ++++++++++++++++++ .../components/Fields/WrapperField.tsx | 14 ++- src/panelWebView/index.tsx | 1 + src/panelWebView/styles.css | 3 + tailwind.panel.js | 8 ++ webpack/panel.config.js | 16 ++- 8 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 src/panelWebView/components/Fields/ComboboxField.tsx create mode 100644 tailwind.panel.js diff --git a/package-lock.json b/package-lock.json index 7022a8bf..0ab0edae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@actions/core": "^1.10.0", "@bendera/vscode-webview-elements": "0.6.2", "@estruyf/vscode": "^1.1.0", - "@headlessui/react": "1.5.0", + "@headlessui/react": "^1.7.17", "@heroicons/react": "1.0.4", "@iarna/toml": "2.2.3", "@octokit/rest": "^18.12.0", @@ -348,9 +348,13 @@ } }, "node_modules/@headlessui/react": { - "version": "1.5.0", + "version": "1.7.17", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz", + "integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==", "dev": true, - "license": "MIT", + "dependencies": { + "client-only": "^0.0.1" + }, "engines": { "node": ">=10" }, @@ -2960,6 +2964,12 @@ "node": ">= 4.0" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "dev": true + }, "node_modules/clipboardy": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", @@ -13314,9 +13324,13 @@ } }, "@headlessui/react": { - "version": "1.5.0", + "version": "1.7.17", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz", + "integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==", "dev": true, - "requires": {} + "requires": { + "client-only": "^0.0.1" + } }, "@heroicons/react": { "version": "1.0.4", @@ -15272,6 +15286,12 @@ "source-map": "~0.6.0" } }, + "client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "dev": true + }, "clipboardy": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", diff --git a/package.json b/package.json index 65797d8f..f06be3bd 100644 --- a/package.json +++ b/package.json @@ -2526,7 +2526,7 @@ "@actions/core": "^1.10.0", "@bendera/vscode-webview-elements": "0.6.2", "@estruyf/vscode": "^1.1.0", - "@headlessui/react": "1.5.0", + "@headlessui/react": "^1.7.17", "@heroicons/react": "1.0.4", "@iarna/toml": "2.2.3", "@octokit/rest": "^18.12.0", diff --git a/src/panelWebView/components/Fields/ComboboxField.tsx b/src/panelWebView/components/Fields/ComboboxField.tsx new file mode 100644 index 00000000..f661960b --- /dev/null +++ b/src/panelWebView/components/Fields/ComboboxField.tsx @@ -0,0 +1,100 @@ +import { Combobox, Transition } from '@headlessui/react'; +import * as React from 'react'; +import { BaseFieldProps } from '../../../models'; +import { Fragment, useEffect, useMemo } from 'react'; +import { Page } from '../../../dashboardWebView/models'; +import { messageHandler } from '@estruyf/vscode/dist/client/webview'; +import { CommandToCode } from '../../CommandToCode'; +import { ChevronDownIcon } from '@heroicons/react/outline'; + +export interface IComboboxFieldProps extends BaseFieldProps { + contentTypeName?: string; + contentTypeValue?: string; + multiSelect?: boolean; + onChange: (value: string | string[]) => void; +} + +export const ComboboxField: React.FunctionComponent = ({ + label, + description, + value, + contentTypeName, + contentTypeValue, + multiSelect, + onChange, + required +}: React.PropsWithChildren) => { + const [loading, setLoading] = React.useState(false); + const [choices, setChoices] = React.useState([]); + const [pages, setPages] = React.useState([]); + const [crntSelected, setCrntSelected] = React.useState(value); + + const availableChoices = useMemo(() => { + return pages.filter((page: Page) => { + const value = contentTypeValue === "slug" ? page.slug : page.fmFilePath; + + if (typeof crntSelected === 'string') { + return crntSelected !== `${value}` && !value.includes(crntSelected); + } else if (crntSelected instanceof Array) { + const selected = crntSelected.filter((v) => v === `${value}` || value.includes(v)); + return selected.length === 0; + } + + return true; + }); + }, [choices, crntSelected, multiSelect, contentTypeValue]); + + useEffect(() => { + if (contentTypeName) { + setLoading(true); + messageHandler + .request(CommandToCode.searchByType, contentTypeName) + .then((pages: Page[]) => { + setPages(pages || []); + setChoices((pages || []).map(page => page.title)) + }).finally(() => { + setLoading(false); + }); + } + }, [contentTypeName]); + + return ( + null} + > +
+ +
+ console.log(e)} /> + + + + +
+ + + + {availableChoices.map((choice) => ( + + {choice.title} + + ))} + + +
+
+ ) +}; \ No newline at end of file diff --git a/src/panelWebView/components/Fields/WrapperField.tsx b/src/panelWebView/components/Fields/WrapperField.tsx index b059a2ae..41d58f39 100644 --- a/src/panelWebView/components/Fields/WrapperField.tsx +++ b/src/panelWebView/components/Fields/WrapperField.tsx @@ -33,6 +33,7 @@ import { fieldWhenClause } from '../../../utils/fieldWhenClause'; import { ContentTypeRelationshipField } from './ContentTypeRelationshipField'; import * as l10n from '@vscode/l10n'; import { LocalizationKey } from '../../../localization'; +import { ComboboxField } from './ComboboxField'; export interface IWrapperFieldProps { field: Field; @@ -485,7 +486,18 @@ export const WrapperField: React.FunctionComponent = ({ } else if (field.type === 'contentRelationship') { return ( - onSendUpdate(field.name, value, parentFields)} + /> */} + +