react-error-boundary#ErrorBoundary TypeScript Examples

The following examples show how to use react-error-boundary#ErrorBoundary. 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: ExampleContainer.tsx    From useDApp with MIT License 6 votes vote down vote up
function ExampleRenderer({ example }: ExampleRendererProps) {
  const [Component = () => <></>] = useState(() => loadExample(example))

  return (
    <div style={{ borderRadius: 16, border: '1px solid rgb(190, 195, 201)', padding: 32 }}>
      <ErrorBoundary FallbackComponent={ErrorFallback}>
        <Component />
      </ErrorBoundary>
    </div>
  )
}
Example #2
Source File: index.tsx    From react-pwa with MIT License 6 votes vote down vote up
function withErrorHandler<P extends object>(Component: FC<P>, Fallback: FC<FallbackProps>) {
  function ComponentWithErrorHandling(props: P) {
    return (
      <ErrorBoundary FallbackComponent={Fallback}>
        <Component {...(props as P)} />
      </ErrorBoundary>
    );
  }

  ComponentWithErrorHandling.displayName = `WithErrorHandling${getDisplayName(
    Component as FC<unknown>,
  )}`;

  return ComponentWithErrorHandling;
}
Example #3
Source File: requestsTableWrapper.tsx    From interactsh-web with MIT License 6 votes vote down vote up
RequestsTableWrapper = ({
  data,
  handleRowClick,
  selectedInteraction,
  filter,
}: RequestsTableWrapperP): JSX.Element => (
  <div className="requests_table_container">
    <ErrorBoundary
      FallbackComponent={({ resetErrorBoundary }) => (
        <RepoSidebarListErrorFallback retry={resetErrorBoundary} />
      )}
    >
      <Suspense fallback={<RepoSidebarListFallback />}>
        <RequestsTable
          data={[...data].reverse()}
          handleRowClick={handleRowClick}
          selectedInteraction={selectedInteraction}
          filter={filter}
        />
      </Suspense>
    </ErrorBoundary>
  </div>
)
Example #4
Source File: WithErrorBoundary.tsx    From assisted-ui-lib with Apache License 2.0 6 votes vote down vote up
WithErrorBoundary = ({
  children,
  ...props
}: PropsWithChildren<WithErrorBoundaryProps>) => {
  const { captureException } = useErrorMonitor();
  const errorHandler = (error: Error) => {
    captureException(error, props.title);
  };
  return (
    <ErrorBoundary FallbackComponent={getErrorFallbackComponent(props)} onError={errorHandler}>
      {children}
    </ErrorBoundary>
  );
}
Example #5
Source File: runtime.tsx    From mui-toolpad with MIT License 6 votes vote down vote up
export function NodeRuntimeWrapper({ nodeId, componentConfig, children }: NodeRuntimeWrapperProps) {
  const resetNodeErrorsKey = React.useContext(ResetNodeErrorsKeyContext);
  return (
    <ErrorBoundary
      resetKeys={[resetNodeErrorsKey]}
      fallbackRender={({ error }) => (
        <NodeFiberHost
          {...{
            [RUNTIME_PROP_NODE_ID]: nodeId,
            nodeError: error,
            componentConfig,
          }}
        >
          <NodeError error={error} />
        </NodeFiberHost>
      )}
    >
      <NodeRuntimeContext.Provider value={nodeId}>
        <NodeFiberHost
          {...{
            [RUNTIME_PROP_NODE_ID]: nodeId,
            componentConfig,
          }}
        >
          {children}
        </NodeFiberHost>
      </NodeRuntimeContext.Provider>
    </ErrorBoundary>
  );
}
Example #6
Source File: ErrorWrapper.tsx    From videotranscode.space with Apache License 2.0 6 votes vote down vote up
GlobalErrorWrapper = () => {
  const [globalError, setGlobalError] = useState({ state: false, message: '' })

  useEffect(() => {
    window.onerror = message => {
      console.info(`Caught Error from Worker ${message}`)
      setGlobalError({ state: true, message: message as string })
    }
  }, [])

  if (globalError.state) {
    return <ErrorScreen errorObj={new Error(globalError.message)} />
  }

  return (
    <>
      <ErrorBoundary
        FallbackComponent={ErrorFallback}
        onError={globalErrorHandler}>
        <App />
      </ErrorBoundary>
    </>
  )
}
Example #7
Source File: index.tsx    From meshtastic-web with GNU General Public License v3.0 6 votes vote down vote up
root.render(
  <StrictMode>
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      <RouteProvider>
        <Provider store={store}>
          <LazyMotion features={domAnimation}>
            <App />
          </LazyMotion>
          <ReloadPrompt />
        </Provider>
      </RouteProvider>
    </ErrorBoundary>
  </StrictMode>,
);
Example #8
Source File: Hub.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
Hub = () => {
  document.title = "Jina Hub"
  return (
    <Provider store={store}>
      <Router basename={"/"}>
        <div>
          {routes.map((route: HubRoute, index: number) => {
            return (
              <Route
                key={index}
                path={route.path}
                exact={route.exact}
                component={withTracker((props) => {
                  return (
                    <route.layout {...props} {...route.props}>
                      <ErrorBoundary FallbackComponent={FallbackPage}>
                        <route.component {...props} />
                      </ErrorBoundary>
                    </route.layout>
                  )
                })}
              />
            )
          })}
        </div>
      </Router>
    </Provider>
  )
}
Example #9
Source File: Dashboard.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
Dashboard = () => {
  document.title = "Jina Dashboard"
  return (
    <Provider store={store}>
      <Router basename={"/"}>
        <div>
          {routes.map((route, idx: number) => {
            return (
              <Route
                key={`${route.path}-${idx}`}
                path={route.path}
                exact={route.exact}
                component={withTracker((props: any) => {
                  return (
                    <route.layout {...props} {...route.props}>
                      <ErrorBoundary FallbackComponent={FallbackPage}>
                        <route.component {...props} />
                      </ErrorBoundary>
                    </route.layout>
                  )
                }, {})}
              />
            )
          })}
        </div>
      </Router>
    </Provider>
  )
}
Example #10
Source File: index.tsx    From rari-dApp with GNU Affero General Public License v3.0 6 votes vote down vote up
ReactDOM.render(
  <>
    <PWAPrompt
      timesToShow={2}
      permanentlyHideOnDismiss={false}
      copyTitle="Add Rari to your homescreen!"
      copyBody="The Rari Portal works best when added to your homescreen. Without doing this, you may have a degraded experience."
      copyClosePrompt="Close"
    />
    <ChakraProvider theme={customTheme}>
      <ErrorBoundary FallbackComponent={ErrorPage}>
        <QueryClientProvider client={queryClient}>
          <ReactQueryDevtools initialIsOpen={false} />
          <BrowserRouter>
            <RariProvider>
              <ScrollToTop />
              <App />
            </RariProvider>
          </BrowserRouter>
        </QueryClientProvider>
      </ErrorBoundary>
    </ChakraProvider>
  </>,
  document.getElementById("root")
);
Example #11
Source File: App.tsx    From TabMerger with GNU General Public License v3.0 5 votes vote down vote up
App = (): JSX.Element => {
  const dispatch = useDispatch();

  const { filterChoice } = useSelector((state) => state.header);
  const { active, available } = useSelector((state) => state.groups.present);

  const { filteredGroups } = useFilter();

  useInitState({ available, active });
  useUpdateWindows();
  useUpdateInfo();
  useExecuteCommand();

  const { onBeforeCapture, onDragStart, onDragEnd } = useDnd();

  return (
    <Container>
      <GlobalStyle />
      <ErrorBoundary
        FallbackComponent={ErrorBoundaryFallback}
        onReset={() => {
          // Revert 2 steps back
          dispatch(ActionCreators.jump(-2));
        }}
      >
        <Header />

        <DragDropContext onBeforeCapture={onBeforeCapture} onDragStart={onDragStart} onDragEnd={onDragEnd}>
          {(filterChoice === "tab" || (filterChoice === "group" && filteredGroups.length > 0)) && (
            <MainArea>
              <SidePanel />

              <Windows />
            </MainArea>
          )}
        </DragDropContext>
      </ErrorBoundary>
    </Container>
  );
}
Example #12
Source File: index.tsx    From meshtastic-web with GNU General Public License v3.0 5 votes vote down vote up
Layout = ({
  title,
  icon,
  sidebarContents,
  children,
}: LayoutProps): JSX.Element => {
  const [settingsOpen, setSettingsOpen] = useState(false);

  const route = useRoute();

  const tabs: Omit<TabProps, 'activeLeft' | 'activeRight'>[] = [
    {
      title: 'Messages',
      icon: <FiMessageCircle />,
      link: routes.messages().link,
      active: route.name === 'messages',
    },
    {
      title: 'Map',
      icon: <RiRoadMapLine />,
      link: routes.map().link,
      active: route.name === 'map',
    },
    {
      title: 'Extensions',
      icon: <VscExtensions />,
      link: routes.extensions().link,
      active: route.name === 'extensions',
    },
  ];

  return (
    <div className="relative flex w-full overflow-hidden bg-white dark:bg-secondaryDark">
      <div className="flex flex-grow">
        <Sidebar settingsOpen={settingsOpen} setSettingsOpen={setSettingsOpen}>
          <div className="bg-white px-1 pt-1 drop-shadow-md dark:bg-primaryDark">
            <div className="flex h-10 gap-1">
              <div className="my-auto">
                <IconButton icon={icon} />
              </div>
              <div className="my-auto text-lg font-medium dark:text-white">
                {title}
              </div>
            </div>
          </div>
          <div className="flex flex-col gap-2">{sidebarContents}</div>
        </Sidebar>
      </div>
      <ErrorBoundary FallbackComponent={ErrorFallback}>
        <div className="flex h-full w-full flex-col bg-gray-300 dark:bg-secondaryDark">
          <div className="flex w-full bg-white pt-1 dark:bg-primaryDark">
            <div className="z-10 -mr-2 h-8">
              <IconButton
                className="m-1"
                icon={<FiSettings />}
                onClick={(): void => {
                  setSettingsOpen(!settingsOpen);
                }}
                active={settingsOpen}
              />
            </div>
            <Tabs tabs={tabs} />
          </div>
          <div className="flex flex-grow">{children}</div>
        </div>
      </ErrorBoundary>
    </div>
  );
}
Example #13
Source File: ToolpadApp.tsx    From mui-toolpad with MIT License 5 votes vote down vote up
export default function ToolpadApp({ basename, appId, version, dom }: ToolpadAppProps) {
  const root = appDom.getApp(dom);
  const { pages = [], themes = [] } = appDom.getChildNodes(dom, root);

  const theme = themes.length > 0 ? themes[0] : null;

  const appContext = React.useMemo(() => ({ appId, version }), [appId, version]);

  const queryClient = React.useMemo(
    () =>
      new QueryClient({
        defaultOptions: {
          queries: {
            retry: false,
          },
        },
      }),
    [],
  );

  const [resetNodeErrorsKey, setResetNodeErrorsKey] = React.useState(0);

  React.useEffect(() => setResetNodeErrorsKey((key) => key + 1), [dom]);

  return (
    <AppRoot id={HTML_ID_APP_ROOT}>
      <NoSsr>
        <DomContextProvider value={dom}>
          <AppThemeProvider node={theme}>
            <CssBaseline />
            <ErrorBoundary FallbackComponent={AppError}>
              <ResetNodeErrorsKeyProvider value={resetNodeErrorsKey}>
                <React.Suspense fallback={<AppLoading />}>
                  <JsRuntimeProvider>
                    <AppContextProvider value={appContext}>
                      <QueryClientProvider client={queryClient}>
                        <BrowserRouter basename={basename}>
                          <Routes>
                            <Route path="/" element={<Navigate replace to="/pages" />} />
                            <Route path="/pages" element={<AppOverview dom={dom} />} />
                            {pages.map((page) => (
                              <Route
                                key={page.id}
                                path={`/pages/${page.id}`}
                                element={
                                  <ComponentsContext dom={dom} page={page}>
                                    <RenderedPage nodeId={page.id} />
                                  </ComponentsContext>
                                }
                              />
                            ))}
                          </Routes>
                        </BrowserRouter>
                      </QueryClientProvider>
                    </AppContextProvider>
                  </JsRuntimeProvider>
                </React.Suspense>
              </ResetNodeErrorsKeyProvider>
            </ErrorBoundary>
          </AppThemeProvider>
        </DomContextProvider>
      </NoSsr>
    </AppRoot>
  );
}
Example #14
Source File: viewer.tsx    From nota with MIT License 5 votes vote down vote up
OutputView: React.FC<{ result: TranslationResult; imports?: any }> = ({
  result,
  imports,
}) => {
  let [lastTranslation] = useState<{ t: JSX.Element | null }>({ t: null });

  let DocResult = execute(result, imports || {});

  let errored = false;
  useEffect(
    action(() => {
      if (errored) {
        errored = false;
        return;
      }
      let Doc = resUnwrap(DocResult);
      lastTranslation.t = <Doc key={counter++} editing />;
    }),
    [result]
  );

  let fallback = (err: JSX.Element) => {
    errored = true;
    return (
      <>
        <ErrorView>{err}</ErrorView>
        {lastTranslation.t}
      </>
    );
  };

  return (
    <>
      {isOk(result) && result.value.css ? <style>{result.value.css}</style> : null}
      <ErrorBoundary
        resetKeys={[result]}
        FallbackComponent={({ error }) => fallback(<>{error.stack}</>)}
      >
        {isOk(DocResult) ? <DocResult.value key={counter++} editing /> : fallback(DocResult.value)}
      </ErrorBoundary>
    </>
  );
}
Example #15
Source File: Routes.tsx    From vsinder-app with Apache License 2.0 5 votes vote down vote up
Routes: React.FC<RoutesProps> = ({}) => {
  const { editorBackground } = useTheme();
  const { data, isLoading } = useQuery<MeResponse>("/me");
  const routeNameRef = React.useRef<string | undefined>();
  const navigationRef = React.useRef<NavigationContainerRef>(null);

  let body: any = null;

  if (isLoading) {
    body = <FullscreenLoading />;
  } else if (!data?.user) {
    body = <AuthStack />;
  } else if (data.user.goal && data.user.codeImgIds.length) {
    body = <MainTabStack />;
  } else {
    body = <ProfileStack isNewUser />;
  }

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: editorBackground }}>
      <ReactQueryErrorResetBoundary>
        {({ reset }) => (
          <ErrorBoundary
            onReset={reset}
            FallbackComponent={ErrorFallback}
            onError={myErrorHandler}
          >
            <NavigationContainer
              ref={navigationRef}
              onStateChange={() => {
                const previousRouteName = routeNameRef.current;
                const currentRouteName = navigationRef.current?.getCurrentRoute()
                  ?.name;

                if (previousRouteName !== currentRouteName) {
                  if (
                    !["swiper", "viewProfile", "matchy"].includes(
                      currentRouteName || ""
                    )
                  ) {
                    useShowTabs.getState().set({ show: false });
                  } else {
                    useShowTabs.getState().set({ show: true });
                  }
                }

                routeNameRef.current = currentRouteName;
              }}
              linking={linking}
              fallback={<FullscreenLoading />}
            >
              {body}
            </NavigationContainer>
          </ErrorBoundary>
        )}
      </ReactQueryErrorResetBoundary>
    </SafeAreaView>
  );
}
Example #16
Source File: Members2.tsx    From Riakuto-StartingReact-ja3.1 with Apache License 2.0 5 votes vote down vote up
Members: VFC<Props> = ({ orgCodeList, prefetch = () => undefined }) => {
  const [orgCode, setOrgCode] = useState('');
  const [input, setInput] = useState('');
  const [isPending, startTransition] = useTransition();
  const { reset } = useQueryErrorResetBoundary();

  const menuItems = orgCodeList.map((code) => ({
    key: code,
    name: capitalize(code),
    onClick: () => {
      setInput('');

      if (orgCode) {
        startTransition(() => setOrgCode(code));
      } else {
        setOrgCode(code);
      }
    },
    onMouseOver: () => prefetch(code),
    active: code === orgCode,
  }));

  const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {
    event.preventDefault();
    setOrgCode(input.toLowerCase().trim());
  };

  return (
    <>
      <header className="app-header">
        <h1>組織メンバーリスト</h1>
      </header>
      <form className="search-form" onSubmit={handleSubmit}>
        <Input
          placeholder="組織コードを入力..."
          type="text"
          value={input}
          onChange={(_, data) => setInput(data.value)}
        />
        <Button type="submit" disabled={isPending} primary>
          検索
        </Button>
      </form>
      <Menu items={menuItems} text />
      <Divider />
      <div className={isPending ? 'loading' : ''}>
        <ErrorBoundary
          fallbackRender={({ resetErrorBoundary }) => (
            <>
              <Message warning>
                {orgCode} というコードの組織は見つかりません
              </Message>
              <Button color="olive" onClick={() => resetErrorBoundary()}>
                エラーをリセット
              </Button>
            </>
          )}
          onReset={() => reset()}
        >
          <SuspenseList revealOrder="forwards">
            <Suspense fallback={<Spinner size="small" />}>
              <OrgInfo orgCode={orgCode} />
            </Suspense>
            <Suspense fallback={<Spinner size="large" />}>
              <MemberList orgCode={orgCode} />
            </Suspense>
          </SuspenseList>
        </ErrorBoundary>
      </div>
    </>
  );
}
Example #17
Source File: requestDetailsWrapper.tsx    From interactsh-web with MIT License 5 votes vote down vote up
RequestDetailsWrapper = (props: RequestDetailsWrapperP) => {
  const { selectedInteractionData, view } = props;

  return (
    <div
      className="detailed_request"
      style={{ flexDirection: View.eq.equals(view, "up_and_down") ? "column" : "row" }}
    >
      <ErrorBoundary
        FallbackComponent={({ resetErrorBoundary }) => (
          <IssuesListErrorFallback retry={resetErrorBoundary} />
        )}
      >
        <Suspense fallback={<IssuesListFallback />}>
          {View.eq.equals(view, "request") ||
          Protocol.eq.equals(selectedInteractionData.protocol, "smtp") ? (
            <DetailedRequest
              view={view}
              data={`${selectedInteractionData["raw-request"]}`}
              title="Request"
              protocol={selectedInteractionData.protocol}
            />
          ) : View.eq.equals(view, "response") ? (
            <DetailedRequest
              view={view}
              data={`${selectedInteractionData["raw-response"]}`}
              title="Response"
              protocol={selectedInteractionData.protocol}
            />
          ) : (
            <>
              <DetailedRequest
                view={view}
                data={`${selectedInteractionData["raw-request"]}`}
                title="Request"
                protocol={selectedInteractionData.protocol}
              />
              <DetailedRequest
                view={view}
                data={`${selectedInteractionData["raw-response"]}`}
                title="Response"
                protocol={selectedInteractionData.protocol}
              />
            </>
          )}
        </Suspense>
      </ErrorBoundary>
    </div>
  );
}
Example #18
Source File: Routes.tsx    From vsinder with Apache License 2.0 5 votes vote down vote up
Routes: React.FC<RoutesProps> = ({}) => {
  const { editorBackground } = useTheme();
  const { data, isLoading } = useQuery<MeResponse>("/me");
  const routeNameRef = React.useRef<string | undefined>();
  const navigationRef = React.useRef<NavigationContainerRef>(null);

  let body: any = null;

  if (isLoading) {
    body = <FullscreenLoading />;
  } else if (!data?.user) {
    body = <AuthStack />;
  } else if (data.user.goal && data.user.codeImgIds.length) {
    body = <MainTabStack />;
  } else {
    body = <ProfileStack isNewUser />;
  }

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: editorBackground }}>
      <ReactQueryErrorResetBoundary>
        {({ reset }) => (
          <ErrorBoundary
            onReset={reset}
            FallbackComponent={ErrorFallback}
            onError={myErrorHandler}
          >
            <NavigationContainer
              ref={navigationRef}
              onStateChange={() => {
                const previousRouteName = routeNameRef.current;
                const currentRouteName = navigationRef.current?.getCurrentRoute()
                  ?.name;

                if (previousRouteName !== currentRouteName) {
                  if (
                    !["swiper", "viewProfile", "matchy"].includes(
                      currentRouteName || ""
                    )
                  ) {
                    useShowTabs.getState().set({ show: false });
                  } else {
                    useShowTabs.getState().set({ show: true });
                  }
                }

                routeNameRef.current = currentRouteName;
              }}
              linking={linking}
              fallback={<FullscreenLoading />}
            >
              {body}
            </NavigationContainer>
          </ErrorBoundary>
        )}
      </ReactQueryErrorResetBoundary>
    </SafeAreaView>
  );
}
Example #19
Source File: showModal.tsx    From yakit with GNU Affero General Public License v3.0 5 votes vote down vote up
showModal = (props: ShowModalProps) => {
    const div = document.createElement("div");
    document.body.appendChild(div)

    let setter: (r: boolean) => any = () => {
    };
    const render = (targetConfig: ShowModalProps) => {
        setTimeout(() => {
            ReactDOM.render(<>
                <BaseModal
                    {...targetConfig as ModalProps}
                    onVisibleSetter={r => {
                        setter = r
                    }}
                    afterClose={() => {
                        const unmountResult = ReactDOM.unmountComponentAtNode(div);
                        if (unmountResult && div.parentNode) {
                            div.parentNode.removeChild(div);
                        }
                    }}
                >
                    <ErrorBoundary FallbackComponent={({error, resetErrorBoundary}) => {
                        if (!error) {
                            return <div>未知错误</div>
                        }
                        return <div>
                            <p>弹框内逻辑性崩溃,请关闭重试!</p>
                            <pre>{error?.message}</pre>
                        </div>
                    }}>
                        {targetConfig.content}
                    </ErrorBoundary>
                </BaseModal>
            </>, div)
        })
    }
    render(props);
    return {
        destroy: () => {
            if (setter) {
                setter(false)
            }
            setTimeout(() => {
                const unmountResult = ReactDOM.unmountComponentAtNode(div);
                if (unmountResult && div.parentNode) {
                    div.parentNode.removeChild(div)
                }
            }, 400)
        }
    }
}
Example #20
Source File: PipelineComponent.tsx    From baleen3 with Apache License 2.0 4 votes vote down vote up
PipelineComponent = React.forwardRef<
  HTMLDivElement,
  PipelineComponentProps
>(({ type, descriptor, setName, setSettings, onDelete, ...props }, ref) => {
  const component = new PipelineComponentDescriptor(descriptor)
  const editable = onDelete !== undefined
  const {
    name,
    settings,
    schema: settingsSchema,
    info: componentInfo,
    valid,
    configured,
  } = component

  const componentClassName = Object.keys(descriptor)[0]
  if (componentClassName === undefined) {
    throw Error('Pipeline component does not define a type')
  }
  const [showSettingsDialog, openSettingsDialog, closeSettingsDialog] =
    useDialog()
  const [showNameDialog, openNameDialog, closeNameDialog] = useDialog()
  const innerRef = useRef<HTMLDivElement>(null)
  const [isHovering] = useHover<HTMLDivElement>(innerRef)
  const [isFocus] = useFocus<HTMLDivElement>(innerRef)
  const [hasSettings, setHasSettings] = useState(settingsSchema !== undefined)

  const handleDelete = useCallback((): void => {
    onDelete !== undefined && onDelete(component.id)
  }, [component.id, onDelete])

  const handleSetName = useCallback(
    (name: string): void => {
      setName !== undefined && setName(component.id, component.type, name)
    },
    [component.id, component.type, setName]
  )

  const handleSetSettings = useCallback(
    (settings: object): void => {
      setSettings !== undefined &&
        setSettings(component.id, component.type, settings)
    },
    [component.id, component.type, setSettings]
  )

  const keyHandlers: {
    [key: string]: (event?: KeyboardEvent | undefined) => void
  } = useMemo(
    () => ({
      DELETE: (event?: KeyboardEvent | undefined): void => {
        if (event !== undefined) {
          event.preventDefault()
          handleDelete()
        }
      },
      OPEN_SETTINGS: (event?: KeyboardEvent | undefined): void => {
        if (event !== undefined && hasSettings) {
          event.preventDefault()
          openSettingsDialog()
        }
      },
      OPEN_NAME: (event?: KeyboardEvent | undefined): void => {
        if (event !== undefined && setName !== undefined) {
          event.preventDefault()
          openNameDialog()
        }
      },
    }),
    [handleDelete, hasSettings, openNameDialog, openSettingsDialog, setName]
  )

  let message: React.ReactNode = null

  if (componentInfo === undefined) {
    message = (
      <MessageBar severity="error" message="Component type not available" />
    )
  } else if (!valid) {
    message = (
      <MessageBar severity="error" message="Component settings not valid" />
    )
  } else if (setSettings !== undefined && hasSettings && !configured) {
    message = (
      <MessageBar
        severity="warning"
        message="Component has not been configured"
      />
    )
  }

  const {
    name: componentName,
    description,
    tags,
  }: ComponentInfo = componentInfo ?? {
    name: 'Missing',
    componentClass: 'Missing',
    artifact: '',
    description: '',
    tags: [],
  }

  const displayName = createDisplayName(name, componentName)
  const displaySub = createDisplaySub(name, componentName)

  return (
    <Box ref={ref} width={1 / 2} minWidth={1 / 2} m={2} {...props}>
      <HotKeys allowChanges keyMap={keyMap} handlers={keyHandlers}>
        <Card ref={innerRef} tabIndex={0}>
          {message}
          {settingsSchema === undefined ? null : (
            <ErrorBoundary
              FallbackComponent={SettingsFallback}
              onError={(error: Error, componentStack: string): void => {
                setHasSettings(false)
                errorHandler(error, componentStack)
              }}
            >
              <Settings
                title={`${displayName} Settings`}
                open={showSettingsDialog}
                settings={settings}
                schema={settingsSchema}
                onSubmit={handleSetSettings}
                onClose={closeSettingsDialog}
                editable={editable}
              />
            </ErrorBoundary>
          )}
          <Header
            displayName={displayName}
            displaySub={displaySub}
            isActive={isFocus || isHovering}
            editable={editable}
            hasSettings={hasSettings}
            openNameDialog={openNameDialog}
            openSettingsDialog={openSettingsDialog}
            onDelete={handleDelete}
          />
          <CardContent>
            <Column>
              <Box flexGrow="1" mb={2}>
                <Typography size={-1}>
                  {description === undefined ? 'No description' : description}
                </Typography>
              </Box>
              <Row flexWrap="none" pb={1} overflow="auto">
                {(tags ?? []).map((tag) => (
                  <Chip mr={1} key={tag} size="small" label={tag} />
                ))}
              </Row>
            </Column>
          </CardContent>
        </Card>
      </HotKeys>
      {setName === undefined ? null : (
        <NameDialog
          title={`${type} Name`}
          description="Set the name of the pipeline component."
          current={displayName}
          open={showNameDialog}
          onSave={handleSetName}
          onClose={closeNameDialog}
        />
      )}
    </Box>
  )
})
Example #21
Source File: RelatedPage.tsx    From covidex with MIT License 4 votes vote down vote up
RelatedPage = () => {
  const {
    params: { articleId },
  } = useRouteMatch<any>();

  const [loading, setLoading] = useState<boolean>(false);
  const [notFound, setNotFound] = useState<boolean>(false);
  const [hasMore, setHasMore] = useState<boolean>(true);
  const [page, setPage] = useState<number>(1);
  const [queryId, setQueryId] = useState<string>('');

  const [originalArticle, setOriginalArticle] = useState<RelatedArticle | null>(null);
  const [relatedArticles, setRelatedArticles] = useState<RelatedArticle[] | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      if (articleId === undefined || articleId === null || articleId === '') {
        setLoading(false);
        setNotFound(true);
        setPage(1);
        return;
      }

      try {
        setLoading(true);
        setRelatedArticles(null);

        let response = await fetch(
          `${API_BASE}${RELATED_ENDPOINT}/${articleId.toLowerCase()}?page_number=${1}`,
        );
        setLoading(false);

        let data = await response.json();
        const { query_id, response: responseArticles } = data;
        const originalArticle = responseArticles
          ? responseArticles.find((a: RelatedArticle) => a.id === articleId)
          : null;

        setQueryId(query_id);
        setOriginalArticle(originalArticle);
        setRelatedArticles(responseArticles.filter((a: RelatedArticle) => a.id !== articleId));
        setPage(2);
      } catch {
        setLoading(false);
        setNotFound(true);
        setPage(2);
      }
    };

    fetchData();
  }, [articleId]);

  const loadMoreResults = async () => {
    let response = await fetch(
      `${API_BASE}${RELATED_ENDPOINT}/${articleId.toLowerCase()}?page_number=${page}`,
    );
    setPage(page + 1);

    if (response.status > 400) {
      setHasMore(false);
    }

    let data = await response.json();
    const { response: responseArticles } = data;
    const currentArticles = relatedArticles || [];
    setRelatedArticles([...currentArticles, ...responseArticles]);
  };

  const TitleRow = (
    <Row>
      <RelatedTitle>
        Related Articles <FileText size={24} style={{ marginLeft: '8px' }} />
      </RelatedTitle>
      <SearchLink to={HOME_ROUTE}>
        <ArrowLeft size={16} style={{ marginRight: '4px' }} />
        Search All Articles
      </SearchLink>
    </Row>
  );

  return (
    <PageWrapper>
      <PageContent>
        <ErrorBoundary FallbackComponent={NotFoundComponent}>
          <RelatedContent>
            {loading && <Loading />}
            {notFound && (
              <>
                {TitleRow}
                <NotFoundComponent />
              </>
            )}
            {originalArticle && relatedArticles && (
              <>
                {TitleRow}
                <OriginalArticle>
                  <SmallTitle>Showing articles related to:</SmallTitle>
                  <ArticleInfo article={originalArticle} boldTitle />
                  {originalArticle.abstract && (
                    <>
                      <AbstractTitle className="hideCollapsed">Abstract</AbstractTitle>
                      <Paragraph>{parseAbstract(originalArticle.abstract)}</Paragraph>
                    </>
                  )}
                </OriginalArticle>
                <InfiniteScroll
                  pageStart={page}
                  loadMore={loadMoreResults}
                  hasMore={hasMore}
                  loader={
                    <Row>
                      <Loading />
                    </Row>
                  }
                >
                  {relatedArticles.map((article, idx) => (
                    <RelatedResult
                      key={article.id}
                      article={article}
                      position={idx}
                      queryId={queryId}
                    />
                  ))}
                </InfiniteScroll>
                {relatedArticles.length === 0 && <NotFound>No related articles found</NotFound>}
              </>
            )}
          </RelatedContent>
        </ErrorBoundary>
      </PageContent>
    </PageWrapper>
  );
}
Example #22
Source File: index.tsx    From mui-toolpad with MIT License 4 votes vote down vote up
function CodeComponentEditorContent({ theme, codeComponentNode }: CodeComponentEditorContentProps) {
  const domApi = useDomApi();

  const [input, setInput] = React.useState<string>(codeComponentNode.attributes.code.value);

  const frameRef = React.useRef<HTMLIFrameElement>(null);

  const editorRef = React.useRef<monacoEditor.editor.IStandaloneCodeEditor>();

  usePageTitle(`${codeComponentNode.name} | Toolpad editor`);

  const updateInputExtern = React.useCallback((newInput) => {
    const editor = editorRef.current;
    if (!editor) {
      return;
    }

    const model = editor.getModel();
    if (!model) {
      return;
    }

    // Used to restore cursor position
    const state = editorRef.current?.saveViewState();

    editor.executeEdits(null, [
      {
        range: model.getFullModelRange(),
        text: newInput,
      },
    ]);

    if (state) {
      editorRef.current?.restoreViewState(state);
    }
  }, []);

  const handleSave = React.useCallback(() => {
    const pretty = tryFormat(input);
    updateInputExtern(pretty);
    domApi.setNodeNamespacedProp(
      codeComponentNode,
      'attributes',
      'code',
      appDom.createConst(pretty),
    );
  }, [codeComponentNode, domApi, input, updateInputExtern]);

  const allChangesAreCommitted = codeComponentNode.attributes.code.value === input;

  usePrompt(
    'Your code has unsaved changes. Are you sure you want to navigate away? All changes will be discarded.',
    !allChangesAreCommitted,
  );

  useShortcut({ code: 'KeyS', metaKey: true }, handleSave);

  const HandleEditorMount = React.useCallback(
    (editor: monacoEditor.editor.IStandaloneCodeEditor, monaco: typeof monacoEditor) => {
      editorRef.current = editor;

      editor.updateOptions({
        minimap: { enabled: false },
        accessibilitySupport: 'off',
      });

      monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
        target: monaco.languages.typescript.ScriptTarget.Latest,
        allowNonTsExtensions: true,
        moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
        module: monaco.languages.typescript.ModuleKind.CommonJS,
        noEmit: true,
        esModuleInterop: true,
        jsx: monaco.languages.typescript.JsxEmit.React,
        reactNamespace: 'React',
        allowJs: true,
        typeRoots: ['node_modules/@types'],
      });

      monaco.languages.typescript.typescriptDefaults.addExtraLib(`declare module "https://*";`);

      monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
        noSemanticValidation: false,
        noSyntaxValidation: false,
      });

      fetch('/typings.json')
        .then((res) => res.json())
        .then((typings) => {
          Array.from(Object.entries(typings)).forEach(([path, content]) => {
            monaco.languages.typescript.typescriptDefaults.addExtraLib(
              content as string,
              `file:///${path}`,
            );
          });
        })
        .catch((err) =>
          console.error(`Failed to initialize typescript types on editor: ${err.message}`),
        );
    },
    [],
  );

  const [iframeLoaded, onLoad] = React.useReducer(() => true, false);

  React.useEffect(() => {
    const document = frameRef.current?.contentDocument;
    // When we hydrate the iframe then the load event is already dispatched
    // once the iframe markup is parsed (maybe later but the important part is
    // that it happens before React can attach event listeners).
    // We need to check the readyState of the document once the iframe is mounted
    // and "replay" the missed load event.
    // See https://github.com/facebook/react/pull/13862 for ongoing effort in React
    // (though not with iframes in mind).
    if (document?.readyState === 'complete' && !iframeLoaded) {
      onLoad();
    }
  }, [iframeLoaded]);

  const frameDocument = frameRef.current?.contentDocument;

  const { Component: GeneratedComponent, error: compileError } = useCodeComponent(input);

  const CodeComponent: ToolpadComponent<any> = useLatest(GeneratedComponent) || Noop;
  const { argTypes } = CodeComponent[TOOLPAD_COMPONENT];

  const defaultProps = React.useMemo(
    () => mapValues(argTypes, (argType) => argType?.defaultValue),
    [argTypes],
  );

  return (
    <React.Fragment>
      <Stack sx={{ height: '100%' }}>
        <Toolbar sx={{ mt: 2 }}>
          <NodeNameEditor node={codeComponentNode} sx={{ maxWidth: 300 }} />
        </Toolbar>
        <Toolbar>
          <Button disabled={allChangesAreCommitted} onClick={handleSave}>
            Update
          </Button>
        </Toolbar>
        <Box flex={1} display="flex">
          <Box flex={1}>
            <Editor
              height="100%"
              defaultValue={input}
              onChange={(newValue) => setInput(newValue || '')}
              path="./component.tsx"
              language="typescript"
              onMount={HandleEditorMount}
            />
          </Box>
          <Box sx={{ flex: 1, position: 'relative' }}>
            <CanvasFrame ref={frameRef} title="Code component sandbox" onLoad={onLoad} />
          </Box>
        </Box>
      </Stack>
      {iframeLoaded && frameDocument
        ? ReactDOM.createPortal(
            <FrameContent document={frameDocument}>
              <React.Suspense fallback={null}>
                <ErrorBoundary
                  resetKeys={[CodeComponent]}
                  fallbackRender={({ error: runtimeError }) => (
                    <React.Fragment>{runtimeError.message}</React.Fragment>
                  )}
                >
                  <AppThemeProvider node={theme}>
                    <CodeComponent {...defaultProps} />
                  </AppThemeProvider>
                </ErrorBoundary>
                {compileError?.message}
              </React.Suspense>
            </FrameContent>,
            frameDocument.body,
          )
        : null}
    </React.Fragment>
  );
}
Example #23
Source File: HomePage.tsx    From covidex with MIT License 4 votes vote down vote up
HomePage = () => {
  const urlParams = new URLSearchParams(useLocation().search);
  const query = urlParams.get('query') || '';

  const [loading, setLoading] = useState<Boolean>(false);
  const [queryInputText, setQueryInputText] = useState<string>(query || '');
  const [selectedVertical, setSelectedVertical] = useState<SearchVerticalOption>({
    value: 'dataset',
    label: Configuration[METADATA]['dataset'],
  });

  const [filters, setFilters] = useState<SearchFilters>({});
  const [selectedFilters, setSelectedFilters] = useState<SearchFilters>({});

  const [queryId, setQueryId] = useState<string>('');
  const [searchResults, setSearchResults] = useState<SearchArticle[] | null>(null);

  useEffect(() => {
    setQueryInputText(query);
  }, [query]);

  useEffect(() => {
    const fetchData = async (query: string | null) => {
      if (query === null || query === '') {
        setLoading(false);
        setSearchResults([]);
        return;
      }

      try {
        setLoading(true);
        setSearchResults(null);

        let response = await fetch(`${API_BASE}${SEARCH_ENDPOINT}?query=${query.toLowerCase()}`);
        setLoading(false);

        let data = await response.json();
        const { query_id, response: searchResults } = data;
        const filters = getSearchFilters(searchResults);

        // Set default filters
        let defaultSelectedFilters: SearchFilters = {};
        const fields = Object.keys(filterSchema);
        fields.forEach((field) => {
          if (filterSchema[field].type === 'year_slider') {
            // Default to maximum range
            defaultSelectedFilters[field] = filters[field];
          } else if (filterSchema[field].type === 'selection') {
            defaultSelectedFilters[field] = new Set([]);
          }
        });

        setQueryId(query_id);
        setSearchResults(searchResults);
        setSelectedFilters(defaultSelectedFilters);
        setFilters(filters);
      } catch (err) {
        setLoading(false);
        setSearchResults([]);
      }
    };
    fetchData(query);
  }, [query]);

  const queryTokens = tokenize(query);
  const filteredResults =
    searchResults === null
      ? null
      : searchResults.filter((article) => filterArticle(selectedFilters, article));

  return (
    <PageWrapper>
      <PageContent>
        <SearchBar
          query={queryInputText}
          vertical={selectedVertical}
          setQuery={setQueryInputText}
          setVertical={setSelectedVertical}
        />
        <ErrorBoundary FallbackComponent={() => <NoResults>Error retrieving results</NoResults>}>
          {loading && <Loading />}
          <HomeContent>
            {!query && <HomeText />}
            {query && searchResults !== null && searchResults.length > 0 && (
              <Filters
                filters={filters}
                selectedFilters={selectedFilters}
                setSelectedFilters={setSelectedFilters}
              />
            )}
            {query &&
              filteredResults !== null &&
              (searchResults === null || filteredResults.length === 0 ? (
                <NoResults>No results found</NoResults>
              ) : (
                <>
                  <SearchResults>
                    {filteredResults.map((article, i) => (
                      <SearchResult
                        key={i}
                        article={article}
                        position={i}
                        queryTokens={queryTokens}
                        queryId={queryId}
                      />
                    ))}
                  </SearchResults>
                </>
              ))}
          </HomeContent>
        </ErrorBoundary>
      </PageContent>
    </PageWrapper>
  );
}