Skip to content

Commit

Permalink
ux: add reconnecting websocket and reloading toast to local preview (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored May 20, 2024
1 parent 25bd239 commit 3e3bd78
Show file tree
Hide file tree
Showing 14 changed files with 537 additions and 189 deletions.
11 changes: 7 additions & 4 deletions packages/ui/app/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { withThemeByClassName } from "@storybook/addon-themes";
import type { Preview } from "@storybook/react";
import { ThemeProvider } from "next-themes";
import React from "react";
import { Toaster } from "../src/components/FernToast";
import { FernTooltipProvider } from "../src/components/FernTooltip";
Expand All @@ -8,10 +9,12 @@ import "./variables.css";

const globalDecorator = (Story) => (
<React.Fragment>
<FernTooltipProvider>
<Story />
<Toaster />
</FernTooltipProvider>
<ThemeProvider>
<FernTooltipProvider>
<Story />
<Toaster />
</FernTooltipProvider>
</ThemeProvider>
</React.Fragment>
);
export const decorators = [
Expand Down
2 changes: 0 additions & 2 deletions packages/ui/app/src/commons/FontAwesomeIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ function getIconUrl(icon: string | undefined): string {
function getCdnHost() {
const CDN_HOST = process.env.NEXT_PUBLIC_FONTAWESOME_CDN_HOST;
if (CDN_HOST == null) {
// eslint-disable-next-line no-console
console.error("NEXT_PUBLIC_FONTAWESOME_CDN_HOST is not set");
return "https://fontawesome-cdn.vercel.app";
}
return CDN_HOST;
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/app/src/components/FernToast.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { useTheme } from "next-themes";
import { FC } from "react";
import { AlertCircle, CheckCircle, Info, Loader, XCircle } from "react-feather";
import { Toaster as SonnerToaster } from "sonner";
export { toast } from "sonner";
export type { ToastT } from "sonner";

export const Toaster: FC = () => {
const { resolvedTheme: theme } = useTheme();
return (
<SonnerToaster
position="bottom-center"
theme="system"
theme={theme === "dark" ? "dark" : theme === "light" ? "light" : "system"}
toastOptions={{
unstyled: true,
classNames: {
Expand Down
15 changes: 15 additions & 0 deletions packages/ui/app/src/contexts/LocalPreviewContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createContext, useContext } from "react";

interface LocalPreviewContextValue {
isLocalPreview: boolean;
}

const LocalPreviewContext = createContext<LocalPreviewContextValue>({
isLocalPreview: false,
});

export const LocalPreviewContextProvider = LocalPreviewContext.Provider;

export function useLocalPreviewContext(): LocalPreviewContextValue {
return useContext(LocalPreviewContext);
}
2 changes: 1 addition & 1 deletion packages/ui/app/src/docs/ThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ThemeProvider as NextThemeProvider, useTheme } from "next-themes";
import { PropsWithChildren, ReactElement, useEffect, useMemo } from "react";

interface ThemeProviderProps {
colors: ColorsConfig;
colors: ColorsConfig | undefined;
}

export function ThemeProvider({ colors, children }: PropsWithChildren<ThemeProviderProps>): ReactElement {
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/app/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export { Stream } from "./api-playground/Stream";
export type { ProxyRequest, ProxyResponse } from "./api-playground/types";
export { toast } from "./components/FernToast";
export { DEFAULT_FEATURE_FLAGS } from "./contexts/FeatureFlagContext";
export type { FeatureFlags } from "./contexts/FeatureFlagContext";
export { LocalPreviewContextProvider } from "./contexts/LocalPreviewContext";
export * from "./next-app/DocsPage";
export { NextApp } from "./next-app/NextApp";
export { ApiDefinitionResolver } from "./resolver/ApiDefinitionResolver";
Expand Down
2 changes: 0 additions & 2 deletions packages/ui/app/src/next-app/DocsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { ColorsConfig, SidebarNavigation } from "@fern-ui/fdr-utils";
import { useDeepCompareMemoize } from "@fern-ui/react-commons";
import { Redirect } from "next";
import { ReactElement } from "react";
import { Toaster } from "../components/FernToast";
import { FeatureFlagContext, FeatureFlags } from "../contexts/FeatureFlagContext";
import { DocsContextProvider } from "../contexts/docs-context/DocsContextProvider";
import { NavigationContextProvider } from "../contexts/navigation-context/NavigationContextProvider";
Expand Down Expand Up @@ -56,7 +55,6 @@ export function DocsPage(pageProps: DocsPage.Props): ReactElement | null {
<Docs logoHeight={logoHeight} logoHref={logoHref} />
</NavigationContextProvider>
</DocsContextProvider>
<Toaster />
</FeatureFlagContext.Provider>
);
}
Expand Down
31 changes: 19 additions & 12 deletions packages/ui/app/src/next-app/NextApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ReactElement, useEffect } from "react";
import DatadogInit from "../analytics/datadog";
import { initializePosthog } from "../analytics/posthog";
import { FernErrorBoundary } from "../components/FernErrorBoundary";
import { Toaster } from "../components/FernToast";
import { LayoutBreakpointProvider } from "../contexts/layout-breakpoint/LayoutBreakpointProvider";
import { IsReadyProvider } from "../contexts/useIsReady";
import { RouteListenerContextProvider } from "../contexts/useRouteListener";
Expand All @@ -17,7 +18,7 @@ import "./globals.scss";

const store = createStore();

export function NextApp({ Component, pageProps, router }: AppProps<DocsPage.Props>): ReactElement {
export function NextApp({ Component, pageProps, router }: AppProps<DocsPage.Props | undefined>): ReactElement {
useEffect(() => {
initializePosthog();
}, []);
Expand All @@ -26,25 +27,26 @@ export function NextApp({ Component, pageProps, router }: AppProps<DocsPage.Prop
// We need to intercept how prefetching is done and modify the hrefs to include the subpath.
useInterceptNextDataHref({
router,
basePath: pageProps.baseUrl?.basePath,
host: pageProps.baseUrl?.domain,
basePath: pageProps?.baseUrl?.basePath,
host: pageProps?.baseUrl?.domain,
});

return (
<TooltipProvider>
<FernErrorBoundary className="flex h-screen items-center justify-center" refreshOnError>
<ThemeProvider colors={pageProps.colors}>
<ThemeProvider colors={pageProps?.colors}>
<IsReadyProvider>
<RouteListenerContextProvider>
<DatadogInit />
<JotaiProvider store={store}>
<LayoutBreakpointProvider>
<NextNProgress options={{ showSpinner: false, speed: 400 }} showOnShallow={false} />
<Component {...pageProps} />
{pageProps != null && <Component {...pageProps} />}
</LayoutBreakpointProvider>
</JotaiProvider>
</RouteListenerContextProvider>
</IsReadyProvider>
<Toaster />
</ThemeProvider>
</FernErrorBoundary>
</TooltipProvider>
Expand All @@ -62,14 +64,19 @@ const useInterceptNextDataHref = ({
host: string | undefined;
}) => {
useEffect(() => {
if (basePath != null && basePath !== "" && basePath !== "/" && router.pageLoader?.getDataHref) {
const prefixedBasePath = basePath.startsWith("/") ? basePath : `/${basePath}`;
try {
if (basePath != null && basePath !== "" && basePath !== "/" && router.pageLoader?.getDataHref) {
const prefixedBasePath = basePath.startsWith("/") ? basePath : `/${basePath}`;

const originalGetDataHref = router.pageLoader.getDataHref;
router.pageLoader.getDataHref = function (...args: Parameters<PageLoader["getDataHref"]>) {
const r = originalGetDataHref.call(router.pageLoader, ...args);
return r && r.startsWith("/_next/data") ? fixHost(`${prefixedBasePath}${r}`, host) : r;
};
const originalGetDataHref = router.pageLoader.getDataHref;
router.pageLoader.getDataHref = function (...args: Parameters<PageLoader["getDataHref"]>) {
const r = originalGetDataHref.call(router.pageLoader, ...args);
return r && r.startsWith("/_next/data") ? fixHost(`${prefixedBasePath}${r}`, host) : r;
};
}
} catch (e) {
// eslint-disable-next-line no-console
console.error("Failed to intercept next data href", e);
}
}, [router, basePath, host]);
};
Expand Down
8 changes: 7 additions & 1 deletion packages/ui/app/src/services/useSearchService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { atom, useAtom, useAtomValue } from "jotai";
import { once } from "lodash-es";
import { useEffect, useMemo } from "react";
import { captureSentryError } from "../analytics/sentry";
import { useLocalPreviewContext } from "../contexts/LocalPreviewContext";
import { useDocsContext } from "../contexts/docs-context/useDocsContext";
import { getEnvConfig, type EnvironmentConfig } from "../env";
import { REGISTRY_SERVICE } from "./registry";
Expand Down Expand Up @@ -59,8 +60,13 @@ export function useSearchService(): SearchService {
export function useCreateSearchService(currentVersionIndex: number | undefined): void {
const { searchInfo, versions } = useDocsContext();
const [, setSearchService] = useAtom(SEARCH_SERVICE_ATOM);
const { isLocalPreview } = useLocalPreviewContext();

const searchService = useMemo<SearchService>(() => {
if (isLocalPreview) {
return { isAvailable: false };
}

try {
const envConfig = getEnvConfig();
if (typeof searchInfo !== "object" || searchInfo.type === "legacyMultiAlgoliaIndex") {
Expand Down Expand Up @@ -110,7 +116,7 @@ export function useCreateSearchService(currentVersionIndex: number | undefined):

return { isAvailable: false };
}
}, [currentVersionIndex, searchInfo, versions]);
}, [currentVersionIndex, isLocalPreview, searchInfo, versions]);

useEffect(() => {
setSearchService(searchService);
Expand Down
1 change: 1 addition & 0 deletions packages/ui/local-preview-bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@emotion/is-prop-valid": "^1.2.2",
"@fern-api/fdr-sdk": "workspace:*",
"@fern-ui/fdr-utils": "workspace:*",
"@fern-ui/loadable": "workspace:*",
"@fern-ui/ui": "workspace:*",
"cssnano": "^6.0.3",
"jsonpath": "^1.1.1",
Expand Down
Loading

0 comments on commit 3e3bd78

Please sign in to comment.