-
-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First pass at creating queries+APIs [WIP] (#396)
* First pass at creating queries+APIs * Runtime support * fix types * fix live values * clean up * Improve live view * hide API/querystate when unused * Add a migration * Fix save and run button * only save certain props * prevent close * revert hide APIs
- Loading branch information
Showing
16 changed files
with
812 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
packages/toolpad-app/prisma/migrations/20220511155305_add_query/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- AlterEnum | ||
ALTER TYPE "DomNodeType" ADD VALUE 'query'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ enum DomNodeType { | |
codeComponent | ||
derivedState | ||
queryState | ||
query | ||
} | ||
|
||
model App { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
packages/toolpad-app/src/components/AppEditor/PageEditor/ErrorAlert.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import * as React from 'react'; | ||
import { Alert, AlertTitle, IconButton, Collapse, Box } from '@mui/material'; | ||
import ExpandLessIcon from '@mui/icons-material/ExpandLess'; | ||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; | ||
|
||
export interface ErrorAlertProps { | ||
error: unknown; | ||
} | ||
|
||
export default function ErrorAlert({ error }: ErrorAlertProps) { | ||
const message: string = | ||
typeof (error as any)?.message === 'string' ? (error as any).message : String(error); | ||
const stack: string | null = | ||
typeof (error as any)?.stack === 'string' ? (error as any).stack : null; | ||
|
||
const [expanded, setExpanded] = React.useState(false); | ||
const toggleExpanded = React.useCallback(() => setExpanded((actual) => !actual), []); | ||
return ( | ||
<Alert | ||
severity="error" | ||
sx={{ | ||
// The content of the Alert doesn't overflow nicely | ||
// TODO: does this need to go in core? | ||
'& .MuiAlert-message': { minWidth: 0 }, | ||
}} | ||
action={ | ||
stack ? ( | ||
<IconButton color="inherit" size="small" onClick={toggleExpanded}> | ||
{expanded ? <ExpandLessIcon /> : <ExpandMoreIcon />} | ||
</IconButton> | ||
) : null | ||
} | ||
> | ||
<AlertTitle>{message}</AlertTitle> | ||
<Collapse in={expanded}> | ||
<Box sx={{ overflow: 'auto' }}> | ||
<pre>{stack}</pre> | ||
</Box> | ||
</Collapse> | ||
</Alert> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
packages/toolpad-app/src/components/AppEditor/PageEditor/ParametersEditor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { Box, TextField, IconButton, SxProps } from '@mui/material'; | ||
import * as React from 'react'; | ||
import DeleteIcon from '@mui/icons-material/Delete'; | ||
import { BindableAttrValue, LiveBinding } from '@mui/toolpad-core'; | ||
import { WithControlledProp } from '../../../utils/types'; | ||
import BindableEditor from './BindableEditor'; | ||
|
||
export interface StringRecordEntriesEditorProps | ||
extends WithControlledProp<[string, BindableAttrValue<any>][]> { | ||
label?: string; | ||
liveValue: [string, LiveBinding][]; | ||
globalScope: Record<string, unknown>; | ||
fieldLabel?: string; | ||
valueLabel?: string; | ||
autoFocus?: boolean; | ||
sx?: SxProps; | ||
} | ||
|
||
export default function ParametersEditor({ | ||
value, | ||
onChange, | ||
liveValue, | ||
globalScope, | ||
label, | ||
fieldLabel = 'field', | ||
valueLabel = 'value', | ||
autoFocus = false, | ||
sx, | ||
}: StringRecordEntriesEditorProps) { | ||
const fieldInputRef = React.useRef<HTMLInputElement>(null); | ||
|
||
const handleRemove = React.useCallback( | ||
(index: number) => () => { | ||
onChange(value.filter((entry, i) => i !== index)); | ||
}, | ||
[onChange, value], | ||
); | ||
|
||
const isValidFieldName: boolean[] = React.useMemo(() => { | ||
const counts: Record<string, number> = {}; | ||
value.forEach(([field]) => { | ||
counts[field] = counts[field] ? counts[field] + 1 : 1; | ||
}); | ||
return value.map(([field]) => !!field && counts[field] <= 1); | ||
}, [value]); | ||
|
||
return ( | ||
<Box sx={sx} display="grid" gridTemplateColumns="1fr 2fr auto" alignItems="center" gap={1}> | ||
{label ? <Box gridColumn="span 3">{label}:</Box> : null} | ||
{value.map(([field, fieldValue], index) => { | ||
const liveBinding = liveValue[index][1]; | ||
|
||
return ( | ||
<React.Fragment key={index}> | ||
<TextField | ||
label={valueLabel} | ||
size="small" | ||
value={field} | ||
autoFocus | ||
onChange={(event) => | ||
onChange( | ||
value.map((entry, i) => (i === index ? [event.target.value, entry[1]] : entry)), | ||
) | ||
} | ||
error={!isValidFieldName[index]} | ||
/> | ||
<BindableEditor | ||
liveBinding={liveBinding} | ||
globalScope={globalScope} | ||
label={field} | ||
argType={{ typeDef: { type: 'string' } }} | ||
value={fieldValue} | ||
onChange={(newBinding) => | ||
onChange( | ||
value.map((entry, i) => | ||
i === index | ||
? [entry[0], newBinding || { type: 'const', value: undefined }] | ||
: entry, | ||
), | ||
) | ||
} | ||
/> | ||
{/* <BindingEditor | ||
globalScope={pageState} | ||
liveBinding={liveBinding} | ||
label={field} | ||
value={fieldValue} | ||
onChange={(newBinding) => | ||
onChange( | ||
value.map((entry, i) => | ||
i === index | ||
? [entry[0], newBinding || { type: 'const', value: undefined }] | ||
: entry, | ||
), | ||
) | ||
} | ||
/> */} | ||
|
||
<IconButton aria-label="Delete property" onClick={handleRemove(index)} size="small"> | ||
<DeleteIcon fontSize="small" /> | ||
</IconButton> | ||
</React.Fragment> | ||
); | ||
})} | ||
|
||
<form autoComplete="off" style={{ display: 'contents' }}> | ||
<TextField | ||
inputRef={fieldInputRef} | ||
size="small" | ||
label={fieldLabel} | ||
value="" | ||
onChange={(event) => { | ||
onChange([...value, [event.target.value, { type: 'const', value: null }]]); | ||
}} | ||
autoFocus={autoFocus} | ||
/> | ||
</form> | ||
</Box> | ||
); | ||
} |
Oops, something went wrong.