Skip to content

Commit

Permalink
[ENG-1315] Generated Snippets in non-SDK languages in API portal (#310)
Browse files Browse the repository at this point in the history
* save

* cleanup

* refactor

* export prism languages

* fix layered border

* TODO: add tailwind

* remove unused css file

* add tailwindcss

* stop jumpy effect on execute output

* remove unused imports

* support dark class in tailwind

* stop from tailwind styled components from flashing white

* reuse generateMantineThemeColors

* integrate headless ui for tabs

* fix some styles

* TODO: configure brand coloring in tailwind

* brand colors from tailwind

* polish

* polish

* make request/response sticky only

* make code font size smaller

* polish

* yarn add httpsnippet

* TODO: ensure curl output is correct

* fix SSR warning

* fix styling in light mode

* support security requirements in curl

* TODO: fixed nested values

* use version 18

* remove unexpected input

* fix nested values not being pruned

* responsive text size for generated code

* masked security

* match radius

* fix deeply nested values from having empty properties

* add content-type to curl generation

* 10x faster

* form data working

* remove empty values in requestBodyValue

* clearing file input actually removes file

* replace prism copy button with custom copy button

* fix bug where going to curl tab modifies form values

* stylle operation request

* remove console.log

* fix typescript generation

* add c# + java

* all language support

* add padding to RHS of last language

* fix padding

* polish styling

* only text-sm for code

* hideNonSdkSnippets

* docs(changeset): add hideNonSdkSnippets configuration to API portal

---------

Co-authored-by: konfig-bot <[email protected]>
  • Loading branch information
dphuang2 and konfig-bot authored Oct 30, 2023
1 parent 787daba commit ce10a4a
Show file tree
Hide file tree
Showing 44 changed files with 1,911 additions and 477 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/konfig-api-portal-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ jobs:
strategy:
matrix:
os: ['ubuntu-latest']
node_version: [lts/*]
# major version 18
node_version: ['lts/hydrogen']
fail-fast: false
runs-on: ${{ matrix.os }}
env:
Expand All @@ -24,7 +25,6 @@ jobs:
node-version: ${{ matrix.node_version }}
cache: yarn
cache-dependency-path: generator/konfig-dash/yarn.lock
working-directory: generator/konfig-dash
- run: yarn install --network-timeout 600000
working-directory: generator/konfig-dash
- run: yarn build
Expand Down
5 changes: 5 additions & 0 deletions generator/konfig-dash/.changeset/clever-snakes-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'konfig-lib': minor
---

add hideNonSdkSnippets configuration to API portal
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ export const portal = z
"Relative path to logo image used for Konfig's API Portal. If an object is provided, the light logo will be used for light mode and the dark logo will be used for dark mode."
),
socials: socialObjectSchema.optional(),
hideNonSdkSnippets: z
.boolean()
.optional()
.describe(
'Do not show non-SDK snippets in the API Reference page of the API Portal. This is useful if your API is not easily usable without an SDK or if you do not want developers to use your API without an SDK.'
),
title: z.string().describe("Title to be used in Konfig's API Portal"),
documentation: documentation
.optional()
Expand Down
1 change: 1 addition & 0 deletions generator/konfig-next-app/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'ts-jest',
{
tsconfig: './tsconfig.jest.json',
isolatedModules: true,
},
],
},
Expand Down
10 changes: 9 additions & 1 deletion generator/konfig-next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"dependencies": {
"@emotion/react": "^11.11.0",
"@emotion/server": "^11.11.0",
"@headlessui/react": "^1.7.17",
"@headlessui/tailwindcss": "^0.2.0",
"@mantine/core": "^6.0.13",
"@mantine/dates": "^6.0.13",
"@mantine/form": "^6.0.13",
Expand All @@ -35,17 +37,18 @@
"@types/node": "20.2.5",
"@types/react": "18.2.8",
"@types/react-dom": "18.2.4",
"ajv": "^8.12.0",
"ajv-draft-04": "^1.0.0",
"axios": "^1.4.0",
"camelcase": "^8.0.0",
"chroma-js": "^2.4.2",
"clone": "^2.1.2",
"dayjs": "^1.11.8",
"deepmerge": "^4.3.1",
"eslint": "8.41.0",
"eslint-config-next": "13.4.4",
"github-slugger": "^2.0.0",
"hast-util-to-text": "^3.1.2",
"httpsnippet": "^3.0.1",
"js-yaml": "^4.1.0",
"konfig-lib": "link:../konfig-dash/packages/konfig-lib",
"localforage": "^1.10.0",
Expand Down Expand Up @@ -77,13 +80,18 @@
},
"devDependencies": {
"@types/chroma-js": "^2.4.0",
"@types/clone": "^2.1.3",
"@types/har-format": "^1.2.14",
"@types/jest": "^29.5.5",
"@types/js-yaml": "^4.0.5",
"@types/uuid": "^9.0.2",
"autoprefixer": "^10.4.16",
"babel-jest": "^29.7.0",
"concurrently": "^8.2.1",
"jest": "^29.7.0",
"postcss": "^8.4.31",
"prettier": "^3.0.2",
"tailwindcss": "^3.3.5",
"ts-jest": "^29.1.1"
}
}
6 changes: 6 additions & 0 deletions generator/konfig-next-app/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
8 changes: 8 additions & 0 deletions generator/konfig-next-app/src/components/CodeIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { linkColor } from '@/utils/link-color'
import { useMantineTheme } from '@mantine/core'
import { IconCode } from '@tabler/icons-react'

export function CodeIcon() {
const theme = useMantineTheme()
return <IconCode stroke={1.5} size="1.3rem" color={linkColor({ theme })} />
}
77 changes: 77 additions & 0 deletions generator/konfig-next-app/src/components/CopyButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { CopyButton as MantineCopyButton, clsx } from '@mantine/core'
import { notifications } from '@mantine/notifications'
import { CodeIcon } from './CodeIcon'
export function CopyButton({ value }: { value: string }) {
return (
<MantineCopyButton value={value}>
{({ copied, copy }) => (
<button
onClick={() => {
copy()
notifications.show({
id: 'code-copied-to-your-clipboard',
radius: 'md',
withBorder: true,
styles: {
body: {
fontWeight: 500,
},
icon: {
backgroundColor: 'transparent',
},
},
message: 'Code copied to your clipboard',
icon: <CodeIcon />,
})
}}
type="button"
className={clsx(
'group/button absolute right-4 top-3.5 overflow-hidden rounded-full py-1 pl-2 pr-3 text-xs font-medium opacity-0 backdrop-blur transition focus:opacity-100 group-hover:opacity-100 outline-brand-500 dark:outline-brand-700',
{
['bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 shadow dark:shadow-none dark:hover:bg-white/5']:
!copied,
['bg-brand-600/20 ring-1 ring-inset dark:ring-brand-400/20 ring-brand-600/40']:
copied,
}
)}
>
<span
aria-hidden={!copied ? 'false' : 'true'}
className={clsx(
'pointer-events-none flex items-center gap-0.5 dark:text-zinc-400 text-zinc-500 transition duration-300',
{ ['-translate-y-1.5 opacity-0']: copied }
)}
>
<svg
viewBox="0 0 20 20"
aria-hidden="true"
className="h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-700 dark:group-hover/button:stroke-zinc-400"
>
<path
strokeWidth="0"
d="M5.5 13.5v-5a2 2 0 0 1 2-2l.447-.894A2 2 0 0 1 9.737 4.5h.527a2 2 0 0 1 1.789 1.106l.447.894a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2Z"
></path>
<path
fill="none"
strokeLinejoin="round"
d="M12.5 6.5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2m5 0-.447-.894a2 2 0 0 0-1.79-1.106h-.527a2 2 0 0 0-1.789 1.106L7.5 6.5m5 0-1 1h-3l-1-1"
></path>
</svg>
Copy
</span>
<span
aria-hidden={!copied ? 'true' : 'false'}
className={clsx(
'pointer-events-none absolute inset-0 flex items-center justify-center text-brand-800 dark:text-brand-400 transition duration-300',
{
['translate-y-1.5 opacity-0']: !copied,
}
)}
>
Copied!
</span>
</button>
)}
</MantineCopyButton>
)
}
2 changes: 1 addition & 1 deletion generator/konfig-next-app/src/components/DemoButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const _DemoButton: Components['button'] = ({
}
return (
<>
<DemoOutput cell={cell} />
<MantineButton
loading={cell.running}
color={
Expand Down Expand Up @@ -56,6 +55,7 @@ const _DemoButton: Components['button'] = ({
>
{children}
</MantineButton>
<DemoOutput cell={cell} />
</>
)
}
Expand Down
20 changes: 15 additions & 5 deletions generator/konfig-next-app/src/components/DemoCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,20 @@ require('prismjs/components/prism-php')
require('prismjs/components/prism-shell-session')
require('prismjs/components/prism-java')

type Language = PrismProps['language']
export type Language = PrismProps['language']

export type LanguageExtended =
| Language
| 'ruby'
| 'csharp'
| 'php'
| 'shell'
| 'java'
| 'js'
| 'kotlin'
| 'swift'
| 'JSON'
| 'ts'

const langDisplayName = {
python: { name: 'Python' },
Expand Down Expand Up @@ -49,10 +62,7 @@ const langDisplayName = {
javascript: { name: 'JavaScript' },
js: { name: 'JavaScript' },
bash: { name: 'Bash' },
} as Record<
Language | 'ruby' | 'csharp' | 'php' | 'shell' | 'java' | 'js' | 'JSON',
{ name: string }
>
} as Record<LanguageExtended, { name: string }>

export const extractLanguageFromClassName = (className?: string) =>
/language-(\w+)/.exec(className || '')
Expand Down
23 changes: 17 additions & 6 deletions generator/konfig-next-app/src/components/DemoOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@ import { ExecuteOutput } from './ExecuteOutput'

export const DemoOutput = observer(({ cell }: { cell: CellState }) => {
return (
<ExecuteOutput
jsonOutput={cell.jsonOutput}
tableOutput={cell.tableOutput}
processedOutput={cell.processedOutput}
show={cell.show}
/>
// gets rid of:
// """"
// Warning: useLayoutEffect does nothing on the server, because its effect
// cannot be encoded into the server renderer's output format. This will
// lead to a mismatch between the initial, non-hydrated UI and the intended
// UI. To avoid this, useLayoutEffect should only be used in components that
// render exclusively on the client. See
// https://reactjs.org/link/uselayouteffect-ssr for common fixes.
// """"
cell.show && (
<ExecuteOutput
jsonOutput={cell.jsonOutput}
tableOutput={cell.tableOutput}
processedOutput={cell.processedOutput}
show={cell.show}
/>
)
)
})
6 changes: 3 additions & 3 deletions generator/konfig-next-app/src/components/ExecuteOutput.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMantineColorScheme, Transition, Tabs, Code } from '@mantine/core'
import { useState, useEffect, useCallback } from 'react'
import { useState, useCallback, useLayoutEffect } from 'react'
import { DemoTable } from './DemoTable'
import { tryTableOutput } from '@/utils/try-table-output'
import { tryJsonOutput } from '@/utils/try-json-output'
Expand Down Expand Up @@ -54,7 +54,7 @@ export function ExecuteOutput({
[isFocusedOnJson]
)

useEffect(() => {
useLayoutEffect(() => {
// Add an event listener when the component mounts
document.addEventListener('copy', onCopy)

Expand All @@ -64,7 +64,7 @@ export function ExecuteOutput({
}
}, [isFocusedOnJson, onCopy])

useEffect(() => {
useLayoutEffect(() => {
if (haveClickedTab) return
const newTab =
tableOutput !== null && !disableTable
Expand Down
3 changes: 3 additions & 0 deletions generator/konfig-next-app/src/components/HeaderTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ export function HeaderTab({
data-active={active}
aria-disabled={disabled}
onClick={handleClick}
style={{
marginBottom: hasLightAndDarkLogo ? -1 : undefined,
}}
className={cx(classes.tab, {
[hasLightDarkModeStyles.classes.color]: hasLightAndDarkLogo,
[colorStyles.classes.color]: !hasLightAndDarkLogo,
Expand Down
2 changes: 1 addition & 1 deletion generator/konfig-next-app/src/components/LinkIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { linkColor } from '@/utils/link-color'
import { useMantineColorScheme, useMantineTheme } from '@mantine/core'
import { useMantineTheme } from '@mantine/core'

export function LinkIcon() {
const theme = useMantineTheme()
Expand Down
27 changes: 17 additions & 10 deletions generator/konfig-next-app/src/components/OperationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { OperationParameter, Parameter } from './OperationParameter'
import { type SchemaObject } from 'konfig-lib'
import { generateParametersFromRequestBodyProperties } from '@/utils/generate-parameters-from-request-body-properties'

const useStyles = createStyles((theme) => ({
export const useBorderStyles = createStyles((theme) => ({
borderBottom: {
borderBottom: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.gray[9] : theme.colors.gray[1]
}`,
borderBottom: `1px solid`,
},
borderColor: {
borderColor:
theme.colorScheme === 'dark'
? theme.colors.gray[9]
: theme.colors.gray[1],
},
}))

Expand Down Expand Up @@ -95,20 +99,23 @@ function ParameterGroup({
owner: string
repo: string
}) {
const { classes, cx } = useStyles()
const { classes, cx } = useBorderStyles()
return (
parameters.length > 0 && (
<Box>
<Title mb="xl" order={6}>
<div className="text-xs text-mantine-gray-600 mb-6 font-semibold">
{title}
</Title>
</div>
<Stack spacing="xl">
{parameters.map((param, i) => (
<Box
key={param.name}
className={cx({
[classes.borderBottom]: i < parameters.length - 1,
})}
className={cx(
{
[classes.borderBottom]: i < parameters.length - 1,
},
classes.borderColor
)}
>
<OperationParameter owner={owner} repo={repo} param={param} />
</Box>
Expand Down
Loading

0 comments on commit ce10a4a

Please sign in to comment.