Skip to content

Commit

Permalink
Merge pull request #83 from shapehq/feature/stoplight
Browse files Browse the repository at this point in the history
Embeds Redoc viewer in iframe
  • Loading branch information
simonbs authored Oct 27, 2023
2 parents 4470eec + 6dbd147 commit 84ed6a3
Show file tree
Hide file tree
Showing 19 changed files with 234 additions and 89 deletions.
16 changes: 16 additions & 0 deletions src/app/documentation-viewer/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import DocumentationViewer from "@/features/docs/view/DocumentationViewer"

type SearchParams = { visualizer: string, url: string }

export default async function Page({
searchParams
}: {
searchParams: SearchParams
}) {
return (
<DocumentationViewer
visualizer={parseInt(searchParams.visualizer)}
url={searchParams.url}
/>
)
}
19 changes: 19 additions & 0 deletions src/common/loading/DelayedLoadingIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useState, useEffect } from "react"
import LoadingIndicator from "./LoadingIndicator"

const DelayedLoadingIndicator = ({
delay
}: {
delay?: number
}) => {
const [isVisible, setVisible] = useState(false)
useEffect(() => {
const timer = setTimeout(() => {
setVisible(true)
}, delay || 1000)
return () => clearTimeout(timer)
}, [delay, setVisible])
return <>{isVisible && <LoadingIndicator/>}</>
}

export default DelayedLoadingIndicator
42 changes: 42 additions & 0 deletions src/common/loading/LoadingIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useState, useEffect } from "react"
import { Box, Typography } from "@mui/material"
import { useTheme } from "@mui/material/styles"

const LoadingIndicator = () => {
const theme = useTheme()
const [count, setCount] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
if (count == 3) {
setCount(0)
} else {
setCount(count + 1)
}
}, 200)
return () => clearTimeout(timer)
}, [count, setCount])
return (
<Box style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100%",
width: "100%",
background: theme.palette.background.default
}}>
{Array.from(Array(3).keys()).map((e) => {
return (
<Typography
key={count}
variant="h3"
sx={{ opacity: e + 1 == count ? 0.5 : 0.2 }}
>
</Typography>
)
})}
</Box>
)
}

export default LoadingIndicator
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import Swagger from "./Swagger"
"use client"

import Redocly from "./Redocly"
import Swagger from "./Swagger"
import DocumentationVisualizer from "@/features/settings/domain/DocumentationVisualizer"
import useDocumentationVisualizer from "@/features/settings/data/useDocumentationVisualizer"

const DocumentationViewer = ({ url }: { url: string }) => {
const [documentationVisualizer] = useDocumentationVisualizer()
switch (documentationVisualizer) {
case DocumentationVisualizer.SWAGGER:
return <Swagger url={url} />
const DocumentationViewer = ({
visualizer,
url
}: {
visualizer: DocumentationVisualizer,
url: string
}) => {
switch (visualizer) {
case DocumentationVisualizer.REDOCLY:
return <Redocly url={url} />
case DocumentationVisualizer.SWAGGER:
return <Swagger url={url} />
}
}

Expand Down
32 changes: 32 additions & 0 deletions src/features/docs/view/LoadingWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ReactNode } from "react"
import { Box } from "@mui/material"
import LoadingIndicator from "@/common/loading/LoadingIndicator"

const LoadingWrapper = ({
showLoadingIndicator,
children
}: {
showLoadingIndicator: boolean,
children: ReactNode
}) => {
return (
<Box sx={{ width: "100%", height: "100%", position: "relative", overflow: "scroll" }}>
{showLoadingIndicator &&
<Box sx={{ width: "100%", height: "100%", position: "absolute" }}>
<LoadingIndicator/>
</Box>
}
<Box sx={{
width: "100%",
height: "100%",
position: "absolute",
background: "white",
opacity: showLoadingIndicator ? 0 : 1
}}>
{children}
</Box>
</Box>
)
}

export default LoadingWrapper
18 changes: 18 additions & 0 deletions src/features/docs/view/Redocly.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useState } from "react"
import { RedocStandalone } from "redoc"
import LoadingWrapper from "./LoadingWrapper"

const Redocly = ({ url }: { url: string }) => {
const [isLoading, setLoading] = useState(true)
return (
<LoadingWrapper showLoadingIndicator={isLoading}>
<RedocStandalone
specUrl={url}
options={{ hideLoading: true }}
onLoaded={() => setLoading(false)}
/>
</LoadingWrapper>
)
}

export default Redocly
15 changes: 15 additions & 0 deletions src/features/docs/view/Swagger.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useState } from "react"
import SwaggerUI from "swagger-ui-react"
import "swagger-ui-react/swagger-ui.css"
import LoadingWrapper from "./LoadingWrapper"

const Swagger = ({ url }: { url: string }) => {
const [isLoading, setLoading] = useState(true)
return (
<LoadingWrapper showLoadingIndicator={isLoading}>
<SwaggerUI url={url} onComplete={() => setLoading(false)} />
</LoadingWrapper>
)
}

export default Swagger
30 changes: 0 additions & 30 deletions src/features/projects/view/DelayedLoading.tsx

This file was deleted.

16 changes: 16 additions & 0 deletions src/features/projects/view/Documentation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import DocumentationViewer from "@/features/docs/view/DocumentationViewer"
import DocumentationIframe from "./DocumentationIframe"
import DocumentationVisualizer from "@/features/settings/domain/DocumentationVisualizer"
import useDocumentationVisualizer from "@/features/settings/data/useDocumentationVisualizer"

const Documentation = ({ url }: { url: string }) => {
const [visualizer] = useDocumentationVisualizer()
switch (visualizer) {
case DocumentationVisualizer.REDOCLY:
return <DocumentationIframe visualizer={visualizer} url={url} />
case DocumentationVisualizer.SWAGGER:
return <DocumentationViewer visualizer={visualizer} url={url} />
}
}

export default Documentation
28 changes: 28 additions & 0 deletions src/features/projects/view/DocumentationIframe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Box } from "@mui/material"
import DelayedLoadingIndicator from "@/common/loading/DelayedLoadingIndicator"
import DocumentationVisualizer from "@/features/settings/domain/DocumentationVisualizer"

const DocumentationIframe = ({
visualizer,
url
}: {
visualizer: DocumentationVisualizer,
url: string
}) => {
const searchParams = new URLSearchParams()
searchParams.append("visualizer", visualizer.toString())
searchParams.append("url", url)
return (
<Box sx={{ width: "100%", height: "100%", position: "relative" }}>
<Box sx={{ width: "100%", height: "100%", position: "absolute" }}>
<DelayedLoadingIndicator/>
</Box>
<iframe
src={`/documentation-viewer?${searchParams.toString()}`}
style={{ width: "100%", height: "100%", position: "absolute" }}
/>
</Box>
)
}

export default DocumentationIframe
8 changes: 4 additions & 4 deletions src/features/projects/view/MainContent.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Project from "../domain/Project"
import Version from "../domain/Version"
import OpenApiSpecification from "../domain/OpenApiSpecification"
import DelayedLoading from "./DelayedLoading"
import DelayedLoadingIndicator from "@/common/loading/DelayedLoadingIndicator"
import ErrorMessage from "./ErrorMessage"
import DocumentationViewer from "./docs/DocumentationViewer"
import Documentation from "./Documentation"

const MainContent = ({
isLoading,
Expand All @@ -19,9 +19,9 @@ const MainContent = ({
specification?: OpenApiSpecification
}) => {
if (project && version && specification) {
return <DocumentationViewer url={specification.url}/>
return <Documentation url={specification.url}/>
} else if (isLoading) {
return <DelayedLoading/>
return <DelayedLoadingIndicator/>
} else if (error) {
return <ErrorMessage text={error.message}/>
} else if (!project) {
Expand Down
4 changes: 2 additions & 2 deletions src/features/projects/view/client/ProjectsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import SidebarContainer from "@/features/sidebar/view/client/SidebarContainer"
import Project from "../../domain/Project"
import ProjectList from "../ProjectList"
import MainContent from "../MainContent"
import MobileToolbar from "../MobileToolbar"
import TrailingToolbarItem from "../TrailingToolbarItem"
import MobileToolbar from "../toolbar/MobileToolbar"
import TrailingToolbarItem from "../toolbar/TrailingToolbarItem"
import getSelection from "../../domain/getSelection"
import projectNavigator from "../../domain/projectNavigator"
import updateWindowTitle from "../../domain/updateWindowTitle"
Expand Down
7 changes: 0 additions & 7 deletions src/features/projects/view/docs/Redocly.tsx

This file was deleted.

8 changes: 0 additions & 8 deletions src/features/projects/view/docs/Swagger.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Stack } from "@mui/material"
import Project from "../domain/Project"
import Version from "../domain/Version"
import OpenApiSpecification from "../domain/OpenApiSpecification"
import VersionSelector from "./docs/VersionSelector"
import SpecificationSelector from "./docs/SpecificationSelector"
import Project from "../../domain/Project"
import Version from "../../domain/Version"
import OpenApiSpecification from "../../domain/OpenApiSpecification"
import VersionSelector from "./VersionSelector"
import SpecificationSelector from "./SpecificationSelector"

const MobileToolbar = ({
project,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { SxProps } from "@mui/system"
import { Stack, IconButton, Typography, Link } from "@mui/material"
import Project from "../domain/Project"
import Version from "../domain/Version"
import OpenApiSpecification from "../domain/OpenApiSpecification"
import VersionSelector from "./docs/VersionSelector"
import SpecificationSelector from "./docs/SpecificationSelector"
import Project from "../../domain/Project"
import Version from "../../domain/Version"
import OpenApiSpecification from "../../domain/OpenApiSpecification"
import VersionSelector from "./VersionSelector"
import SpecificationSelector from "./SpecificationSelector"
import EditIcon from "@mui/icons-material/Edit"

const TrailingToolbarItem = ({
Expand Down
40 changes: 19 additions & 21 deletions src/features/settings/view/DocumentationVisualizationPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
import { ToggleButtonGroup, ToggleButton } from "@mui/material"
import { FormControl, Select, MenuItem, SelectChangeEvent } from "@mui/material"
import DocumentationVisualizer from "../domain/DocumentationVisualizer"
import useDocumentationVisualizer from "@/features/settings/data/useDocumentationVisualizer"

const DocumentationVisualizationPicker: React.FC = () => {
const [value, setValue] = useDocumentationVisualizer()
const handleChange = (
_event: React.MouseEvent<HTMLElement>,
documentationVisualizer: DocumentationVisualizer
) => {
setValue(documentationVisualizer)
const handleChange = (event: SelectChangeEvent) => {
setValue(parseInt(event.target.value))
}
return (
<ToggleButtonGroup
exclusive
value={value}
onChange={handleChange}
fullWidth={true}
color="secondary"
aria-label="Viewer"
>
<ToggleButton value={DocumentationVisualizer.SWAGGER}>
Swagger
</ToggleButton>
<ToggleButton value={DocumentationVisualizer.REDOCLY}>
Redocly
</ToggleButton>
</ToggleButtonGroup>
<FormControl fullWidth sx={{ m: 1, minWidth: 120, margin: 0 }} size="small">
<Select defaultValue={value.toString()} onChange={handleChange}>
<MenuItem
key={DocumentationVisualizer.REDOCLY}
value={DocumentationVisualizer.REDOCLY.toString()}
>
Redocly
</MenuItem>
<MenuItem
key={DocumentationVisualizer.SWAGGER}
value={DocumentationVisualizer.SWAGGER.toString()}
>
Swagger
</MenuItem>
</Select>
</FormControl>
)
}

Expand Down

0 comments on commit 84ed6a3

Please sign in to comment.