@stoplight/elements-dev-portal 1.19.6 → 2.0.1
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/components/Search/SearchOverlay.d.ts +16 -0
- package/index.esm.js +232 -184
- package/index.js +229 -181
- package/index.mjs +232 -184
- package/package.json +2 -2
- package/styles.min.css +1 -1
- package/version.d.ts +1 -1
- package/web-components.min.js +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NodeSearchResult, ProjectTableOfContents } from '../../types';
|
|
2
|
+
declare type SearchOverlayProps = {
|
|
3
|
+
isFetching: boolean;
|
|
4
|
+
search: string;
|
|
5
|
+
setSearch: (search: string) => void;
|
|
6
|
+
data?: NodeSearchResult[];
|
|
7
|
+
toc?: ProjectTableOfContents;
|
|
8
|
+
nodeSlug?: string;
|
|
9
|
+
projectSlug?: string;
|
|
10
|
+
branchSlug?: string;
|
|
11
|
+
isSearchShowing: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onClick: (item?: NodeSearchResult) => void;
|
|
14
|
+
};
|
|
15
|
+
export declare const SearchOverlay: ({ isFetching, search, setSearch, data, toc, nodeSlug, projectSlug, branchSlug, isSearchShowing, onClose, onClick, }: SearchOverlayProps) => JSX.Element;
|
|
16
|
+
export {};
|
package/index.esm.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Menu, FieldButton, Modal, Input, Box, Icon, ListBox, ListBoxItem, Flex, VStack, Heading } from '@stoplight/mosaic';
|
|
1
|
+
import { Menu, FieldButton, Modal, Input, Box, Icon, ListBox, ListBoxItem, Flex, VStack, Heading, Button, useModalState } from '@stoplight/mosaic';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import React__default, { useRef, useEffect, useMemo, useCallback, useState } from 'react';
|
|
4
|
-
import { withPersistenceBoundary, withQueryClientProvider, withMosaicProvider, MarkdownComponentsProvider, MockingProvider, Docs, withStyles, NodeTypeIconDefs, NodeTypeColors, TableOfContents as TableOfContents$1, PoweredByLink, useRouter, RouterTypeContext, findFirstNode, ReactRouterMarkdownLink, SidebarLayout } from '@stoplight/elements-core';
|
|
4
|
+
import { withPersistenceBoundary, withQueryClientProvider, withMosaicProvider, MarkdownComponentsProvider, LinkHeading, MockingProvider, Docs, withStyles, NodeTypeIconDefs, NodeTypeColors, TableOfContents as TableOfContents$1, PoweredByLink, useRouter, RouterTypeContext, useResponsiveLayout, findFirstNode, ReactRouterMarkdownLink, SidebarLayout } from '@stoplight/elements-core';
|
|
5
5
|
import { resolve, dirname } from '@stoplight/path';
|
|
6
6
|
import { NodeType } from '@stoplight/types';
|
|
7
7
|
import flow from 'lodash/flow.js';
|
|
8
|
-
import { Route, useParams, useHistory, Redirect
|
|
8
|
+
import { Link, Route, useParams, useHistory, Redirect } from 'react-router-dom';
|
|
9
9
|
import { useQuery } from 'react-query';
|
|
10
10
|
|
|
11
11
|
const BranchSelector = ({ branchSlug, branches, onChange }) => {
|
|
@@ -37,10 +37,61 @@ const PlatformProvider = ({ platformUrl = 'https://stoplight.io', platformAuthTo
|
|
|
37
37
|
};
|
|
38
38
|
const DevPortalProvider = withPersistenceBoundary(withQueryClientProvider(withMosaicProvider(PlatformProvider)));
|
|
39
39
|
|
|
40
|
+
/*! *****************************************************************************
|
|
41
|
+
Copyright (c) Microsoft Corporation.
|
|
42
|
+
|
|
43
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
44
|
+
purpose with or without fee is hereby granted.
|
|
45
|
+
|
|
46
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
47
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
48
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
49
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
50
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
51
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
52
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
53
|
+
***************************************************************************** */
|
|
54
|
+
|
|
55
|
+
function __rest(s, e) {
|
|
56
|
+
var t = {};
|
|
57
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
58
|
+
t[p] = s[p];
|
|
59
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
60
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
61
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
62
|
+
t[p[i]] = s[p[i]];
|
|
63
|
+
}
|
|
64
|
+
return t;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
68
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
69
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
70
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
71
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
72
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
73
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
40
77
|
const NodeContent = ({ node, Link, hideMocking, refResolver, maxRefDepth, tryItCorsProxy, tryItCredentialsPolicy, nodeHasChanged, nodeUnsupported, compact, hideTryIt, hideTryItPanel, hideExport, onExportRequest, }) => {
|
|
41
78
|
var _a, _b, _c, _d;
|
|
42
79
|
return (React.createElement(NodeLinkContext.Provider, { value: [node, Link] },
|
|
43
|
-
React.createElement(MarkdownComponentsProvider, { value: {
|
|
80
|
+
React.createElement(MarkdownComponentsProvider, { value: {
|
|
81
|
+
a: LinkComponent,
|
|
82
|
+
h2: (_a) => {
|
|
83
|
+
var props = __rest(_a, ["color"]);
|
|
84
|
+
return React.createElement(LinkHeading, Object.assign({ size: 2 }, props));
|
|
85
|
+
},
|
|
86
|
+
h3: (_a) => {
|
|
87
|
+
var props = __rest(_a, ["color"]);
|
|
88
|
+
return React.createElement(LinkHeading, Object.assign({ size: 3 }, props));
|
|
89
|
+
},
|
|
90
|
+
h4: (_a) => {
|
|
91
|
+
var props = __rest(_a, ["color"]);
|
|
92
|
+
return React.createElement(LinkHeading, Object.assign({ size: 4 }, props));
|
|
93
|
+
},
|
|
94
|
+
} },
|
|
44
95
|
React.createElement(MockingProvider, { mockUrl: node.links.mock_url, hideMocking: hideMocking },
|
|
45
96
|
React.createElement(Docs, { nodeType: node.type, nodeData: node.data, nodeTitle: node.title, layoutOptions: {
|
|
46
97
|
compact,
|
|
@@ -164,43 +215,6 @@ const SearchResultsList = ({ searchResults, onClick, isEmbedded, showDivider = t
|
|
|
164
215
|
const SearchResults = flow(withStyles, withPersistenceBoundary, withMosaicProvider, withQueryClientProvider)(SearchResultsList);
|
|
165
216
|
const Search = flow(withStyles, withPersistenceBoundary, withMosaicProvider, withQueryClientProvider)(SearchImpl);
|
|
166
217
|
|
|
167
|
-
/*! *****************************************************************************
|
|
168
|
-
Copyright (c) Microsoft Corporation.
|
|
169
|
-
|
|
170
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
171
|
-
purpose with or without fee is hereby granted.
|
|
172
|
-
|
|
173
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
174
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
175
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
176
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
177
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
178
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
179
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
180
|
-
***************************************************************************** */
|
|
181
|
-
|
|
182
|
-
function __rest(s, e) {
|
|
183
|
-
var t = {};
|
|
184
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
185
|
-
t[p] = s[p];
|
|
186
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
187
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
188
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
189
|
-
t[p[i]] = s[p[i]];
|
|
190
|
-
}
|
|
191
|
-
return t;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
195
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
196
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
197
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
198
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
199
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
200
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
218
|
const TableOfContents = (_a) => {
|
|
205
219
|
var { tableOfContents, activeId, Link, collapseTableOfContents = false, externalScrollbar, isInResponsiveMode = false, onLinkClick } = _a, boxProps = __rest(_a, ["tableOfContents", "activeId", "Link", "collapseTableOfContents", "externalScrollbar", "isInResponsiveMode", "onLinkClick"]);
|
|
206
220
|
return (React.createElement(Flex, Object.assign({ bg: isInResponsiveMode ? 'canvas' : 'canvas-100' }, boxProps, { flexDirection: "col", maxH: "full" }),
|
|
@@ -245,11 +259,29 @@ const NotFound = () => (React__default.createElement(Flex, { align: "center", ju
|
|
|
245
259
|
React__default.createElement(Heading, { size: 1 }, "Not Found"),
|
|
246
260
|
React__default.createElement(Box, { as: "p" }, "Could not find what you are looking for"))));
|
|
247
261
|
|
|
262
|
+
const SearchOverlay = ({ isFetching, search, setSearch, data, toc, nodeSlug, projectSlug, branchSlug, isSearchShowing, onClose, onClick, }) => {
|
|
263
|
+
return (React.createElement(Modal, { isOpen: isSearchShowing, onClose: onClose },
|
|
264
|
+
React.createElement(Box, { className: "sl-overlay", bg: "canvas", overflowY: "scroll", "data-test": "search-overlay" },
|
|
265
|
+
React.createElement(Flex, { alignItems: "center", h: "3xl", px: 7, bg: "canvas", borderB: true, pos: "sticky", zIndex: 20 },
|
|
266
|
+
React.createElement(Flex, { w: "full" },
|
|
267
|
+
React.createElement(Box, { pt: 1, pr: 2 },
|
|
268
|
+
React.createElement(Button, { appearance: "minimal", onClick: () => {
|
|
269
|
+
onClose();
|
|
270
|
+
}, "data-test": "search-overlay-back-button" },
|
|
271
|
+
React.createElement(Icon, { icon: ['fas', 'arrow-left'], color: "gray", size: "lg" }))),
|
|
272
|
+
React.createElement(Input, { border: true, "data-test": "docs-search-input", display: "inline-block", appearance: "minimal", icon: React.createElement(Box, { as: Icon, ml: 1, icon: isFetching ? faSpinner : faSearch, spin: isFetching }), autoFocus: true, placeholder: projectSlug ? 'Search within the project' : 'Search...', value: search, onChange: e => {
|
|
273
|
+
setSearch(e.currentTarget.value);
|
|
274
|
+
}, type: "search", w: "full", size: "lg" }))),
|
|
275
|
+
React.createElement(Box, { px: 5, py: toc && !search ? 0 : 5, "data-test": "responsive-project-toc" },
|
|
276
|
+
toc && !search && projectSlug && (React.createElement(TableOfContents, { tableOfContents: Object.assign(Object.assign({}, toc), { hide_powered_by: true }), activeId: nodeSlug || '', Link: Link, onLinkClick: onClick })),
|
|
277
|
+
search && (React.createElement(SearchResults, { searchResults: data, onClick: item => onClick(item), isEmbedded: true, showDivider: false }))))));
|
|
278
|
+
};
|
|
279
|
+
|
|
248
280
|
const UpgradeToStarter = () => (React__default.createElement(Flex, { as: "a", href: "https://stoplight.io/pricing/", target: "_blank", rel: "noreferrer noopener", justify: "center", alignItems: "center", w: "full", minH: "screen", color: "muted", flexDirection: "col" },
|
|
249
281
|
React__default.createElement(Icon, { icon: ['fas', 'exclamation-triangle'], size: "4x" }),
|
|
250
282
|
React__default.createElement(Box, { pt: 3 }, "Please upgrade your Stoplight Workspace to the Starter Plan to use Elements Dev Portal in production.")));
|
|
251
283
|
|
|
252
|
-
const appVersion = '
|
|
284
|
+
const appVersion = '2.0.1';
|
|
253
285
|
|
|
254
286
|
class ResponseError extends Error {
|
|
255
287
|
constructor(message, responseCode) {
|
|
@@ -305,148 +337,6 @@ function useGetNodeContent({ nodeSlug, projectId, branchSlug, }) {
|
|
|
305
337
|
return useQuery([...devPortalCacheKeys.branchNodeDetails(projectId, branchSlug !== null && branchSlug !== void 0 ? branchSlug : '', nodeSlug), platformUrl, platformAuthToken], () => getNodeContent({ nodeSlug, projectId, branchSlug, platformUrl, platformAuthToken }), { enabled: nodeSlug && projectId ? true : false });
|
|
306
338
|
}
|
|
307
339
|
|
|
308
|
-
const getTableOfContents = ({ projectId, branchSlug, platformUrl = 'https://stoplight.io', platformAuthToken, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
309
|
-
const encodedProjectId = encodeURIComponent(projectId);
|
|
310
|
-
const encodedBranchSlug = branchSlug ? encodeURIComponent(branchSlug) : '';
|
|
311
|
-
const branchQuery = encodedBranchSlug ? `?branch=${encodedBranchSlug}` : '';
|
|
312
|
-
const response = yield fetch(`${platformUrl}/api/v1/projects/${encodedProjectId}/table-of-contents${branchQuery}`, {
|
|
313
|
-
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
314
|
-
});
|
|
315
|
-
const data = yield response.json();
|
|
316
|
-
if (!response.ok) {
|
|
317
|
-
throw new Error(data);
|
|
318
|
-
}
|
|
319
|
-
return data;
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
function useGetTableOfContents({ projectId, branchSlug }) {
|
|
323
|
-
const { platformUrl, platformAuthToken } = React.useContext(PlatformContext);
|
|
324
|
-
return useQuery([...devPortalCacheKeys.branchTOC(projectId, branchSlug !== null && branchSlug !== void 0 ? branchSlug : ''), platformUrl, platformAuthToken], () => getTableOfContents({ projectId, branchSlug, platformUrl, platformAuthToken }), { enabled: projectId ? true : false });
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const StoplightProjectImpl = ({ projectId, hideTryIt, hideMocking, hideExport, collapseTableOfContents = false, tryItCredentialsPolicy, tryItCorsProxy, }) => {
|
|
328
|
-
const { branchSlug: encodedBranchSlug = '', nodeSlug = '' } = useParams();
|
|
329
|
-
const branchSlug = decodeURIComponent(encodedBranchSlug);
|
|
330
|
-
const history = useHistory();
|
|
331
|
-
const { data: tableOfContents, isFetched: isTocFetched } = useGetTableOfContents({ projectId, branchSlug });
|
|
332
|
-
const { data: branches } = useGetBranches({ projectId });
|
|
333
|
-
const { data: node, isLoading: isLoadingNode, isError, error: nodeError, } = useGetNodeContent({
|
|
334
|
-
nodeSlug,
|
|
335
|
-
projectId,
|
|
336
|
-
branchSlug,
|
|
337
|
-
});
|
|
338
|
-
const container = React.useRef(null);
|
|
339
|
-
if (!nodeSlug && isTocFetched && (tableOfContents === null || tableOfContents === void 0 ? void 0 : tableOfContents.items)) {
|
|
340
|
-
const firstNode = findFirstNode(tableOfContents.items);
|
|
341
|
-
if (firstNode) {
|
|
342
|
-
return React.createElement(Redirect, { to: branchSlug ? `/branches/${branchSlug}/${firstNode.slug}` : `/${firstNode.slug}` });
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
let elem;
|
|
346
|
-
if (isLoadingNode || !isTocFetched) {
|
|
347
|
-
elem = React.createElement(Loading, null);
|
|
348
|
-
}
|
|
349
|
-
else if (isError) {
|
|
350
|
-
if (nodeError instanceof ResponseError) {
|
|
351
|
-
if (nodeError.code === 402) {
|
|
352
|
-
elem = React.createElement(UpgradeToStarter, null);
|
|
353
|
-
}
|
|
354
|
-
else if (nodeError.code === 403) {
|
|
355
|
-
elem = React.createElement(Forbidden, null);
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
elem = React.createElement(NotFound, null);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
elem = React.createElement(NotFound, null);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
else if (!node) {
|
|
366
|
-
elem = React.createElement(NotFound, null);
|
|
367
|
-
}
|
|
368
|
-
else if ((node === null || node === void 0 ? void 0 : node.slug) && nodeSlug !== node.slug) {
|
|
369
|
-
return React.createElement(Redirect, { to: branchSlug ? `/branches/${branchSlug}/${node.slug}` : `/${node.slug}` });
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
elem = (React.createElement(NodeContent, { node: node, Link: ReactRouterMarkdownLink, hideTryIt: hideTryIt, hideMocking: hideMocking, hideExport: hideExport, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy }));
|
|
373
|
-
}
|
|
374
|
-
const handleTocClick = () => {
|
|
375
|
-
if (container.current) {
|
|
376
|
-
container.current.scrollIntoView();
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
return (React.createElement(SidebarLayout, { ref: container, sidebar: React.createElement(React.Fragment, null,
|
|
380
|
-
branches && branches.length > 1 ? (React.createElement(BranchSelector, { branchSlug: branchSlug, branches: branches, onChange: branch => {
|
|
381
|
-
const encodedBranchSlug = encodeURIComponent(branch.slug);
|
|
382
|
-
history.push(branch.is_default ? `/${nodeSlug}` : `/branches/${encodedBranchSlug}/${nodeSlug}`);
|
|
383
|
-
} })) : null,
|
|
384
|
-
tableOfContents ? (React.createElement(TableOfContents, { activeId: (node === null || node === void 0 ? void 0 : node.id) || (nodeSlug === null || nodeSlug === void 0 ? void 0 : nodeSlug.split('-')[0]) || '', tableOfContents: tableOfContents, Link: Link, collapseTableOfContents: collapseTableOfContents, onLinkClick: handleTocClick })) : null) }, elem));
|
|
385
|
-
};
|
|
386
|
-
const StoplightProjectRouter = (_a) => {
|
|
387
|
-
var { platformUrl, basePath = '/', staticRouterPath = '', router = 'history' } = _a, props = __rest(_a, ["platformUrl", "basePath", "staticRouterPath", "router"]);
|
|
388
|
-
const { Router, routerProps } = useRouter(router, basePath, staticRouterPath);
|
|
389
|
-
return (React.createElement(DevPortalProvider, { platformUrl: platformUrl },
|
|
390
|
-
React.createElement(RouterTypeContext.Provider, { value: router },
|
|
391
|
-
React.createElement(Router, Object.assign({}, routerProps, { key: basePath }),
|
|
392
|
-
React.createElement(Route, { path: "/branches/:branchSlug/:nodeSlug+", exact: true },
|
|
393
|
-
React.createElement(StoplightProjectImpl, Object.assign({}, props))),
|
|
394
|
-
React.createElement(Route, { path: "/:nodeSlug+", exact: true },
|
|
395
|
-
React.createElement(StoplightProjectImpl, Object.assign({}, props))),
|
|
396
|
-
React.createElement(Route, { path: "/", exact: true },
|
|
397
|
-
React.createElement(StoplightProjectImpl, Object.assign({}, props)))))));
|
|
398
|
-
};
|
|
399
|
-
const StoplightProject = withStyles(StoplightProjectRouter);
|
|
400
|
-
|
|
401
|
-
const getNodes = ({ workspaceId, branchSlug, projectIds, search, platformUrl = 'https://stoplight.io', platformAuthToken, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
402
|
-
const queryParams = [];
|
|
403
|
-
let fetchedWorkspaceId = workspaceId || '';
|
|
404
|
-
if (!workspaceId && (projectIds === null || projectIds === void 0 ? void 0 : projectIds.length)) {
|
|
405
|
-
const encodedProjectId = encodeURIComponent(projectIds[0]);
|
|
406
|
-
const response = yield fetch(`${platformUrl}/api/v1/projects/${encodedProjectId}`, {
|
|
407
|
-
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
408
|
-
});
|
|
409
|
-
const data = yield response.json();
|
|
410
|
-
fetchedWorkspaceId = data.workspace.id;
|
|
411
|
-
}
|
|
412
|
-
if (projectIds && projectIds.length) {
|
|
413
|
-
queryParams.push(...projectIds.map((projectId, index) => {
|
|
414
|
-
const encodedProjectId = encodeURIComponent(projectId);
|
|
415
|
-
return `project_ids[${index}]=${encodedProjectId}`;
|
|
416
|
-
}));
|
|
417
|
-
}
|
|
418
|
-
if (search) {
|
|
419
|
-
const encodedSearch = encodeURIComponent(search);
|
|
420
|
-
queryParams.push(`search=${encodedSearch}`);
|
|
421
|
-
}
|
|
422
|
-
if (branchSlug) {
|
|
423
|
-
const encodedBranchSlug = encodeURIComponent(branchSlug);
|
|
424
|
-
queryParams.push(`branch=${encodedBranchSlug}`);
|
|
425
|
-
}
|
|
426
|
-
const query = queryParams.length ? `?${queryParams.join('&')}` : '';
|
|
427
|
-
const encodedWorkspaceId = encodeURIComponent(fetchedWorkspaceId);
|
|
428
|
-
const response = yield fetch(`${platformUrl}/api/v1/workspaces/${encodedWorkspaceId}/nodes${query}`, {
|
|
429
|
-
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
430
|
-
});
|
|
431
|
-
const data = yield response.json();
|
|
432
|
-
if (!response.ok) {
|
|
433
|
-
throw new Error(data);
|
|
434
|
-
}
|
|
435
|
-
return data;
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
const getWorkspace = ({ projectIds, platformUrl = 'https://stoplight.io', platformAuthToken, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
439
|
-
const encodedProjectId = encodeURIComponent(projectIds[0]);
|
|
440
|
-
const response = yield fetch(`${platformUrl}/api/v1/projects/${encodedProjectId}`, {
|
|
441
|
-
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
442
|
-
});
|
|
443
|
-
const data = yield response.json();
|
|
444
|
-
if (!response.ok) {
|
|
445
|
-
throw new Error(data);
|
|
446
|
-
}
|
|
447
|
-
return data;
|
|
448
|
-
});
|
|
449
|
-
|
|
450
340
|
/**
|
|
451
341
|
* Creates a debounced function that delays invoking `func` until after `wait`
|
|
452
342
|
* milliseconds have elapsed since the last time the debounced function was
|
|
@@ -674,6 +564,43 @@ function useDebounce(value, delay, options) {
|
|
|
674
564
|
return [state, { cancel: debounced.cancel, isPending: debounced.isPending, flush: debounced.flush }];
|
|
675
565
|
}
|
|
676
566
|
|
|
567
|
+
const getNodes = ({ workspaceId, branchSlug, projectIds, search, platformUrl = 'https://stoplight.io', platformAuthToken, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
568
|
+
const queryParams = [];
|
|
569
|
+
let fetchedWorkspaceId = workspaceId || '';
|
|
570
|
+
if (!workspaceId && (projectIds === null || projectIds === void 0 ? void 0 : projectIds.length)) {
|
|
571
|
+
const encodedProjectId = encodeURIComponent(projectIds[0]);
|
|
572
|
+
const response = yield fetch(`${platformUrl}/api/v1/projects/${encodedProjectId}`, {
|
|
573
|
+
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
574
|
+
});
|
|
575
|
+
const data = yield response.json();
|
|
576
|
+
fetchedWorkspaceId = data.workspace.id;
|
|
577
|
+
}
|
|
578
|
+
if (projectIds && projectIds.length) {
|
|
579
|
+
queryParams.push(...projectIds.map((projectId, index) => {
|
|
580
|
+
const encodedProjectId = encodeURIComponent(projectId);
|
|
581
|
+
return `project_ids[${index}]=${encodedProjectId}`;
|
|
582
|
+
}));
|
|
583
|
+
}
|
|
584
|
+
if (search) {
|
|
585
|
+
const encodedSearch = encodeURIComponent(search);
|
|
586
|
+
queryParams.push(`search=${encodedSearch}`);
|
|
587
|
+
}
|
|
588
|
+
if (branchSlug) {
|
|
589
|
+
const encodedBranchSlug = encodeURIComponent(branchSlug);
|
|
590
|
+
queryParams.push(`branch=${encodedBranchSlug}`);
|
|
591
|
+
}
|
|
592
|
+
const query = queryParams.length ? `?${queryParams.join('&')}` : '';
|
|
593
|
+
const encodedWorkspaceId = encodeURIComponent(fetchedWorkspaceId);
|
|
594
|
+
const response = yield fetch(`${platformUrl}/api/v1/workspaces/${encodedWorkspaceId}/nodes${query}`, {
|
|
595
|
+
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
596
|
+
});
|
|
597
|
+
const data = yield response.json();
|
|
598
|
+
if (!response.ok) {
|
|
599
|
+
throw new Error(data);
|
|
600
|
+
}
|
|
601
|
+
return data;
|
|
602
|
+
});
|
|
603
|
+
|
|
677
604
|
function useGetNodes({ search, workspaceId, projectIds, branch, pause, }) {
|
|
678
605
|
const { platformUrl, platformAuthToken } = React.useContext(PlatformContext);
|
|
679
606
|
const [debounceSearch] = useDebounce(search, 500);
|
|
@@ -684,6 +611,127 @@ function useGetNodes({ search, workspaceId, projectIds, branch, pause, }) {
|
|
|
684
611
|
], () => getNodes({ workspaceId, projectIds, branchSlug: branch, search: debounceSearch, platformUrl, platformAuthToken }), { enabled: !pause, keepPreviousData: true });
|
|
685
612
|
}
|
|
686
613
|
|
|
614
|
+
const getTableOfContents = ({ projectId, branchSlug, platformUrl = 'https://stoplight.io', platformAuthToken, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
615
|
+
const encodedProjectId = encodeURIComponent(projectId);
|
|
616
|
+
const encodedBranchSlug = branchSlug ? encodeURIComponent(branchSlug) : '';
|
|
617
|
+
const branchQuery = encodedBranchSlug ? `?branch=${encodedBranchSlug}` : '';
|
|
618
|
+
const response = yield fetch(`${platformUrl}/api/v1/projects/${encodedProjectId}/table-of-contents${branchQuery}`, {
|
|
619
|
+
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
620
|
+
});
|
|
621
|
+
const data = yield response.json();
|
|
622
|
+
if (!response.ok) {
|
|
623
|
+
throw new Error(data);
|
|
624
|
+
}
|
|
625
|
+
return data;
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
function useGetTableOfContents({ projectId, branchSlug }) {
|
|
629
|
+
const { platformUrl, platformAuthToken } = React.useContext(PlatformContext);
|
|
630
|
+
return useQuery([...devPortalCacheKeys.branchTOC(projectId, branchSlug !== null && branchSlug !== void 0 ? branchSlug : ''), platformUrl, platformAuthToken], () => getTableOfContents({ projectId, branchSlug, platformUrl, platformAuthToken }), { enabled: projectId ? true : false });
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
const StoplightProjectImpl = ({ projectId, hideTryIt, hideMocking, hideExport, collapseTableOfContents = false, tryItCredentialsPolicy, tryItCorsProxy, }) => {
|
|
634
|
+
const { branchSlug: encodedBranchSlug = '', nodeSlug = '' } = useParams();
|
|
635
|
+
const branchSlug = decodeURIComponent(encodedBranchSlug);
|
|
636
|
+
const history = useHistory();
|
|
637
|
+
const { data: tableOfContents, isFetched: isTocFetched } = useGetTableOfContents({ projectId, branchSlug });
|
|
638
|
+
const { data: branches } = useGetBranches({ projectId });
|
|
639
|
+
const { data: node, isLoading: isLoadingNode, isError, error: nodeError, } = useGetNodeContent({
|
|
640
|
+
nodeSlug,
|
|
641
|
+
projectId,
|
|
642
|
+
branchSlug,
|
|
643
|
+
});
|
|
644
|
+
const { isOpen, open, close } = useModalState();
|
|
645
|
+
const [search, setSearch] = React.useState('');
|
|
646
|
+
const onSearchResultClick = (item) => {
|
|
647
|
+
close();
|
|
648
|
+
};
|
|
649
|
+
const { isResponsiveLayoutEnabled } = useResponsiveLayout();
|
|
650
|
+
const { data, isFetching } = useGetNodes({
|
|
651
|
+
search,
|
|
652
|
+
projectIds: [projectId],
|
|
653
|
+
pause: !isResponsiveLayoutEnabled,
|
|
654
|
+
});
|
|
655
|
+
const container = React.useRef(null);
|
|
656
|
+
if (!nodeSlug && isTocFetched && (tableOfContents === null || tableOfContents === void 0 ? void 0 : tableOfContents.items)) {
|
|
657
|
+
const firstNode = findFirstNode(tableOfContents.items);
|
|
658
|
+
if (firstNode) {
|
|
659
|
+
return React.createElement(Redirect, { to: branchSlug ? `/branches/${branchSlug}/${firstNode.slug}` : `/${firstNode.slug}` });
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
let elem;
|
|
663
|
+
if (isLoadingNode || !isTocFetched) {
|
|
664
|
+
elem = React.createElement(Loading, null);
|
|
665
|
+
}
|
|
666
|
+
else if (isError) {
|
|
667
|
+
if (nodeError instanceof ResponseError) {
|
|
668
|
+
if (nodeError.code === 402) {
|
|
669
|
+
elem = React.createElement(UpgradeToStarter, null);
|
|
670
|
+
}
|
|
671
|
+
else if (nodeError.code === 403) {
|
|
672
|
+
elem = React.createElement(Forbidden, null);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
elem = React.createElement(NotFound, null);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
elem = React.createElement(NotFound, null);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
else if (!node) {
|
|
683
|
+
elem = React.createElement(NotFound, null);
|
|
684
|
+
}
|
|
685
|
+
else if ((node === null || node === void 0 ? void 0 : node.slug) && nodeSlug !== node.slug) {
|
|
686
|
+
return React.createElement(Redirect, { to: branchSlug ? `/branches/${branchSlug}/${node.slug}` : `/${node.slug}` });
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
elem = (React.createElement(React.Fragment, null,
|
|
690
|
+
React.createElement(Button, { "data-test": "show-project-search-overlay", onPress: open, appearance: "default", w: "full", rounded: "lg", borderColor: "light" },
|
|
691
|
+
React.createElement(Icon, { icon: faSearch }),
|
|
692
|
+
React.createElement(Box, { pl: 2 }, node.title)),
|
|
693
|
+
React.createElement(SearchOverlay, { toc: tableOfContents, projectSlug: nodeSlug, branchSlug: branchSlug, nodeSlug: nodeSlug, isFetching: isFetching || !isTocFetched, search: search, setSearch: setSearch, data: data, isSearchShowing: isOpen, onClose: close, onClick: onSearchResultClick }),
|
|
694
|
+
React.createElement(NodeContent, { node: node, Link: ReactRouterMarkdownLink, hideTryIt: hideTryIt, hideMocking: hideMocking, hideExport: hideExport, tryItCredentialsPolicy: tryItCredentialsPolicy, tryItCorsProxy: tryItCorsProxy })));
|
|
695
|
+
}
|
|
696
|
+
const handleTocClick = () => {
|
|
697
|
+
if (container.current) {
|
|
698
|
+
container.current.scrollIntoView();
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
return (React.createElement(SidebarLayout, { ref: container, sidebar: React.createElement(React.Fragment, null,
|
|
702
|
+
branches && branches.length > 1 ? (React.createElement(BranchSelector, { branchSlug: branchSlug, branches: branches, onChange: branch => {
|
|
703
|
+
const encodedBranchSlug = encodeURIComponent(branch.slug);
|
|
704
|
+
history.push(branch.is_default ? `/${nodeSlug}` : `/branches/${encodedBranchSlug}/${nodeSlug}`);
|
|
705
|
+
} })) : null,
|
|
706
|
+
tableOfContents ? (React.createElement(TableOfContents, { activeId: (node === null || node === void 0 ? void 0 : node.id) || (nodeSlug === null || nodeSlug === void 0 ? void 0 : nodeSlug.split('-')[0]) || '', tableOfContents: tableOfContents, Link: Link, collapseTableOfContents: collapseTableOfContents, onLinkClick: handleTocClick })) : null) }, elem));
|
|
707
|
+
};
|
|
708
|
+
const StoplightProjectRouter = (_a) => {
|
|
709
|
+
var { platformUrl, basePath = '/', staticRouterPath = '', router = 'history' } = _a, props = __rest(_a, ["platformUrl", "basePath", "staticRouterPath", "router"]);
|
|
710
|
+
const { Router, routerProps } = useRouter(router, basePath, staticRouterPath);
|
|
711
|
+
return (React.createElement(DevPortalProvider, { platformUrl: platformUrl },
|
|
712
|
+
React.createElement(RouterTypeContext.Provider, { value: router },
|
|
713
|
+
React.createElement(Router, Object.assign({}, routerProps, { key: basePath }),
|
|
714
|
+
React.createElement(Route, { path: "/branches/:branchSlug/:nodeSlug+", exact: true },
|
|
715
|
+
React.createElement(StoplightProjectImpl, Object.assign({}, props))),
|
|
716
|
+
React.createElement(Route, { path: "/:nodeSlug+", exact: true },
|
|
717
|
+
React.createElement(StoplightProjectImpl, Object.assign({}, props))),
|
|
718
|
+
React.createElement(Route, { path: "/", exact: true },
|
|
719
|
+
React.createElement(StoplightProjectImpl, Object.assign({}, props)))))));
|
|
720
|
+
};
|
|
721
|
+
const StoplightProject = withStyles(StoplightProjectRouter);
|
|
722
|
+
|
|
723
|
+
const getWorkspace = ({ projectIds, platformUrl = 'https://stoplight.io', platformAuthToken, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
724
|
+
const encodedProjectId = encodeURIComponent(projectIds[0]);
|
|
725
|
+
const response = yield fetch(`${platformUrl}/api/v1/projects/${encodedProjectId}`, {
|
|
726
|
+
headers: Object.assign({ 'Stoplight-Elements-Version': appVersion }, (platformAuthToken && { Authorization: `Bearer ${platformAuthToken}` })),
|
|
727
|
+
});
|
|
728
|
+
const data = yield response.json();
|
|
729
|
+
if (!response.ok) {
|
|
730
|
+
throw new Error(data);
|
|
731
|
+
}
|
|
732
|
+
return data;
|
|
733
|
+
});
|
|
734
|
+
|
|
687
735
|
function useGetWorkspace({ projectIds }) {
|
|
688
736
|
const { platformUrl, platformAuthToken } = React.useContext(PlatformContext);
|
|
689
737
|
return useQuery([...devPortalCacheKeys.searchNodes({ projectIds }), platformUrl, platformAuthToken], () => getWorkspace({ projectIds, platformUrl, platformAuthToken }));
|