diff options
author | Valerij Fredriksen <valerijf@yahooinc.com> | 2022-08-12 14:47:58 +0200 |
---|---|---|
committer | Valerij Fredriksen <valerijf@yahooinc.com> | 2022-08-12 15:02:05 +0200 |
commit | 9aa5e8e284080168ba168f8196f203425fb7c6a6 (patch) | |
tree | 633b56ce4cabae472119d170a94c59f10e23b986 /client/js | |
parent | 07a74e30b98ae8ae7790e4fc5762cc32a8ae77d3 (diff) |
Implement paste JSON
Diffstat (limited to 'client/js')
-rw-r--r-- | client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx | 12 | ||||
-rw-r--r-- | client/js/app/src/app/pages/querybuilder/query-derived/paste-modal.jsx | 65 |
2 files changed, 55 insertions, 22 deletions
diff --git a/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx b/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx index 31cafeb860f..cfe39aaf5ee 100644 --- a/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx +++ b/client/js/app/src/app/pages/querybuilder/context/query-builder-provider.jsx @@ -1,6 +1,6 @@ +import { cloneDeep, last } from 'lodash'; import React, { useReducer } from 'react'; import { createContext, useContextSelector } from 'use-context-selector'; -import { cloneDeep, last } from 'lodash'; import parameters from 'app/pages/querybuilder/context/parameters'; let _dispatch; @@ -25,13 +25,19 @@ function inputsToJson(inputs) { ); } -function jsonToInputs(json, parent) { +export function jsonToInputs(json, parent = root) { return Object.entries(json).map(([key, value], i) => { const node = { id: parent.id ? `${parent.id}.${i}` : i.toString(), type: parent.type.children[key], parent, }; + if (!node.type) { + const location = parent.type.name + ? `under ${parent.type.name}` + : 'on root level'; + throw new Error(`Unknown property '${key}' ${location}`); + } if (typeof value === 'object') { node.input = ''; node.children = jsonToInputs(value, node); @@ -100,7 +106,7 @@ function preReducer(state, { action, data }) { switch (action) { case ACTION.SET_QUERY: { try { - const children = jsonToInputs(JSON.parse(data), root); + const children = jsonToInputs(JSON.parse(data)); return { ...state, query: { ...root, children } }; } catch (error) { alert(`Failed to parse query: ${error}`); // TODO: Change to toast diff --git a/client/js/app/src/app/pages/querybuilder/query-derived/paste-modal.jsx b/client/js/app/src/app/pages/querybuilder/query-derived/paste-modal.jsx index 9b68bd23e1c..04827427133 100644 --- a/client/js/app/src/app/pages/querybuilder/query-derived/paste-modal.jsx +++ b/client/js/app/src/app/pages/querybuilder/query-derived/paste-modal.jsx @@ -1,14 +1,57 @@ +import { Button, Modal, Stack, Textarea } from '@mantine/core'; import React, { useState } from 'react'; -import { Modal, Button, JsonInput, Stack } from '@mantine/core'; import { Icon } from 'app/components'; +import { + ACTION, + dispatch, + jsonToInputs, +} from 'app/pages/querybuilder/context/query-builder-provider'; + +function PasteForm({ close }) { + const [query, setQuery] = useState(''); + const [error, setError] = useState(''); + + function onSubmit() { + try { + const json = JSON.parse(query); + try { + jsonToInputs(json); + dispatch(ACTION.SET_QUERY, query); + close(); + } catch (error) { + setError(`Invalid Vespa query: ${error.message}`); + } + } catch (error) { + setError(`Invalid JSON: ${error.message}`); + } + } + + return ( + <Stack> + <Textarea + placeholder="Your Vespa query JSON" + error={error} + minRows={34} + value={query} + onChange={({ target }) => setQuery(target.value)} + autosize + /> + <Button leftIcon={<Icon name="paste" />} onClick={onSubmit}> + Save + </Button> + </Stack> + ); +} export function PasteModal() { const [opened, setOpened] = useState(false); + const close = () => setOpened(false); + return ( <> <Modal opened={opened} - onClose={() => setOpened(false)} + onClose={close} title="Vespa Query" overlayColor="white" shadow="1px 3px 10px 2px rgb(0 0 0 / 20%)" @@ -16,23 +59,7 @@ export function PasteModal() { size="xl" centered > - <Stack> - <JsonInput - placeholder="Your Vespa query JSON" - validationError="Invalid JSON or Vespa invalid query" - minRows={34} - formatOnBlur - autosize - /> - <Button - leftIcon={<Icon name="paste" />} - onClick={() => { - console.log('paste and close'); - }} - > - Paste - </Button> - </Stack> + <PasteForm close={close} /> </Modal> <Button onClick={() => setOpened(true)} |