@stoplight/elements-dev-portal 3.0.12-beta-0.1 → 3.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{dist/index.esm.js → index.esm.js} +2 -2
- package/{dist/index.js → index.js} +2 -2
- package/{dist/index.mjs → index.mjs} +2 -2
- package/package.json +17 -71
- package/{dist/types.d.ts → types.d.ts} +0 -1
- package/version.d.ts +1 -0
- package/{dist/web-components.min.js → web-components.min.js} +1 -1
- package/.storybook/main.js +0 -6
- package/.storybook/manager.js +0 -1
- package/.storybook/preview.jsx +0 -46
- package/dist/LICENSE +0 -190
- package/dist/README.md +0 -22
- package/dist/package.json +0 -51
- package/dist/version.d.ts +0 -1
- package/jest.config.js +0 -10
- package/src/__fixtures__/branches.json +0 -28
- package/src/__fixtures__/node-content.json +0 -257
- package/src/__fixtures__/table-of-contents.json +0 -144
- package/src/components/BranchSelector/BranchSelector.spec.tsx +0 -61
- package/src/components/BranchSelector/BranchSelector.stories.tsx +0 -41
- package/src/components/BranchSelector/BranchSelector.tsx +0 -50
- package/src/components/BranchSelector/index.tsx +0 -1
- package/src/components/DevPortalProvider/index.tsx +0 -25
- package/src/components/Forbidden.tsx +0 -11
- package/src/components/Loading.tsx +0 -9
- package/src/components/NodeContent/NodeContent.spec.tsx +0 -128
- package/src/components/NodeContent/NodeContent.stories.tsx +0 -60
- package/src/components/NodeContent/NodeContent.tsx +0 -235
- package/src/components/NodeContent/index.tsx +0 -1
- package/src/components/NotFound.tsx +0 -11
- package/src/components/Search/Search.stories.tsx +0 -151
- package/src/components/Search/Search.tsx +0 -161
- package/src/components/Search/SearchOverlay.tsx +0 -88
- package/src/components/Search/index.tsx +0 -1
- package/src/components/TableOfContents/TableOfContents.stories.tsx +0 -68
- package/src/components/TableOfContents/TableOfContents.tsx +0 -54
- package/src/components/TableOfContents/index.tsx +0 -1
- package/src/components/UpgradeToStarter.tsx +0 -22
- package/src/consts.ts +0 -32
- package/src/containers/StoplightProject.spec.tsx +0 -78
- package/src/containers/StoplightProject.stories.tsx +0 -28
- package/src/containers/StoplightProject.tsx +0 -269
- package/src/handlers/__tests__/getBranches.test.ts +0 -30
- package/src/handlers/__tests__/getNodeContent.test.ts +0 -35
- package/src/handlers/__tests__/getNodes.test.ts +0 -38
- package/src/handlers/__tests__/getTableOfContents.test.ts +0 -34
- package/src/handlers/__tests__/getWorkspace.test.ts +0 -30
- package/src/handlers/getBranches.ts +0 -27
- package/src/handlers/getNodeContent.ts +0 -53
- package/src/handlers/getNodes.ts +0 -69
- package/src/handlers/getTableOfContents.ts +0 -30
- package/src/handlers/getWorkspace.ts +0 -27
- package/src/hooks/__tests__/dataFetching.spec.tsx +0 -42
- package/src/hooks/useGetBranches.ts +0 -17
- package/src/hooks/useGetNodeContent.ts +0 -24
- package/src/hooks/useGetNodes.ts +0 -34
- package/src/hooks/useGetTableOfContents.ts +0 -17
- package/src/hooks/useGetWorkspace.tsx +0 -13
- package/src/index.ts +0 -25
- package/src/styles.css +0 -1
- package/src/types.ts +0 -85
- package/src/version.ts +0 -2
- package/src/web-components/__stories__/StoplightProject.stories.tsx +0 -33
- package/src/web-components/components.ts +0 -19
- package/src/web-components/index.ts +0 -3
- package/tsconfig.build.json +0 -18
- package/tsconfig.json +0 -7
- package/web-components.config.js +0 -1
- /package/{dist/components → components}/BranchSelector/BranchSelector.d.ts +0 -0
- /package/{dist/components → components}/BranchSelector/BranchSelector.spec.d.ts +0 -0
- /package/{dist/components → components}/BranchSelector/BranchSelector.stories.d.ts +0 -0
- /package/{dist/components → components}/BranchSelector/index.d.ts +0 -0
- /package/{dist/components → components}/DevPortalProvider/index.d.ts +0 -0
- /package/{dist/components → components}/Forbidden.d.ts +0 -0
- /package/{dist/components → components}/Loading.d.ts +0 -0
- /package/{dist/components → components}/NodeContent/NodeContent.d.ts +0 -0
- /package/{dist/components → components}/NodeContent/NodeContent.spec.d.ts +0 -0
- /package/{dist/components → components}/NodeContent/NodeContent.stories.d.ts +0 -0
- /package/{dist/components → components}/NodeContent/index.d.ts +0 -0
- /package/{dist/components → components}/NotFound.d.ts +0 -0
- /package/{dist/components → components}/Search/Search.d.ts +0 -0
- /package/{dist/components → components}/Search/Search.stories.d.ts +0 -0
- /package/{dist/components → components}/Search/SearchOverlay.d.ts +0 -0
- /package/{dist/components → components}/Search/index.d.ts +0 -0
- /package/{dist/components → components}/TableOfContents/TableOfContents.d.ts +0 -0
- /package/{dist/components → components}/TableOfContents/TableOfContents.stories.d.ts +0 -0
- /package/{dist/components → components}/TableOfContents/index.d.ts +0 -0
- /package/{dist/components → components}/UpgradeToStarter.d.ts +0 -0
- /package/{dist/consts.d.ts → consts.d.ts} +0 -0
- /package/{dist/containers → containers}/StoplightProject.d.ts +0 -0
- /package/{dist/containers → containers}/StoplightProject.spec.d.ts +0 -0
- /package/{dist/containers → containers}/StoplightProject.stories.d.ts +0 -0
- /package/{dist/handlers → handlers}/getBranches.d.ts +0 -0
- /package/{dist/handlers → handlers}/getNodeContent.d.ts +0 -0
- /package/{dist/handlers → handlers}/getNodes.d.ts +0 -0
- /package/{dist/handlers → handlers}/getTableOfContents.d.ts +0 -0
- /package/{dist/handlers → handlers}/getWorkspace.d.ts +0 -0
- /package/{dist/hooks → hooks}/useGetBranches.d.ts +0 -0
- /package/{dist/hooks → hooks}/useGetNodeContent.d.ts +0 -0
- /package/{dist/hooks → hooks}/useGetNodes.d.ts +0 -0
- /package/{dist/hooks → hooks}/useGetTableOfContents.d.ts +0 -0
- /package/{dist/hooks → hooks}/useGetWorkspace.d.ts +0 -0
- /package/{dist/index.d.ts → index.d.ts} +0 -0
- /package/{dist/styles.min.css → styles.min.css} +0 -0
- /package/{dist/web-components → web-components}/components.d.ts +0 -0
- /package/{dist/web-components → web-components}/index.d.ts +0 -0
- /package/{dist/web-components.min.js.LICENSE.txt → web-components.min.js.LICENSE.txt} +0 -0
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Story } from '@storybook/react';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
|
|
4
|
-
import { useGetTableOfContents } from '../../hooks/useGetTableOfContents';
|
|
5
|
-
import { TableOfContents } from './';
|
|
6
|
-
|
|
7
|
-
// Wrapper to show how to use the node content hook
|
|
8
|
-
const TableOfContentsWrapper = ({
|
|
9
|
-
projectId,
|
|
10
|
-
branchSlug,
|
|
11
|
-
isInResponsiveMode,
|
|
12
|
-
}: {
|
|
13
|
-
projectId: string;
|
|
14
|
-
branchSlug?: string;
|
|
15
|
-
isInResponsiveMode?: boolean;
|
|
16
|
-
}) => {
|
|
17
|
-
const { data } = useGetTableOfContents({ projectId, branchSlug });
|
|
18
|
-
|
|
19
|
-
return data ? (
|
|
20
|
-
<TableOfContents
|
|
21
|
-
isInResponsiveMode={isInResponsiveMode}
|
|
22
|
-
activeId="b3A6MTE0"
|
|
23
|
-
tableOfContents={data}
|
|
24
|
-
Link={({ children, ...props }) => {
|
|
25
|
-
return (
|
|
26
|
-
<a
|
|
27
|
-
onClick={() => {
|
|
28
|
-
console.log('Link clicked!', props);
|
|
29
|
-
}}
|
|
30
|
-
>
|
|
31
|
-
{children}
|
|
32
|
-
</a>
|
|
33
|
-
);
|
|
34
|
-
}}
|
|
35
|
-
style={{
|
|
36
|
-
width: '300px',
|
|
37
|
-
}}
|
|
38
|
-
/>
|
|
39
|
-
) : (
|
|
40
|
-
<>Loading</>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export default {
|
|
45
|
-
title: 'Public/TableOfContents',
|
|
46
|
-
component: TableOfContentsWrapper,
|
|
47
|
-
argTypes: {
|
|
48
|
-
projectId: { table: { category: 'Input' } },
|
|
49
|
-
branchSlug: { table: { category: 'Input' } },
|
|
50
|
-
platformUrl: { table: { category: 'Input' } },
|
|
51
|
-
isInResponsiveMode: { table: { category: 'Input' } },
|
|
52
|
-
},
|
|
53
|
-
args: {
|
|
54
|
-
projectId: 'cHJqOjYwNjYx',
|
|
55
|
-
branchSlug: '',
|
|
56
|
-
platformUrl: 'https://stoplight.io',
|
|
57
|
-
isInResponsiveMode: false,
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const Playground: Story<{
|
|
62
|
-
nodeSlug: string;
|
|
63
|
-
projectId: string;
|
|
64
|
-
branchSlug?: string;
|
|
65
|
-
isInResponsiveMode?: boolean;
|
|
66
|
-
}> = args => <TableOfContentsWrapper {...args} />;
|
|
67
|
-
|
|
68
|
-
Playground.storyName = 'Studio Demo';
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CustomLinkComponent,
|
|
3
|
-
PoweredByLink,
|
|
4
|
-
TableOfContents as ElementsTableOfContents,
|
|
5
|
-
} from '@stoplight/elements-core';
|
|
6
|
-
import { BoxProps, Flex } from '@stoplight/mosaic';
|
|
7
|
-
import * as React from 'react';
|
|
8
|
-
|
|
9
|
-
import { ProjectTableOfContents } from '../../types';
|
|
10
|
-
|
|
11
|
-
export type TableOfContentsProps = BoxProps<'div'> & {
|
|
12
|
-
activeId: string;
|
|
13
|
-
tableOfContents: ProjectTableOfContents;
|
|
14
|
-
Link: CustomLinkComponent;
|
|
15
|
-
collapseTableOfContents?: boolean;
|
|
16
|
-
externalScrollbar?: boolean;
|
|
17
|
-
isInResponsiveMode?: boolean;
|
|
18
|
-
onLinkClick?(): void;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const TableOfContents = ({
|
|
22
|
-
tableOfContents,
|
|
23
|
-
activeId,
|
|
24
|
-
Link,
|
|
25
|
-
collapseTableOfContents = false,
|
|
26
|
-
externalScrollbar,
|
|
27
|
-
isInResponsiveMode = false,
|
|
28
|
-
onLinkClick,
|
|
29
|
-
...boxProps
|
|
30
|
-
}: TableOfContentsProps) => {
|
|
31
|
-
return (
|
|
32
|
-
<Flex bg={isInResponsiveMode ? 'canvas' : 'canvas-100'} {...boxProps} flexDirection="col" maxH="full">
|
|
33
|
-
<Flex flexGrow flexShrink overflowY="auto">
|
|
34
|
-
<ElementsTableOfContents
|
|
35
|
-
tree={tableOfContents.items}
|
|
36
|
-
activeId={activeId}
|
|
37
|
-
Link={Link}
|
|
38
|
-
maxDepthOpenByDefault={collapseTableOfContents ? 0 : 1}
|
|
39
|
-
externalScrollbar={externalScrollbar}
|
|
40
|
-
onLinkClick={onLinkClick}
|
|
41
|
-
isInResponsiveMode={isInResponsiveMode}
|
|
42
|
-
/>
|
|
43
|
-
</Flex>
|
|
44
|
-
|
|
45
|
-
{tableOfContents.hide_powered_by ? null : (
|
|
46
|
-
<PoweredByLink
|
|
47
|
-
source={activeId}
|
|
48
|
-
pathname={typeof window !== 'undefined' ? window.location.pathname : ''}
|
|
49
|
-
packageType="elements-dev-portal"
|
|
50
|
-
/>
|
|
51
|
-
)}
|
|
52
|
-
</Flex>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './TableOfContents';
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Box, Flex, Icon } from '@stoplight/mosaic';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
export const UpgradeToStarter = () => (
|
|
5
|
-
<Flex
|
|
6
|
-
as="a"
|
|
7
|
-
href="https://stoplight.io/pricing/"
|
|
8
|
-
target="_blank"
|
|
9
|
-
rel="noreferrer noopener"
|
|
10
|
-
justify="center"
|
|
11
|
-
alignItems="center"
|
|
12
|
-
w="full"
|
|
13
|
-
minH="screen"
|
|
14
|
-
color="muted"
|
|
15
|
-
flexDirection="col"
|
|
16
|
-
>
|
|
17
|
-
<Icon icon={['fas', 'exclamation-triangle']} size="4x" />
|
|
18
|
-
<Box pt={3}>
|
|
19
|
-
Please upgrade your Stoplight Workspace to the Starter Plan to use Elements Dev Portal in production.
|
|
20
|
-
</Box>
|
|
21
|
-
</Flex>
|
|
22
|
-
);
|
package/src/consts.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const ROOT_CACHE_KEY = '@stoplight/elements-dev-portal/client-query';
|
|
2
|
-
|
|
3
|
-
export const devPortalCacheKeys = {
|
|
4
|
-
all: [ROOT_CACHE_KEY] as const,
|
|
5
|
-
|
|
6
|
-
projects: () => [ROOT_CACHE_KEY, 'projects'] as const,
|
|
7
|
-
project: (projectId: string) => [...devPortalCacheKeys.projects(), projectId] as const,
|
|
8
|
-
projectsList: () => [...devPortalCacheKeys.projects(), 'list'] as const,
|
|
9
|
-
projectDetails: (projectId: string) => [...devPortalCacheKeys.project(projectId), 'details'] as const,
|
|
10
|
-
|
|
11
|
-
branches: (projectId: string) => [...devPortalCacheKeys.project(projectId), 'branches'] as const,
|
|
12
|
-
branch: (projectId: string, branch: string) => [...devPortalCacheKeys.branches(projectId), branch] as const,
|
|
13
|
-
branchesList: (projectId: string) => [...devPortalCacheKeys.branches(projectId), 'list'] as const,
|
|
14
|
-
branchDetails: (projectId: string, branch: string) =>
|
|
15
|
-
[...devPortalCacheKeys.branch(projectId, branch), 'details'] as const,
|
|
16
|
-
branchTOC: (projectId: string, branch: string) => [...devPortalCacheKeys.branch(projectId, branch), 'toc'] as const,
|
|
17
|
-
|
|
18
|
-
branchNodes: (projectId: string, branch: string) =>
|
|
19
|
-
[...devPortalCacheKeys.branch(projectId, branch), 'nodes'] as const,
|
|
20
|
-
branchNode: (projectId: string, branch: string, node: string) =>
|
|
21
|
-
[...devPortalCacheKeys.branchNodes(projectId, branch), node] as const,
|
|
22
|
-
branchNodesList: (projectId: string, branch: string) =>
|
|
23
|
-
[...devPortalCacheKeys.branchNodes(projectId, branch), 'list'] as const,
|
|
24
|
-
branchNodeDetails: (projectId: string, branch: string, node: string) =>
|
|
25
|
-
[...devPortalCacheKeys.branchNode(projectId, branch, node), 'details'] as const,
|
|
26
|
-
|
|
27
|
-
search: () => [...devPortalCacheKeys.all, 'search'],
|
|
28
|
-
searchNodes: (filters: { projectIds?: string[]; branchSlug?: string; workspaceId?: string; search?: string }) => [
|
|
29
|
-
...devPortalCacheKeys.search(),
|
|
30
|
-
filters,
|
|
31
|
-
],
|
|
32
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-dom';
|
|
2
|
-
|
|
3
|
-
import { render, screen } from '@testing-library/react';
|
|
4
|
-
import fetchMock from 'jest-fetch-mock';
|
|
5
|
-
import * as React from 'react';
|
|
6
|
-
|
|
7
|
-
import branches from '../__fixtures__/branches.json';
|
|
8
|
-
import nodeContent from '../__fixtures__/node-content.json';
|
|
9
|
-
import tableOfContents from '../__fixtures__/table-of-contents.json';
|
|
10
|
-
import { StoplightProject } from './StoplightProject';
|
|
11
|
-
|
|
12
|
-
describe('Stoplight Project', () => {
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
fetchMock.mockResponse(request => {
|
|
15
|
-
if (request.url.match(/\/api\/v1\/projects\/[a-zA-Z0-9_.-]+\/table-of-contents/i)) {
|
|
16
|
-
return Promise.resolve({
|
|
17
|
-
body: JSON.stringify(tableOfContents),
|
|
18
|
-
status: 200,
|
|
19
|
-
statusText: 'OK',
|
|
20
|
-
headers: [],
|
|
21
|
-
});
|
|
22
|
-
} else if (request.url.match(/\/api\/v1\/projects\/[a-zA-Z0-9_.-]+\/nodes/i)) {
|
|
23
|
-
return Promise.resolve({
|
|
24
|
-
body: JSON.stringify(nodeContent),
|
|
25
|
-
status: 200,
|
|
26
|
-
statusText: 'OK',
|
|
27
|
-
headers: [],
|
|
28
|
-
});
|
|
29
|
-
} else if (request.url.match(/\/api\/v1\/projects\/[a-zA-Z0-9_.-]+\/branches/i)) {
|
|
30
|
-
return Promise.resolve({
|
|
31
|
-
body: JSON.stringify(branches),
|
|
32
|
-
status: 200,
|
|
33
|
-
statusText: 'OK',
|
|
34
|
-
headers: [],
|
|
35
|
-
});
|
|
36
|
-
} else {
|
|
37
|
-
return Promise.resolve({ status: 404, statusText: 'Not Found', headers: [], body: '' });
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
fetchMock.enableMocks();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
afterEach(() => {
|
|
44
|
-
fetchMock.disableMocks();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('loads correctly using memory router', async () => {
|
|
48
|
-
render(<StoplightProject router="memory" projectId="cHJqOjYwNjYx" platformUrl="https://stoplight.io" />);
|
|
49
|
-
|
|
50
|
-
expect(
|
|
51
|
-
await screen.findByText(
|
|
52
|
-
'Markdown is supported in descriptions. Add information here for users to get accustomed to endpoints',
|
|
53
|
-
{},
|
|
54
|
-
{ timeout: 10000 },
|
|
55
|
-
),
|
|
56
|
-
).toBeInTheDocument();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('loads correctly using static router', async () => {
|
|
60
|
-
render(
|
|
61
|
-
<StoplightProject
|
|
62
|
-
router="static"
|
|
63
|
-
projectId="cHJqOjYwNjYx"
|
|
64
|
-
basePath=""
|
|
65
|
-
staticRouterPath="/b3A6Mzg5NDM2-create-todo"
|
|
66
|
-
platformUrl="https://stoplight.io"
|
|
67
|
-
/>,
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
expect(
|
|
71
|
-
await screen.findByText(
|
|
72
|
-
'Markdown is supported in descriptions. Add information here for users to get accustomed to endpoints',
|
|
73
|
-
{},
|
|
74
|
-
{ timeout: 10000 },
|
|
75
|
-
),
|
|
76
|
-
).toBeInTheDocument();
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Story } from '@storybook/react';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
|
|
4
|
-
import { StoplightProject, StoplightProjectProps } from './StoplightProject';
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
title: 'Public/StoplightProject',
|
|
8
|
-
component: StoplightProject,
|
|
9
|
-
argTypes: {
|
|
10
|
-
projectId: { table: { category: 'Input' } },
|
|
11
|
-
hideTryIt: { table: { category: 'Input' } },
|
|
12
|
-
hideMocking: { table: { category: 'Input' } },
|
|
13
|
-
basePath: { table: { category: 'Routing' } },
|
|
14
|
-
router: { table: { category: 'Routing' } },
|
|
15
|
-
platformUrl: { table: { category: 'Advanced' } },
|
|
16
|
-
},
|
|
17
|
-
args: {
|
|
18
|
-
router: 'memory',
|
|
19
|
-
platformUrl: 'https://stoplight.io',
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const Playground: Story<StoplightProjectProps> = args => <StoplightProject {...args} />;
|
|
24
|
-
Playground.storyName = 'Studio Demo';
|
|
25
|
-
Playground.args = {
|
|
26
|
-
projectId: 'cHJqOjYwNjYx',
|
|
27
|
-
platformUrl: 'https://stoplight.io',
|
|
28
|
-
};
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type CustomLinkComponent,
|
|
3
|
-
findFirstNode,
|
|
4
|
-
ReactRouterMarkdownLink,
|
|
5
|
-
RouterTypeContext,
|
|
6
|
-
RoutingProps,
|
|
7
|
-
ScrollToHashElement,
|
|
8
|
-
SidebarLayout,
|
|
9
|
-
useRouter,
|
|
10
|
-
withStyles,
|
|
11
|
-
} from '@stoplight/elements-core';
|
|
12
|
-
import * as React from 'react';
|
|
13
|
-
import {
|
|
14
|
-
Link,
|
|
15
|
-
Navigate,
|
|
16
|
-
Outlet,
|
|
17
|
-
Route,
|
|
18
|
-
Routes,
|
|
19
|
-
useInRouterContext,
|
|
20
|
-
useNavigate,
|
|
21
|
-
useOutletContext,
|
|
22
|
-
useParams,
|
|
23
|
-
} from 'react-router-dom';
|
|
24
|
-
|
|
25
|
-
import { BranchSelector } from '../components/BranchSelector';
|
|
26
|
-
import { DevPortalProvider } from '../components/DevPortalProvider';
|
|
27
|
-
import { Forbidden } from '../components/Forbidden';
|
|
28
|
-
import { Loading } from '../components/Loading';
|
|
29
|
-
import { NodeContent } from '../components/NodeContent';
|
|
30
|
-
import { NotFound } from '../components/NotFound';
|
|
31
|
-
import { TableOfContents } from '../components/TableOfContents';
|
|
32
|
-
import { UpgradeToStarter } from '../components/UpgradeToStarter';
|
|
33
|
-
import { ResponseError } from '../handlers/getNodeContent';
|
|
34
|
-
import { useGetBranches } from '../hooks/useGetBranches';
|
|
35
|
-
import { useGetNodeContent } from '../hooks/useGetNodeContent';
|
|
36
|
-
import { useGetTableOfContents } from '../hooks/useGetTableOfContents';
|
|
37
|
-
|
|
38
|
-
export interface StoplightProjectProps extends RoutingProps {
|
|
39
|
-
/**
|
|
40
|
-
* The ID of the Stoplight Project.
|
|
41
|
-
* @example "d2s6NDE1NTU"
|
|
42
|
-
*/
|
|
43
|
-
projectId: string;
|
|
44
|
-
/**
|
|
45
|
-
* If your company runs an on-premise deployment of Stoplight,
|
|
46
|
-
* set this prop to point the StoplightProject component at the URL of that instance.
|
|
47
|
-
*/
|
|
48
|
-
platformUrl?: string;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Allows to hide TryIt component
|
|
52
|
-
*/
|
|
53
|
-
hideTryIt?: boolean;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Allows to hide mocking button
|
|
57
|
-
*/
|
|
58
|
-
hideMocking?: boolean;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Allows to hide export button
|
|
62
|
-
* @default false
|
|
63
|
-
*/
|
|
64
|
-
hideExport?: boolean;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Allows to the server information
|
|
68
|
-
* @default false
|
|
69
|
-
*/
|
|
70
|
-
hideServerInfo?: boolean;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Allows to hide the security schemes
|
|
74
|
-
* @default false
|
|
75
|
-
*/
|
|
76
|
-
hideSecurityInfo?: boolean;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* If set to true, all table of contents panels will be collapsed.
|
|
80
|
-
* @default false
|
|
81
|
-
*/
|
|
82
|
-
collapseTableOfContents?: boolean;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Fetch credentials policy for TryIt component
|
|
86
|
-
* For more information: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
|
87
|
-
* @default "omit"
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
tryItCredentialsPolicy?: 'omit' | 'include' | 'same-origin';
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* URL of a CORS proxy that will be used to send requests in TryIt.
|
|
94
|
-
* Provided url will be prepended to an URL of an actual request.
|
|
95
|
-
* @default false
|
|
96
|
-
*/
|
|
97
|
-
tryItCorsProxy?: string;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const StoplightProjectImpl: React.FC<StoplightProjectProps> = ({ projectId, collapseTableOfContents = false }) => {
|
|
101
|
-
const { branchSlug: encodedBranchSlug = '', '*': nodeSlug = '' } = useParams<{
|
|
102
|
-
branchSlug?: string;
|
|
103
|
-
'*': string;
|
|
104
|
-
}>();
|
|
105
|
-
const branchSlug = decodeURIComponent(encodedBranchSlug);
|
|
106
|
-
const navigate = useNavigate();
|
|
107
|
-
|
|
108
|
-
const { data: tableOfContents, isFetched: isTocFetched } = useGetTableOfContents({ projectId, branchSlug });
|
|
109
|
-
const { data: branches } = useGetBranches({ projectId });
|
|
110
|
-
const {
|
|
111
|
-
data: node,
|
|
112
|
-
isLoading: isLoadingNode,
|
|
113
|
-
isError,
|
|
114
|
-
error: nodeError,
|
|
115
|
-
} = useGetNodeContent({
|
|
116
|
-
nodeSlug: nodeSlug ?? '',
|
|
117
|
-
projectId,
|
|
118
|
-
branchSlug,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const container = React.useRef<HTMLDivElement>(null);
|
|
122
|
-
|
|
123
|
-
if (!nodeSlug && isTocFetched && tableOfContents?.items) {
|
|
124
|
-
const firstNode = findFirstNode(tableOfContents.items);
|
|
125
|
-
if (firstNode) {
|
|
126
|
-
return <Navigate to={branchSlug ? `branches/${branchSlug}/${firstNode.slug}` : `${firstNode.slug}`} replace />;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const handleTocClick = () => {
|
|
131
|
-
if (container.current) {
|
|
132
|
-
container.current.scrollIntoView();
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<SidebarLayout
|
|
138
|
-
ref={container}
|
|
139
|
-
sidebar={
|
|
140
|
-
<>
|
|
141
|
-
{branches && branches.items.length > 1 ? (
|
|
142
|
-
<BranchSelector
|
|
143
|
-
branchSlug={branchSlug}
|
|
144
|
-
branches={branches.items}
|
|
145
|
-
onChange={branch => {
|
|
146
|
-
const encodedBranchSlug = encodeURIComponent(branch.slug);
|
|
147
|
-
navigate(branch.is_default ? `${nodeSlug}` : `branches/${encodedBranchSlug}/${nodeSlug}`);
|
|
148
|
-
}}
|
|
149
|
-
/>
|
|
150
|
-
) : null}
|
|
151
|
-
{tableOfContents ? (
|
|
152
|
-
<TableOfContents
|
|
153
|
-
activeId={node?.id || nodeSlug?.split('-')[0] || ''}
|
|
154
|
-
tableOfContents={tableOfContents}
|
|
155
|
-
Link={Link as CustomLinkComponent}
|
|
156
|
-
collapseTableOfContents={collapseTableOfContents}
|
|
157
|
-
onLinkClick={handleTocClick}
|
|
158
|
-
/>
|
|
159
|
-
) : null}
|
|
160
|
-
</>
|
|
161
|
-
}
|
|
162
|
-
>
|
|
163
|
-
<Outlet context={[isLoadingNode, isTocFetched, isError, nodeError, node]} />
|
|
164
|
-
</SidebarLayout>
|
|
165
|
-
);
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
const ProjectNode: React.FC<StoplightProjectProps> = ({
|
|
169
|
-
hideTryIt,
|
|
170
|
-
hideSecurityInfo,
|
|
171
|
-
hideServerInfo,
|
|
172
|
-
hideMocking,
|
|
173
|
-
hideExport,
|
|
174
|
-
tryItCredentialsPolicy,
|
|
175
|
-
tryItCorsProxy,
|
|
176
|
-
}) => {
|
|
177
|
-
const { branchSlug: encodedBranchSlug = '', '*': nodeSlug = '' } = useParams<{ branchSlug?: string; '*': string }>();
|
|
178
|
-
const branchSlug = decodeURIComponent(encodedBranchSlug);
|
|
179
|
-
const [isLoadingNode, isTocFetched, isError, nodeError, node] = useOutletContext<any>();
|
|
180
|
-
|
|
181
|
-
if (isLoadingNode || !isTocFetched) {
|
|
182
|
-
return <Loading />;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (isError) {
|
|
186
|
-
if (nodeError instanceof ResponseError) {
|
|
187
|
-
if (nodeError.code === 402) {
|
|
188
|
-
return <UpgradeToStarter />;
|
|
189
|
-
} else if (nodeError.code === 403) {
|
|
190
|
-
return <Forbidden />;
|
|
191
|
-
} else {
|
|
192
|
-
return <NotFound />;
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
return <NotFound />;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (!node) {
|
|
200
|
-
return <NotFound />;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (node?.slug && nodeSlug !== node.slug) {
|
|
204
|
-
// Handle redirect to node's slug
|
|
205
|
-
return <Navigate to={branchSlug ? `/branches/${branchSlug}/${node.slug}` : `/${node.slug}`} replace />;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return (
|
|
209
|
-
<>
|
|
210
|
-
<ScrollToHashElement />
|
|
211
|
-
<NodeContent
|
|
212
|
-
node={node}
|
|
213
|
-
Link={ReactRouterMarkdownLink}
|
|
214
|
-
hideTryIt={hideTryIt}
|
|
215
|
-
hideMocking={hideMocking}
|
|
216
|
-
hideExport={hideExport}
|
|
217
|
-
hideSecurityInfo={hideSecurityInfo}
|
|
218
|
-
hideServerInfo={hideServerInfo}
|
|
219
|
-
tryItCredentialsPolicy={tryItCredentialsPolicy}
|
|
220
|
-
tryItCorsProxy={tryItCorsProxy}
|
|
221
|
-
/>
|
|
222
|
-
</>
|
|
223
|
-
);
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const StoplightProjectRouter = ({
|
|
227
|
-
platformUrl,
|
|
228
|
-
basePath = '/',
|
|
229
|
-
staticRouterPath = '',
|
|
230
|
-
router = 'hash',
|
|
231
|
-
...props
|
|
232
|
-
}: StoplightProjectProps) => {
|
|
233
|
-
const { Router, routerProps } = useRouter(router, basePath, staticRouterPath);
|
|
234
|
-
const outerRouter = useInRouterContext();
|
|
235
|
-
|
|
236
|
-
const InternalRoutes = () => (
|
|
237
|
-
<Routes>
|
|
238
|
-
<Route path="/" element={<StoplightProjectImpl {...props} />}>
|
|
239
|
-
<Route path="/branches/:branchSlug/*" element={<ProjectNode {...props} />} />
|
|
240
|
-
<Route path="/*" element={<ProjectNode {...props} />} />
|
|
241
|
-
</Route>
|
|
242
|
-
</Routes>
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
if (!outerRouter) {
|
|
246
|
-
return (
|
|
247
|
-
<DevPortalProvider platformUrl={platformUrl}>
|
|
248
|
-
<RouterTypeContext.Provider value={router}>
|
|
249
|
-
<Router {...routerProps} key={basePath}>
|
|
250
|
-
<InternalRoutes />
|
|
251
|
-
</Router>
|
|
252
|
-
</RouterTypeContext.Provider>
|
|
253
|
-
</DevPortalProvider>
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return (
|
|
258
|
-
<DevPortalProvider platformUrl={platformUrl}>
|
|
259
|
-
<RouterTypeContext.Provider value={router}>
|
|
260
|
-
<InternalRoutes />
|
|
261
|
-
</RouterTypeContext.Provider>
|
|
262
|
-
</DevPortalProvider>
|
|
263
|
-
);
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* The StoplightProject component displays a traditional documentation UI for an existing Stoplight Project.
|
|
268
|
-
*/
|
|
269
|
-
export const StoplightProject = withStyles(StoplightProjectRouter);
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import fetchMock from 'jest-fetch-mock';
|
|
2
|
-
|
|
3
|
-
import { getBranches } from '../getBranches';
|
|
4
|
-
|
|
5
|
-
describe('getBranches', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
fetchMock.resetMocks();
|
|
8
|
-
localStorage.clear();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('should URI encode the parameters in the request URL', async () => {
|
|
12
|
-
fetchMock.mockResolvedValue(
|
|
13
|
-
new Response('{}', {
|
|
14
|
-
status: 200,
|
|
15
|
-
statusText: 'OK',
|
|
16
|
-
headers: [],
|
|
17
|
-
}),
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
await getBranches({
|
|
21
|
-
projectId: 'some/slash',
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
expect(fetchMock).toBeCalledWith('https://stoplight.io/api/v1/projects/some%2Fslash/branches', {
|
|
25
|
-
headers: expect.objectContaining({
|
|
26
|
-
'Stoplight-Elements-Version': expect.any(String),
|
|
27
|
-
}),
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import fetchMock from 'jest-fetch-mock';
|
|
2
|
-
|
|
3
|
-
import { getNodeContent } from '../getNodeContent';
|
|
4
|
-
|
|
5
|
-
describe('getNodeContent', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
fetchMock.resetMocks();
|
|
8
|
-
localStorage.clear();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('should URI encode the parameters in the request URL', async () => {
|
|
12
|
-
fetchMock.mockResolvedValue(
|
|
13
|
-
new Response('{}', {
|
|
14
|
-
status: 200,
|
|
15
|
-
statusText: 'OK',
|
|
16
|
-
headers: [],
|
|
17
|
-
}),
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
await getNodeContent({
|
|
21
|
-
nodeSlug: 'node&slug',
|
|
22
|
-
projectId: 'some/slash',
|
|
23
|
-
branchSlug: 'test+branch',
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
expect(fetchMock).toBeCalledWith(
|
|
27
|
-
'https://stoplight.io/api/v1/projects/some%2Fslash/nodes/node%26slug?branch=test%2Bbranch',
|
|
28
|
-
{
|
|
29
|
-
headers: expect.objectContaining({
|
|
30
|
-
'Stoplight-Elements-Version': expect.any(String),
|
|
31
|
-
}),
|
|
32
|
-
},
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import fetchMock from 'jest-fetch-mock';
|
|
2
|
-
|
|
3
|
-
import { getNodes } from '../getNodes';
|
|
4
|
-
|
|
5
|
-
describe('getNodes', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
fetchMock.resetMocks();
|
|
8
|
-
localStorage.clear();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
describe('with a provided workspace identifier', () => {
|
|
12
|
-
it('should URI encode the parameters in the request URL', async () => {
|
|
13
|
-
fetchMock.mockResolvedValue(
|
|
14
|
-
new Response('{}', {
|
|
15
|
-
status: 200,
|
|
16
|
-
statusText: 'OK',
|
|
17
|
-
headers: [],
|
|
18
|
-
}),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
await getNodes({
|
|
22
|
-
workspaceId: 'my?workspace',
|
|
23
|
-
projectIds: ['some/slash'],
|
|
24
|
-
branchSlug: 'test+branch',
|
|
25
|
-
search: 'a?special&search',
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
expect(fetchMock).toBeCalledWith(
|
|
29
|
-
'https://stoplight.io/api/v1/workspaces/my%3Fworkspace/nodes?project_ids[0]=some%2Fslash&search=a%3Fspecial%26search&branch=test%2Bbranch',
|
|
30
|
-
{
|
|
31
|
-
headers: expect.objectContaining({
|
|
32
|
-
'Stoplight-Elements-Version': expect.any(String),
|
|
33
|
-
}),
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
});
|