@mui/material#DialogTitle TypeScript Examples

The following examples show how to use @mui/material#DialogTitle. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ChangelogDialog.tsx    From airmessage-web with Apache License 2.0 6 votes vote down vote up
/**
 * A dialog that shows the app version and latest changelog
 */
export default function ChangelogDialog(props: {isOpen: boolean, onDismiss: () => void}) {
	//Generating the build details
	const buildDate = getFormattedBuildDate();
	const buildVersion = `AirMessage for web ${appVersion}`;
	const detailedBuildVersion = buildVersion + ` (${releaseHash ?? "unlinked"})`;
	const buildTitle = buildVersion + (buildDate ? (`, ${WPEnv.ENVIRONMENT === "production" ? "released" : "built"} ${buildDate}`) : "");
	
	return (
		<Dialog
			open={props.isOpen}
			onClose={props.onDismiss}
			fullWidth>
			<DialogTitle>Release notes</DialogTitle>
			<DialogContent dividers>
				<Typography variant="overline" color="textSecondary" gutterBottom title={detailedBuildVersion}>{buildTitle}</Typography>
				<Markdown markdown={changelog} />
			</DialogContent>
		</Dialog>
	);
}
Example #2
Source File: Files.tsx    From NekoMaid with MIT License 6 votes vote down vote up
CompressDialog: React.FC<{ file: string | null, dirs: Record<string, boolean>, onClose: () => void, plugin: Plugin, path: string, refresh: () => void }> =
  ({ dirs, file, onClose, plugin, path, refresh }) => {
    const [value, setValue] = useState('')
    const [ext, setExt] = useState('zip')
    useEffect(() => {
      setValue(file || 'server')
    }, [file])
    let error: string | undefined
    if (!validFilename(value)) error = lang.files.wrongName
    else if (((path || '/') + value + '.' + ext) in dirs) error = lang.files.exists
    return <Dialog open={file != null} onClose={onClose}>
      <DialogTitle>{lang.files.compress}</DialogTitle>
      <DialogContent>
        <DialogContentText>{lang.files.compressName}</DialogContentText>
        <TextField value={value} variant='standard' error={!!error} helperText={error} onChange={e => setValue(e.target.value)} />
        <Select variant='standard' value={ext} onChange={e => setExt(e.target.value)}>
          {compressFileExt.map(it => <MenuItem key={it} value={it}>.{it}</MenuItem>)}
        </Select>
      </DialogContent>
      <DialogActions>
        <Button onClick={onClose}>{minecraft['gui.cancel']}</Button>
        <Button disabled={!!error} onClick={() => {
          onClose()
          plugin.emit('files:compress', (res: boolean) => {
            action(res)
            refresh()
          }, file, value, ext)
        }}>{minecraft['gui.ok']}</Button>
      </DialogActions>
    </Dialog>
  }
Example #3
Source File: cookies-dialog.tsx    From master-frontend-lemoncode with MIT License 6 votes vote down vote up
CookiesDialog: React.FunctionComponent<Props> = (props) => {
  const { onAgreeClick } = props;
  const [open, setOpen] = React.useState(false);

  const handleAgreeClick = () => {
    setOpen(false);
    onAgreeClick();
  };

  return (
    <>
      <Button variant="outlined" onClick={() => setOpen(true)}>
        Learn more about our cookies
      </Button>
      <Dialog open={open} onClose={() => setOpen(false)}>
        <DialogTitle>About cookies</DialogTitle>
        <DialogContent>
          <DialogContentText>
            Any information that you voluntarily provide to us, including your
            name and email address, will be used for the sole purpose for which
            the information was provided to us. In addition, communication
            exchanges on this website are public (not private) communications.
            Therefore, any message that you post on this website will be
            considered and treated as available for public use and distribution.
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button color="primary" onClick={handleAgreeClick}>
            Agree
          </Button>
        </DialogActions>
      </Dialog>
    </>
  );
}
Example #4
Source File: Vault.tsx    From NekoMaid with MIT License 6 votes vote down vote up
Groups: React.FC<{ plugin: Plugin, id: string | undefined, onClose: () => void, groups: GroupInfo[] }> =
  ({ plugin, id, onClose, groups }) => {
    const [loading, setLoading] = useState(true)
    const [playerGroups, setPlayerGroups] = useState<Record<string, true>>({ })
    const refresh = () => {
      setLoading(true)
      plugin.emit('vault:playerGroup', (res: string[]) => {
        if (!res) return
        const obj: Record<string, true> = { }
        res.forEach(it => (obj[it] = true))
        setPlayerGroups(obj)
        setLoading(false)
      }, id, null, 0)
    }
    useEffect(() => {
      setPlayerGroups({})
      if (!id) return
      refresh()
    }, [id])
    return <Dialog onClose={onClose} open={!!id}>
      <DialogTitle>{lang.vault.whosPermissionGroup(id!)}</DialogTitle>
      <List sx={{ pt: 0 }}>
        {groups.map(it => <ListItem onClick={() => { }} key={it.id}>
          <ListItemIcon><Checkbox
            tabIndex={-1}
            disabled={loading}
            checked={!!playerGroups[it.id]}
            onChange={e => plugin.emit('vault:playerGroup', (res: boolean) => {
              action(res)
              refresh()
            }, id, it.id, e.target.checked ? 1 : 2)}
          /></ListItemIcon>
          <ListItemText primary={it.id} />
        </ListItem>)}
      </List>
      <DialogActions><Button onClick={onClose}>{minecraft['gui.back']}</Button></DialogActions>
    </Dialog>
  }
Example #5
Source File: DeleteSelectedModal.tsx    From frontend with MIT License 6 votes vote down vote up
function DeleteSelectedModal({
  isOpen,
  handleDeleteModalClose,
  handleDelete,
}: {
  isOpen: boolean
  handleDeleteModalClose: () => void
  handleDelete: () => void
}) {
  return (
    <Modal open={isOpen} onClose={handleDeleteModalClose}>
      <Dialog open={isOpen} onClose={handleDeleteModalClose}>
        <DialogTitle>Искате ли да изтриете избраните кампании?</DialogTitle>
        <DialogActions>
          <Button onClick={handleDelete} autoFocus>
            Да
          </Button>
          <Button onClick={handleDeleteModalClose}>Не</Button>
        </DialogActions>
      </Dialog>
    </Modal>
  )
}
Example #6
Source File: Home.tsx    From mui-toolpad with MIT License 6 votes vote down vote up
function AppDeleteDialog({ app, onClose }: AppDeleteDialogProps) {
  const latestApp = useLatest(app);
  const deleteAppMutation = client.useMutation('deleteApp');

  const handleDeleteClick = React.useCallback(async () => {
    if (app) {
      await deleteAppMutation.mutateAsync([app.id]);
    }
    await client.refetchQueries('getApps');
    onClose();
  }, [app, deleteAppMutation, onClose]);

  return (
    <Dialog open={!!app} onClose={onClose}>
      <DialogForm>
        <DialogTitle>Confirm delete</DialogTitle>
        <DialogContent>
          Are you sure you want to delete application &quot;{latestApp?.name}&quot;
        </DialogContent>
        <DialogActions>
          <Button color="inherit" variant="text" onClick={onClose}>
            Cancel
          </Button>
          <LoadingButton
            type="submit"
            loading={deleteAppMutation.isLoading}
            onClick={handleDeleteClick}
            color="error"
          >
            Delete
          </LoadingButton>
        </DialogActions>
      </DialogForm>
    </Dialog>
  );
}
Example #7
Source File: UTXODetail.tsx    From sapio-studio with Mozilla Public License 2.0 6 votes vote down vote up
function ContinuationOption(props: { v: Continuation }) {
    const [is_open, setOpen] = React.useState(false);
    const name = props.v.path.substr(props.v.path.lastIndexOf('/') + 1);
    const dispatch = useDispatch();

    return (
        <div>
            <Button onClick={() => setOpen(true)} variant="contained">
                {name}
            </Button>
            <Dialog open={is_open} onClose={() => setOpen(false)}>
                <DialogTitle>
                    <Typography variant="h5">{name}</Typography>
                    <ASM
                        className="txhex"
                        value={props.v.path}
                        label="Full Path"
                    />
                </DialogTitle>
                <DialogContent>
                    <MemoizeContForm {...props} />
                </DialogContent>
                <DialogActions>
                    <Button onClick={() => dispatch(recreate_contract())}>
                        Recompile
                    </Button>
                    <Button onClick={() => setOpen(false)}>Close</Button>
                </DialogActions>
            </Dialog>
        </div>
    );
}
Example #8
Source File: Home.tsx    From mui-toolpad with MIT License 6 votes vote down vote up
function CreateAppDialog({ onClose, ...props }: CreateAppDialogProps) {
  const [name, setName] = React.useState('');
  const createAppMutation = client.useMutation('createApp');

  return (
    <Dialog {...props} onClose={onClose}>
      <DialogForm
        onSubmit={async (event) => {
          event.preventDefault();

          const app = await createAppMutation.mutateAsync([name]);
          window.location.href = `/_toolpad/app/${app.id}/editor`;
        }}
      >
        <DialogTitle>Create a new MUI Toolpad App</DialogTitle>
        <DialogContent>
          <TextField
            sx={{ my: 1 }}
            autoFocus
            fullWidth
            label="name"
            value={name}
            onChange={(event) => setName(event.target.value)}
          />
        </DialogContent>
        <DialogActions>
          <Button color="inherit" variant="text" onClick={onClose}>
            Cancel
          </Button>
          <LoadingButton type="submit" loading={createAppMutation.isLoading} disabled={!name}>
            Create
          </LoadingButton>
        </DialogActions>
      </DialogForm>
    </Dialog>
  );
}
Example #9
Source File: GroupDeleteModal.tsx    From abrechnung with GNU Affero General Public License v3.0 6 votes vote down vote up
export default function GroupDeleteModal({ show, onClose, groupToDelete }) {
    const confirmDeleteGroup = () => {
        deleteGroup({ groupID: groupToDelete.id })
            .then((res) => {
                onClose();
            })
            .catch((err) => {
                toast.error(err);
            });
    };

    return (
        <Dialog open={show} onClose={onClose}>
            <DialogTitle>Delete Group</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    {groupToDelete ? <span>Are you sure you want to delete group {groupToDelete.name}</span> : null}
                </DialogContentText>
            </DialogContent>
            <DialogActions>
                <Button color="primary" onClick={onClose}>
                    No
                </Button>
                <Button color="error" onClick={confirmDeleteGroup}>
                    Yes pls
                </Button>
            </DialogActions>
        </Dialog>
    );
}
Example #10
Source File: UpdateRequiredDialog.tsx    From airmessage-web with Apache License 2.0 6 votes vote down vote up
/**
 * A dialog that warns the user to check their server for updates
 */
export default function UpdateRequiredDialog(props: {isOpen: boolean, onDismiss: () => void}) {
	return (
		<Dialog
			open={props.isOpen}
			onClose={props.onDismiss}
			fullWidth>
			<DialogTitle>Your server needs to be updated</DialogTitle>
			<DialogContent>
				<DialogContentText>
					<Typography paragraph>
						You&apos;re running an unsupported version of AirMessage Server.
					</Typography>
					
					<Typography paragraph>
						Unsupported versions of AirMessage Server may contain security or stability issues,
						and will start refusing connections late January.
					</Typography>
					
					<Typography paragraph>
						Please install the latest version of AirMessage Server from <Link href="https://airmessage.org" target="_blank">airmessage.org</Link> on your Mac.
					</Typography>
				</DialogContentText>
			</DialogContent>
		</Dialog>
	);
}
Example #11
Source File: Dialog.tsx    From your_spotify with GNU General Public License v3.0 5 votes vote down vote up
export default function Dialog({ open, onClose, title, children }: DialogProps) {
  return (
    <MDialog open={open} maxWidth="xl" onClose={onClose} TransitionComponent={Grow}>
      <DialogTitle>{title}</DialogTitle>
      <DialogContent>{children}</DialogContent>
    </MDialog>
  );
}
Example #12
Source File: ServerSwitch.tsx    From NekoMaid with MIT License 5 votes vote down vote up
ServerSwitch: React.FC<DialogProps> = props => {
  const [value, setValue] = useState<string>('')
  let error = false
  // eslint-disable-next-line no-new
  try { if (value) new URL(value.startsWith('http://') ? value : 'http://' + value) } catch { error = true }
  return <Dialog fullWidth maxWidth='xs' {...props}>
    <DialogTitle>{lang.serverSwitch.title}</DialogTitle>
    <DialogContent sx={{ overflow: 'hidden' }}>
      <Autocomplete
        freeSolo
        inputValue={value}
        clearOnBlur={false}
        onInputChange={(_: any, v: string) => setValue(v)}
        noOptionsText={lang.serverSwitch.noServer}
        style={{ width: '100%', maxWidth: 500, marginTop: 10 }}
        options={JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')}
        getOptionLabel={(option: any) => option.address}
        renderInput={(props: any) => <TextField
          {...props}
          error={error}
          label={minecraft['addServer.enterIp']}
          helperText={error ? lang.serverSwitch.wrongHostname : undefined}
        />}
      />
      <DialogContentText>{lang.serverSwitch.content}</DialogContentText>
    </DialogContent>
    <DialogActions>
      <Button
        color='primary'
        disabled={error}
        onClick={() => (location.search = '?' + encodeURIComponent(value))}
      >{lang.serverSwitch.connect}</Button>
    </DialogActions>
  </Dialog>
}
Example #13
Source File: FeedbackDialog.tsx    From airmessage-web with Apache License 2.0 5 votes vote down vote up
/**
 * A dialog that presents help and feedback options
 */
export default function FeedbackDialog(props: {isOpen: boolean, onDismiss: () => void}) {
	const propsOnDismiss = props.onDismiss;
	
	const onClickEmail = useCallback(async () => {
		const body =
			`\n\n---------- DEVICE INFORMATION ----------` +
			Object.entries(await getPlatformUtils().getExtraEmailDetails())
				.map(([key, value]) => `\n${key}: ${value}`)
				.join("") +
			`\nUser agent: ${navigator.userAgent}` +
			`\nClient version: ${appVersion}` +
			`\nCommunications version: ${getActiveCommVer()?.join(".")} (target ${targetCommVerString})` +
			`\nProxy type: ${getActiveProxyType()}` +
			`\nServer system version: ${getServerSystemVersion()}` +
			`\nServer software version: ${getServerSoftwareVersion()}`;
		const url = `mailto:${supportEmail}?subject=${encodeURIComponent("AirMessage feedback")}&body=${encodeURIComponent(body)}`;
		window.open(url, "_blank");
		propsOnDismiss();
	}, [propsOnDismiss]);
	
	const onClickCommunity = useCallback(() => {
		window.open(communityPage, "_blank");
		propsOnDismiss();
	}, [propsOnDismiss]);
	
	return (
		<Dialog
			open={props.isOpen}
			onClose={props.onDismiss}>
			<DialogTitle>Help and feedback</DialogTitle>
			<DialogContent>
				<DialogContentText>
					Have a bug to report, a feature to suggest, or anything else to say? Contact us or discuss with others using the links below.
				</DialogContentText>
			</DialogContent>
			<DialogActions>
				<Button onClick={onClickEmail} color="primary">
					Send E-Mail
				</Button>
				<Button onClick={onClickCommunity} color="primary" autoFocus>
					Open community subreddit
				</Button>
			</DialogActions>
		</Dialog>
	);
}
Example #14
Source File: UrlQueryEditor.tsx    From mui-toolpad with MIT License 5 votes vote down vote up
export default function UrlQueryEditor({ pageNodeId }: UrlQueryEditorProps) {
  const dom = useDom();
  const domApi = useDomApi();

  const page = appDom.getNode(dom, pageNodeId, 'page');

  const [dialogOpen, setDialogOpen] = React.useState(false);

  const [input, setInput] = React.useState(page.attributes.urlQuery.value || {});
  React.useEffect(
    () => setInput(page.attributes.urlQuery.value || {}),
    [page.attributes.urlQuery.value],
  );

  const handleSave = React.useCallback(() => {
    domApi.setNodeNamespacedProp(page, 'attributes', 'urlQuery', appDom.createConst(input));
  }, [domApi, page, input]);

  return (
    <React.Fragment>
      <Button color="inherit" startIcon={<AddIcon />} onClick={() => setDialogOpen(true)}>
        URL query
      </Button>
      <Dialog fullWidth open={dialogOpen} onClose={() => setDialogOpen(false)}>
        <DialogTitle>Edit URL query</DialogTitle>
        <DialogContent>
          <StringRecordEditor
            sx={{ my: 1 }}
            fieldLabel="Parameter"
            valueLabel="Default value"
            value={input}
            onChange={setInput}
            autoFocus
          />
        </DialogContent>
        <DialogActions>
          <Button color="inherit" variant="text" onClick={() => setDialogOpen(false)}>
            Close
          </Button>
          <Button disabled={page.attributes.urlQuery.value === input} onClick={handleSave}>
            Save
          </Button>
        </DialogActions>
      </Dialog>
    </React.Fragment>
  );
}
Example #15
Source File: PictureDialog.tsx    From aws_serverless_photo_gallery with MIT License 5 votes vote down vote up
export default function PictureDialog({
  onClose,
  file,
}: {
  onClose: Function
  file?: DixieFile
}) {
  const [comments, setComments] = useState<Comment[]>()
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<unknown>()
  const [counter, setCounter] = useState(0)
  const [password] = useQueryParam('password', StringParam)
  const classes = useStyles()

  const handleClose = () => {
    setLoading(false)
    setError(undefined)
    onClose()
  }

  useEffect(() => {
    ;(async () => {
      try {
        if (file) {
          const result = await myfetchjson(
            API_ENDPOINT + `/getDixieComments?filename=${file?.filename}`,
          )
          setComments(result)
        }
      } catch (e) {
        setError(e)
      }
    })()
  }, [file, counter])

  return (
    <Dialog onClose={handleClose} open={Boolean(file)} maxWidth="lg">
      <DialogTitle>{file ? file.filename : ''}</DialogTitle>
      <DialogContent>
        {file ? (
          <Media file={file} style={{ width: '80%', maxHeight: '70%' }}>
            {getCaption(file)}
          </Media>
        ) : null}
        {error ? (
          <div className={classes.error}>{`${error}`}</div>
        ) : loading ? (
          'Loading...'
        ) : comments ? (
          <div className={classes.posts}>
            {comments
              .sort((a, b) => a.timestamp - b.timestamp)
              .map(comment => {
                const { user, timestamp, message } = comment
                return (
                  <div
                    key={JSON.stringify(comment)}
                    className={classes.post}
                    style={{ background: '#ddd' }}
                  >
                    <div>
                      {user ? user + ' - ' : ''}
                      {new Date(timestamp).toLocaleString()}
                    </div>
                    <div>{message}</div>
                  </div>
                )
              })}
          </div>
        ) : null}
        {file && password ? (
          <CommentForm
            filename={file.filename}
            forceRefresh={() => setCounter(counter + 1)}
          />
        ) : null}
      </DialogContent>
    </Dialog>
  )
}
Example #16
Source File: QueryEditor.tsx    From mui-toolpad with MIT License 5 votes vote down vote up
function ConnectionSelectorDialog<Q>({ open, onCreated, onClose }: DataSourceSelectorProps<Q>) {
  const dom = useDom();

  const [input, setInput] = React.useState<NodeId | null>(null);

  const handleClick = React.useCallback(() => {
    const connectionId = input;
    const connection = connectionId && appDom.getMaybeNode(dom, connectionId, 'connection');

    if (!connection) {
      throw new Error(`Invariant: Selected non-existing connection "${connectionId}"`);
    }

    const dataSourceId = connection.attributes.dataSource.value;
    const dataSource = dataSources[dataSourceId];
    if (!dataSource) {
      throw new Error(`Invariant: Selected non-existing dataSource "${dataSourceId}"`);
    }

    const queryNode = appDom.createNode(dom, 'query', {
      attributes: {
        query: appDom.createConst(dataSource.getInitialQueryValue()),
        connectionId: appDom.createConst(connectionId),
        dataSource: appDom.createConst(dataSourceId),
      },
    });

    onCreated(queryNode);
  }, [dom, input, onCreated]);

  return (
    <Dialog open={open} onClose={onClose} scroll="body">
      <DialogTitle>Create Query</DialogTitle>
      <DialogContent>
        <ConnectionSelect value={input} onChange={setInput} />
      </DialogContent>
      <DialogActions>
        <Button color="inherit" variant="text" onClick={onClose}>
          Cancel
        </Button>
        <Button disabled={!input} onClick={handleClick}>
          Create query
        </Button>
      </DialogActions>
    </Dialog>
  );
}
Example #17
Source File: ConfirmationDialog.tsx    From console with GNU Affero General Public License v3.0 5 votes vote down vote up
ConfirmationDialog = ({
  classes,
  open,
  cancelLabel,
  okLabel,
  onClose,
  cancelOnClick,
  okOnClick,
  title,
  description,
}: IConfirmationDialog) => {
  const [isSending, setIsSending] = useState<boolean>(false);
  const onClick = () => {
    setIsSending(true);
    if (okOnClick !== null) {
      okOnClick();
    }
    setIsSending(false);
  };
  if (!open) return null;
  return (
    <Dialog
      open={open}
      onClose={onClose}
      aria-labelledby="alert-dialog-title"
      aria-describedby="alert-dialog-description"
    >
      <DialogTitle id="alert-dialog-title">{title}</DialogTitle>
      <DialogContent>
        {isSending && <LinearProgress />}
        <DialogContentText id="alert-dialog-description">
          {description}
        </DialogContentText>
      </DialogContent>
      <DialogActions>
        <Button onClick={cancelOnClick} color="primary" disabled={isSending}>
          {cancelLabel || "Cancel"}
        </Button>
        <Button onClick={onClick} color="secondary" autoFocus>
          {okLabel || "Ok"}
        </Button>
      </DialogActions>
    </Dialog>
  );
}
Example #18
Source File: CreatePageNodeDialog.tsx    From mui-toolpad with MIT License 5 votes vote down vote up
export default function CreatePageDialog({ appId, onClose, ...props }: CreatePageDialogProps) {
  const dom = useDom();
  const domApi = useDomApi();
  const [name, setName] = React.useState('');
  const navigate = useNavigate();

  return (
    <Dialog {...props} onClose={onClose}>
      <DialogForm
        autoComplete="off"
        onSubmit={(e) => {
          e.preventDefault();
          const newNode = appDom.createNode(dom, 'page', {
            name,
            attributes: {
              title: appDom.createConst(name),
              urlQuery: appDom.createConst({}),
            },
          });
          const appNode = appDom.getApp(dom);
          domApi.addNode(newNode, appNode, 'pages');

          onClose();
          navigate(`/app/${appId}/editor/pages/${newNode.id}`);
        }}
      >
        <DialogTitle>Create a new MUI Toolpad Page</DialogTitle>
        <DialogContent>
          <TextField
            sx={{ my: 1 }}
            autoFocus
            fullWidth
            label="name"
            value={name}
            onChange={(event) => setName(event.target.value)}
          />
        </DialogContent>
        <DialogActions>
          <Button color="inherit" variant="text" onClick={onClose}>
            Cancel
          </Button>
          <Button type="submit" disabled={!name}>
            Create
          </Button>
        </DialogActions>
      </DialogForm>
    </Dialog>
  );
}
Example #19
Source File: WalletDialog.tsx    From wallet-adapter with Apache License 2.0 5 votes vote down vote up
WalletDialog: FC<WalletDialogProps> = ({
    title = 'Select your wallet',
    featuredWallets = 3,
    onClose,
    ...props
}) => {
    const { wallets, select } = useWallet();
    const { open, setOpen } = useWalletDialog();
    const [expanded, setExpanded] = useState(false);

    const [featured, more] = useMemo(
        () => [wallets.slice(0, featuredWallets), wallets.slice(featuredWallets)],
        [wallets, featuredWallets]
    );

    const handleClose = useCallback(
        (event: SyntheticEvent, reason?: 'backdropClick' | 'escapeKeyDown') => {
            if (onClose) onClose(event, reason!);
            if (!event.defaultPrevented) setOpen(false);
        },
        [setOpen, onClose]
    );

    const handleWalletClick = useCallback(
        (event: SyntheticEvent, walletName: WalletName) => {
            select(walletName);
            handleClose(event);
        },
        [select, handleClose]
    );

    const handleExpandClick = useCallback(() => setExpanded(!expanded), [setExpanded, expanded]);

    return (
        <RootDialog open={open} onClose={handleClose} {...props}>
            <DialogTitle>
                {title}
                <IconButton onClick={handleClose} size="large">
                    <CloseIcon />
                </IconButton>
            </DialogTitle>
            <DialogContent>
                <List>
                    {featured.map((wallet) => (
                        <WalletListItem
                            key={wallet.adapter.name}
                            onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                            wallet={wallet}
                        />
                    ))}
                    {more.length ? (
                        <>
                            <Collapse in={expanded} timeout="auto" unmountOnExit>
                                <List>
                                    {more.map((wallet) => (
                                        <WalletListItem
                                            key={wallet.adapter.name}
                                            onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                                            wallet={wallet}
                                        />
                                    ))}
                                </List>
                            </Collapse>
                            <ListItem>
                                <Button onClick={handleExpandClick}>
                                    {expanded ? 'Less' : 'More'} options
                                    {expanded ? <CollapseIcon /> : <ExpandIcon />}
                                </Button>
                            </ListItem>
                        </>
                    ) : null}
                </List>
            </DialogContent>
        </RootDialog>
    );
}
Example #20
Source File: StatsDialog.tsx    From GTAV-NativeDB with MIT License 5 votes vote down vote up
export default function StatsDialog({ open, onClose }: Props) {
  const stats = useStats()

  return (
    <Dialog open={open} onClose={onClose} fullWidth maxWidth="xs">
      <DialogTitle>
        Stats
      </DialogTitle>
      <List dense>
        <ListItem sx={{ px: 3 }} >
          <ListItemText 
            primary="Namespaces"
            secondary={stats.namespaces}
          />
        </ListItem>
        <ListItem sx={{ px: 3 }} >
          <ListItemText 
            primary="Natives"
            secondary={stats.natives}
          />
        </ListItem>
        <ListItem sx={{ px: 3 }} >
          <ListItemText 
            primary="Comments"
            secondary={stats.comments}
          />
        </ListItem>
        <ListItem sx={{ px: 3 }} >
          <ListItemText 
            primary="Known names"
            secondary={`${stats.knownNames.confirmed} (${stats.knownNames.total})`}
          />
        </ListItem>
      </List>
      <DialogActions>
        <Button onClick={onClose}>Close</Button>
      </DialogActions>
    </Dialog>
  )
}
Example #21
Source File: WalletSendDialog.tsx    From sapio-studio with Mozilla Public License 2.0 5 votes vote down vote up
export function WalletSendDialog(props: {
    show: boolean;
    amt: number;
    to: string;
    close: () => void;
    bitcoin_node_manager: BitcoinNodeManager;
}) {
    return (
        <Dialog
            open={props.show}
            onClose={() => {
                props.close();
            }}
        >
            <DialogTitle>Confirm Spend</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    Confirm sending
                    {props.amt} BTC to {props.to}
                </DialogContentText>
            </DialogContent>
            <DialogActions>
                <Button
                    onClick={() => {
                        props.close();
                    }}
                >
                    Cancel
                </Button>
                <Button
                    onClick={async () => {
                        await props.bitcoin_node_manager.send_to_address(
                            props.amt,
                            props.to
                        );
                        props.close();
                    }}
                >
                    Confirm
                </Button>
            </DialogActions>
        </Dialog>
    );
}
Example #22
Source File: dialog.tsx    From NekoMaid with MIT License 5 votes vote down vote up
DialogWrapper: React.FC = () => {
  const [canClick, setCanClick] = useState(false)
  const [open, setOpen] = useState(false)
  const [text, setText] = useState('')
  const [data, setDate] = useState<DialogOptionsWithPromise | undefined>()
  useEffect(() => {
    openFn = it => {
      setDate(it)
      setOpen(true)
    }
  }, [])
  if (!data) return <></>

  const input = (data as any).input
  const cancel = () => {
    setOpen(false)
    setDate(undefined)
    setText('')
    data.resolve(input ? null : false)
  }
  let inputElm: React.ReactNode
  if (input) {
    const props: any = {
      key: input.label || input,
      autoFocus: true,
      fullWidth: true,
      margin: 'dense',
      variant: 'standard',
      value: text,
      onStatusChange: setCanClick,
      onChange (it: any) { setText(it.target.value) }
    }
    if (typeof input === 'string') props.label = input
    else if (typeof input === 'object') Object.assign(props, input)
    inputElm = React.createElement(ValidInput, props)
  }

  return <Dialog open={!!open} onClose={cancel}>
    <DialogTitle>{data.title || lang.tip}</DialogTitle>
    <DialogContent>
      <DialogContentText>{data.content}</DialogContentText>
      {inputElm}
    </DialogContent>
    <DialogActions>
      {data.cancelButton !== false && <Button onClick={cancel}>{minecraft['gui.cancel']}</Button>}
      <Button {...data.okButton} disabled={canClick} onClick={() => {
        setOpen(false)
        setDate(undefined)
        setText('')
        data.resolve((data as any).input ? text : true)
      }}>{minecraft['gui.ok']}</Button>
    </DialogActions>
  </Dialog>
}
Example #23
Source File: DeleteModal.tsx    From frontend with MIT License 5 votes vote down vote up
export default function DeleteModal({ id, onClose, onDelete }: Props) {
  const queryClient = useQueryClient()
  const router = useRouter()
  const { t } = useTranslation()

  const mutationFn = useDeleteCampaignById(id)

  const deleteMutation = useMutation<AxiosResponse<null>, AxiosError<ApiErrors>, string>({
    mutationFn,
    onError: () => AlertStore.show(t('campaigns:alerts:error'), 'error'),
    onSuccess: () => {
      AlertStore.show(t('Кампанията беше преместена в кошчето.'), 'warning')
      queryClient.removeQueries(endpoints.campaign.viewCampaignById(id).url)
      onDelete()
      router.push(routes.admin.campaigns.index)
    },
  })

  function deleteHandler() {
    deleteMutation.mutate(id)
  }

  return (
    <Dialog open onClose={onClose} sx={{ top: '-35%' }}>
      <DialogTitle>{t('campaigns:deleteTitle')}</DialogTitle>
      <Card>
        <CardContent>
          <Typography variant="body1" sx={{ marginBottom: '16px', textAlign: 'center' }}>
            {t('campaigns:deleteContent')}
          </Typography>
          <Box sx={{ display: 'flex', justifyContent: 'center' }}>
            <Button color="error" onClick={deleteHandler}>
              {t('campaigns:cta:delete')}
            </Button>
            <Button onClick={onClose}>{t('campaigns:cta:cancel')}</Button>
          </Box>
        </CardContent>
      </Card>
    </Dialog>
  )
}
Example #24
Source File: FinanceDialogueBody.tsx    From mojito_pdm with Creative Commons Attribution Share Alike 4.0 International 5 votes vote down vote up
FinanceDialogueBody: React.FC<IFinanceDialogueBody> = ({spawncode, price, setDialogueOpen, setModalOpen}) => {
    const [downpay, setDownpay] = useState(20)
    const [colour, setColour] = useState<RgbColor>({r: 0, g: 0, b:0})
    const {setVisible} = useVisibility()
    const coloursEnabled = useRecoilValue(GlobalState.customColours)

    const handleClose = () => {
        setDialogueOpen(false)
    }

    const handleAccept = async () => {
        setDialogueOpen(false)
        setModalOpen(false)

        try {
            await fetchNui<void>("finance_vehicle", {
                vehicle: spawncode,
                downpayPercent: downpay,
                colour: coloursEnabled ? colour : null
            })
            await fetchNui("exit")
            setVisible(false)
        } catch (e) {
            console.error(e)
        }
    }

    const calculateDownpayment = () => {
        const total = parseFloat(price.slice(1).replace(/,/g, ''))

        return Math.round(total * (downpay / 100))
    }

    const onSliderChange = (e: any) => {
        setDownpay(e.target.value)
    }

    return (
        <>
            <DialogTitle>Confirm your finance options</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    Downpayment: ${calculateDownpayment()}.00 <br/>
                    Interest Rate: {interestRates[downpay]}%
                </DialogContentText>

                <br/>
                <Slider
                    defaultValue={downpay}
                    marks={[
                        {value: 10, label: "10%"},
                        {value: 20, label: "20%"},
                        {value: 30, label: "30%"},
                        {value: 40, label: "40%"},
                    ]}
                    min={10}
                    max={40}
                    step={10}
                    getAriaValueText={(value) => value + "%"}
                    onChange={onSliderChange}
                />

                {coloursEnabled &&
                <DialogContentText>
                    <br />
                    Pick a colour, any colour:
                    <RgbColorPicker color={colour} onChange={setColour} />
                </DialogContentText>
                }

            </DialogContent>
            <DialogActions>
                <Button color="success" variant="outlined" onClick={handleAccept}>Confirm</Button>
                <Button color="error" variant="outlined" onClick={handleClose}>Cancel</Button>
            </DialogActions>
        </>
    )
}
Example #25
Source File: PersonDialog.tsx    From frontend with MIT License 5 votes vote down vote up
export default function PersonDialog({ label, type, onSubmit }: Props) {
  const { t } = useTranslation()
  const [open, setOpen] = useState(false)

  const handleClickOpen = () => setOpen(true)
  const handleClose = () => setOpen(false)

  return (
    <>
      <Button fullWidth variant="contained" color="info" onClick={handleClickOpen}>
        {label}
      </Button>
      <Dialog
        open={open}
        onClose={(e, reason) => {
          if (reason === 'backdropClick') return
          handleClose()
        }}
        onBackdropClick={() => false}>
        <DialogTitle>
          {label}
          <IconButton
            aria-label="close"
            onClick={handleClose}
            sx={{
              position: 'absolute',
              right: 8,
              top: 8,
              color: (theme) => theme.palette.grey[500],
            }}>
            <Close />
          </IconButton>
        </DialogTitle>
        <DialogContent>
          <Box sx={{ mb: 2 }}>
            {type === 'beneficiary' ? (
              <Alert severity="info">
                <AlertTitle>{t('campaigns:campaign.beneficiary.name')}</AlertTitle>
                Лице, в чиято полза се организира кампанията. От юридическа гледна точка,
                бенефициентът <strong>НЕ влиза</strong> във взаимоотношения с оператора при набиране
                на средства в негова полза. Всички договори, изисквания, банкова сметка на
                кампанията са на името на организатора. Възможно е бенефициентът по една кампания да
                е и неговият организатор.
              </Alert>
            ) : (
              <Alert severity="warning">
                <AlertTitle>{t('campaigns:campaign.coordinator.name')}</AlertTitle>
                Организаторът е физическото или юридическо лице, с което се сключва договор за
                набиране на средства, след като негова заявка за кампания е одобрена. Набраните
                средства се прехвърлят в неговата банкова сметка, от него се изискват отчети за
                разходените средства. Когато дадено лице иска да стане организатор на кампании,
                преминава през процес на верификация, за да се избегнат измамите. Организаторът също
                може да е и бенефициент по дадена кампания.
              </Alert>
            )}
          </Box>
          <PersonForm
            {...type}
            onSubmit={(...args) => {
              onSubmit(...args)
              handleClose()
            }}
          />
        </DialogContent>
      </Dialog>
    </>
  )
}
Example #26
Source File: NewNickname.tsx    From sapio-studio with Mozilla Public License 2.0 5 votes vote down vote up
export function NewNickname(props: { show: boolean; hide: () => void }) {
    const [value, set_value] = React.useState<null | string>(null);
    const [key_value, set_key_value] = React.useState<null | string>(null);
    return (
        <Dialog onClose={props.hide} open={props.show}>
            <DialogTitle>Create a new User</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    The key and nickname for the new person. Keys must be
                    unique.
                </DialogContentText>
                <TextField
                    onChange={(ev) => set_value(ev.currentTarget.value)}
                    value={value}
                    autoFocus
                    margin="dense"
                    label="Name"
                    name="name"
                    type="text"
                    fullWidth
                    variant="standard"
                />
                <TextField
                    onChange={(ev) => set_key_value(ev.currentTarget.value)}
                    value={key_value}
                    autoFocus
                    margin="dense"
                    label="Key Hash"
                    name="keyhash"
                    type="text"
                    fullWidth
                    variant="standard"
                />
            </DialogContent>
            <DialogActions>
                <Button onClick={props.hide}>Cancel</Button>
                <Button
                    color="success"
                    onClick={async (ev) => {
                        if (value !== null && key_value) {
                            await window.electron.chat.add_user(
                                value,
                                key_value
                            );
                        }
                        props.hide();
                    }}
                >
                    Create
                </Button>
            </DialogActions>
        </Dialog>
    );
}
Example #27
Source File: PurchaseDialogueBody.tsx    From mojito_pdm with Creative Commons Attribution Share Alike 4.0 International 5 votes vote down vote up
PurchaseDialogueBody: React.FC<IPurchaseDialogueBody> = ({spawncode, price, setDialogueOpen, setModalOpen}) => {
    const [colour, setColour] = useState<RgbColor>({r: 0, g: 0, b: 0})
    const handleClose = () => {
        setDialogueOpen(false)
    }
    const {setVisible} = useVisibility()
    const coloursEnabled = useRecoilValue(GlobalState.customColours)

    const handleAccept = async () => {
        setDialogueOpen(false)
        setModalOpen(false)

        try {
            await fetchNui("buy_vehicle", {
                vehicle: spawncode,
                colour: coloursEnabled ? colour : null
            })
            await fetchNui("exit")
            setVisible(false)
        } catch (e) {
            console.error(e)
        }
    }

    return (
        <>
            <DialogTitle>Are you sure?</DialogTitle>
            <DialogContent>
                <DialogContentText>
                    Do you want to purchase this vehicle for {price}?
                </DialogContentText>

                {coloursEnabled &&
                    <DialogContentText>
                        <br />
                        Pick a colour, any colour:
                        <RgbColorPicker color={colour} onChange={setColour} />
                    </DialogContentText>
                }

            </DialogContent>
            <DialogActions>
                <Button color="success" variant="outlined" onClick={handleAccept}>Yes</Button>
                <Button color="error" variant="outlined" onClick={handleClose}>Cancel</Button>
            </DialogActions>
        </>
    )
}
Example #28
Source File: Settings.tsx    From sapio-studio with Mozilla Public License 2.0 4 votes vote down vote up
export function SettingsInner() {
    const [idx, set_idx] = React.useState<number>(0);
    const [dialog_node, set_dialog_node] = React.useState<
        [string | null, string[]]
    >([null, []]);
    const handleChange = (_: any, idx: number) => {
        set_idx(idx);
    };

    const test_bitcoind = async () => {
        window.electron
            .bitcoin_command([{ method: 'getbestblockhash', parameters: [] }])
            .then((h) =>
                set_dialog_node(['Connection Seems OK:', [`Best Hash ${h[0]}`]])
            )
            .catch((e) => {
                console.log('GOT', JSON.stringify(e));
                const r = e.message;
                if (typeof e.message === 'string') {
                    const err = JSON.parse(r);
                    if (
                        err instanceof Object &&
                        'code' in err &&
                        'name' in err &&
                        'message' in err
                    ) {
                        set_dialog_node([
                            '¡Connection Not Working!',
                            [
                                `Name: ${err.name}`,
                                `Message: ${err.message}`,
                                `Error Code: ${err.code}`,
                            ],
                        ]);
                        return;
                    } else if (typeof err === 'string') {
                        set_dialog_node([
                            '¡Connection Not Working!',
                            [`${err}`],
                        ]);
                        return;
                    }
                }
                set_dialog_node(['¡Unknown Error!', [`${r.toString()}`]]);
            });
    };

    const test_sapio = async () => {
        window.electron.sapio
            .show_config()
            .then((conf) => {
                if ('ok' in conf)
                    set_dialog_node([
                        'Sapio-CLI is Working!\nUsing Configuration:',
                        [`${conf.ok}`],
                    ]);
                else
                    set_dialog_node(['¡Configuration Error!', [`${conf.err}`]]);
            })
            .catch((e) =>
                set_dialog_node(['¡Configuration Error!', [`${e.toString()}`]])
            );
    };
    const check_emulator = async () => {
        window.electron.emulator.read_log().then((log) => {
            if (log.length) {
                const json = JSON.parse(log);
                set_dialog_node([
                    'Emulator Status:',
                    [
                        `interface: ${json.interface}`,
                        `pk: ${json.pk}`,
                        `sync: ${json.sync}`,
                    ],
                ]);
            } else {
                set_dialog_node(['Emulator Status:', ['Not Running']]);
            }
        });
    };

    return (
        <div className="Settings">
            <Box className="SettingsNav">
                <Tabs
                    orientation="vertical"
                    value={idx}
                    onChange={handleChange}
                    aria-label="basic tabs example"
                >
                    <Tab label="Guide"></Tab>
                    <Tab label="Sapio CLI"></Tab>
                    <Tab label="Bitcoin"></Tab>
                    <Tab label="Emulator"></Tab>
                    <Tab label="Display"></Tab>
                </Tabs>
            </Box>
            <Box className="SettingsPanes">
                <Dialog
                    open={
                        Boolean(dialog_node[0]) ||
                        Boolean(dialog_node[1].length)
                    }
                    onClose={() => set_dialog_node([null, []])}
                    aria-labelledby="alert-dialog-title"
                    aria-describedby="alert-dialog-description"
                >
                    <DialogTitle id="alert-dialog-title">
                        {dialog_node[0]}
                    </DialogTitle>
                    <DialogContent>
                        <div id="alert-dialog-description">
                            {dialog_node[1].map((txt) => (
                                <DialogContentText key={txt}>
                                    {txt}
                                </DialogContentText>
                            ))}
                        </div>
                    </DialogContent>
                    <DialogActions>
                        <Button onClick={() => set_dialog_node([null, []])}>
                            Close
                        </Button>
                    </DialogActions>
                </Dialog>
                <Guide idx={idx} my_idx={0} />
                <SettingPane name={'sapio_cli'} value={idx} idx={1}>
                    <Button
                        onClick={test_sapio}
                        variant="contained"
                        color="info"
                        size="large"
                    >
                        Test Sapio-Cli
                    </Button>
                </SettingPane>
                <SettingPane name={'bitcoin'} value={idx} idx={2}>
                    <Button
                        onClick={test_bitcoind}
                        variant="contained"
                        color="info"
                        size="large"
                    >
                        Test Connection
                    </Button>
                </SettingPane>
                <SettingPane name={'local_oracle'} value={idx} idx={3}>
                    <Button
                        variant="contained"
                        color="success"
                        size="large"
                        onClick={window.electron.emulator.start}
                    >
                        Start
                    </Button>
                    <Button
                        sx={{ marginLeft: '20px' }}
                        variant="contained"
                        color="error"
                        size="large"
                        onClick={window.electron.emulator.kill}
                    >
                        Kill
                    </Button>
                    <Button
                        sx={{ marginLeft: '20px' }}
                        variant="contained"
                        color="info"
                        size="large"
                        onClick={check_emulator}
                    >
                        Check Status
                    </Button>
                </SettingPane>
                <SettingPane name={'display'} value={idx} idx={4} />
            </Box>
        </div>
    );
}
Example #29
Source File: index.tsx    From mui-toolpad with MIT License 4 votes vote down vote up
export default function HierarchyExplorer({ appId, className }: HierarchyExplorerProps) {
  const dom = useDom();
  const domApi = useDomApi();

  const app = appDom.getApp(dom);
  const {
    apis = [],
    codeComponents = [],
    pages = [],
    connections = [],
  } = appDom.getChildNodes(dom, app);

  const [expanded, setExpanded] = useLocalStorageState<string[]>(
    `editor/${app.id}/hierarchy-expansion`,
    [':connections', ':pages', ':codeComponents'],
  );

  const location = useLocation();
  const match =
    matchRoutes(
      [
        { path: `/app/:appId/editor/pages/:activeNodeId` },
        { path: `/app/:appId/editor/apis/:activeNodeId` },
        { path: `/app/:appId/editor/codeComponents/:activeNodeId` },
        { path: `/app/:appId/editor/connections/:activeNodeId` },
      ],
      location,
    ) || [];

  const selected: NodeId[] = match.map((route) => route.params.activeNodeId as NodeId);

  const handleToggle = (event: React.SyntheticEvent, nodeIds: string[]) => {
    setExpanded(nodeIds as NodeId[]);
  };

  const navigate = useNavigate();

  const handleSelect = (event: React.SyntheticEvent, nodeIds: string[]) => {
    if (nodeIds.length <= 0) {
      return;
    }

    const rawNodeId = nodeIds[0];
    if (rawNodeId.startsWith(':')) {
      return;
    }

    const selectedNodeId: NodeId = rawNodeId as NodeId;
    const node = appDom.getNode(dom, selectedNodeId);
    if (appDom.isElement(node)) {
      // TODO: sort out in-page selection
      const page = appDom.getPageAncestor(dom, node);
      if (page) {
        navigate(`/app/${appId}/editor/pages/${page.id}`);
      }
    }

    if (appDom.isPage(node)) {
      navigate(`/app/${appId}/editor/pages/${node.id}`);
    }

    if (appDom.isApi(node)) {
      navigate(`/app/${appId}/editor/apis/${node.id}`);
    }

    if (appDom.isCodeComponent(node)) {
      navigate(`/app/${appId}/editor/codeComponents/${node.id}`);
    }

    if (appDom.isConnection(node)) {
      navigate(`/app/${appId}/editor/connections/${node.id}`);
    }
  };

  const [createConnectionDialogOpen, setCreateConnectionDialogOpen] = React.useState(0);
  const handleCreateConnectionDialogOpen = React.useCallback((event: React.MouseEvent) => {
    event.stopPropagation();
    setCreateConnectionDialogOpen(Math.random());
  }, []);
  const handleCreateConnectionDialogClose = React.useCallback(
    () => setCreateConnectionDialogOpen(0),
    [],
  );

  const [createPageDialogOpen, setCreatePageDialogOpen] = React.useState(0);
  const handleCreatePageDialogOpen = React.useCallback((event: React.MouseEvent) => {
    event.stopPropagation();
    setCreatePageDialogOpen(Math.random());
  }, []);
  const handleCreatepageDialogClose = React.useCallback(() => setCreatePageDialogOpen(0), []);

  const [createCodeComponentDialogOpen, setCreateCodeComponentDialogOpen] = React.useState(0);
  const handleCreateCodeComponentDialogOpen = React.useCallback((event: React.MouseEvent) => {
    event.stopPropagation();
    setCreateCodeComponentDialogOpen(Math.random());
  }, []);
  const handleCreateCodeComponentDialogClose = React.useCallback(
    () => setCreateCodeComponentDialogOpen(0),
    [],
  );

  const [deletedNodeId, setDeletedNodeId] = React.useState<NodeId | null>(null);
  const handleDeleteNodeDialogOpen = React.useCallback(
    (nodeId: NodeId) => (event: React.MouseEvent) => {
      event.stopPropagation();
      setDeletedNodeId(nodeId);
    },
    [],
  );
  const handledeleteNodeDialogClose = React.useCallback(() => setDeletedNodeId(null), []);

  const handleDeleteNode = React.useCallback(() => {
    if (deletedNodeId) {
      domApi.removeNode(deletedNodeId);
      navigate(`/app/${appId}/editor/`);
      handledeleteNodeDialogClose();
    }
  }, [deletedNodeId, domApi, navigate, appId, handledeleteNodeDialogClose]);

  const deletedNode = deletedNodeId && appDom.getMaybeNode(dom, deletedNodeId);
  const latestDeletedNode = useLatest(deletedNode);

  return (
    <HierarchyExplorerRoot className={className}>
      <TreeView
        aria-label="hierarchy explorer"
        selected={selected}
        onNodeSelect={handleSelect}
        expanded={expanded}
        onNodeToggle={handleToggle}
        multiSelect
        defaultCollapseIcon={<ExpandMoreIcon />}
        defaultExpandIcon={<ChevronRightIcon />}
      >
        <HierarchyTreeItem
          nodeId=":connections"
          labelText="Connections"
          onCreate={handleCreateConnectionDialogOpen}
        >
          {connections.map((connectionNode) => (
            <HierarchyTreeItem
              key={connectionNode.id}
              nodeId={connectionNode.id}
              labelText={connectionNode.name}
              onDelete={handleDeleteNodeDialogOpen(connectionNode.id)}
            />
          ))}
        </HierarchyTreeItem>
        {apis.length > 0 ? (
          <HierarchyTreeItem nodeId=":apis" labelText="Apis">
            {apis.map((apiNode) => (
              <HierarchyTreeItem
                key={apiNode.id}
                nodeId={apiNode.id}
                labelText={apiNode.name}
                onDelete={handleDeleteNodeDialogOpen(apiNode.id)}
              />
            ))}
          </HierarchyTreeItem>
        ) : null}
        <HierarchyTreeItem
          nodeId=":codeComponents"
          labelText="Components"
          onCreate={handleCreateCodeComponentDialogOpen}
        >
          {codeComponents.map((codeComponent) => (
            <HierarchyTreeItem
              key={codeComponent.id}
              nodeId={codeComponent.id}
              labelText={codeComponent.name}
              onDelete={handleDeleteNodeDialogOpen(codeComponent.id)}
            />
          ))}
        </HierarchyTreeItem>
        <HierarchyTreeItem nodeId=":pages" labelText="Pages" onCreate={handleCreatePageDialogOpen}>
          {pages.map((page) => (
            <HierarchyTreeItem
              key={page.id}
              nodeId={page.id}
              labelText={page.name}
              onDelete={handleDeleteNodeDialogOpen(page.id)}
            />
          ))}
        </HierarchyTreeItem>
      </TreeView>

      <CreateConnectionNodeDialog
        key={createConnectionDialogOpen || undefined}
        appId={appId}
        open={!!createConnectionDialogOpen}
        onClose={handleCreateConnectionDialogClose}
      />
      <CreatePageNodeDialog
        key={createPageDialogOpen || undefined}
        appId={appId}
        open={!!createPageDialogOpen}
        onClose={handleCreatepageDialogClose}
      />
      <CreateCodeComponentNodeDialog
        key={createCodeComponentDialogOpen || undefined}
        appId={appId}
        open={!!createCodeComponentDialogOpen}
        onClose={handleCreateCodeComponentDialogClose}
      />
      <Dialog open={!!deletedNode} onClose={handledeleteNodeDialogClose}>
        <DialogTitle>
          Delete {latestDeletedNode?.type} &quot;{latestDeletedNode?.name}&quot;?
        </DialogTitle>
        <DialogActions>
          <Button
            type="submit"
            color="inherit"
            variant="text"
            onClick={handledeleteNodeDialogClose}
          >
            Cancel
          </Button>
          <Button type="submit" onClick={handleDeleteNode}>
            Delete
          </Button>
        </DialogActions>
      </Dialog>
    </HierarchyExplorerRoot>
  );
}