@patternfly/quickstarts 2.2.3 → 2.2.4

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.
Files changed (188) hide show
  1. package/dist/HelpTopicDrawer.d.ts +8 -2
  2. package/dist/QuickStartDrawer.d.ts +21 -2
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/patternfly-docs/quick-starts/design-guidelines/design-guidelines.md +105 -0
  6. package/dist/patternfly-docs/quick-starts/design-guidelines/img/card-elements copy.png +0 -0
  7. package/dist/patternfly-docs/quick-starts/design-guidelines/img/card-elements.png +0 -0
  8. package/dist/patternfly-docs/quick-starts/design-guidelines/img/catalog-elements.png +0 -0
  9. package/dist/patternfly-docs/quick-starts/design-guidelines/img/check-your-work.png +0 -0
  10. package/dist/patternfly-docs/quick-starts/design-guidelines/img/introduction-screen.png +0 -0
  11. package/dist/patternfly-docs/quick-starts/design-guidelines/img/mixed-catalog.png +0 -0
  12. package/dist/patternfly-docs/quick-starts/design-guidelines/img/prerequisites.png +0 -0
  13. package/dist/patternfly-docs/quick-starts/design-guidelines/img/qs-context.png +0 -0
  14. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel-elements.png +0 -0
  15. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel-resized.png +0 -0
  16. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel.png +0 -0
  17. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task-no.png +0 -0
  18. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task-yes.png +0 -0
  19. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task.png +0 -0
  20. package/dist/patternfly-docs/quick-starts/examples/Basic.jsx +73 -0
  21. package/dist/patternfly-docs/quick-starts/examples/HelpTopic.jsx +53 -0
  22. package/dist/patternfly-docs/quick-starts/examples/about.md +77 -0
  23. package/dist/patternfly-docs/quick-starts/examples/basic.md +27 -0
  24. package/dist/patternfly-docs/quick-starts/examples/example-data/example-help-topics.js +173 -0
  25. package/dist/patternfly-docs/quick-starts/examples/example-data/example-quickstarts.js +215 -0
  26. package/dist/patternfly-docs/quick-starts/examples/example-data/index.js +15 -0
  27. package/dist/patternfly-docs/quick-starts/examples/help-topics.md +25 -0
  28. package/dist/patternfly-docs/quick-starts/examples/img/catalog.png +0 -0
  29. package/dist/patternfly-docs/quick-starts/examples/img/help-topic.png +0 -0
  30. package/dist/patternfly-docs/quick-starts/examples/img/side-panel.png +0 -0
  31. package/dist/quickstarts-full.es.js.map +1 -1
  32. package/package.json +11 -4
  33. package/src/ConsoleInternal/components/_icon-and-text.scss +14 -0
  34. package/src/ConsoleInternal/components/_markdown-view.scss +19 -0
  35. package/src/ConsoleInternal/components/catalog/_catalog.scss +390 -0
  36. package/src/ConsoleInternal/components/markdown-view.tsx +305 -0
  37. package/src/ConsoleInternal/components/utils/_status-box.scss +58 -0
  38. package/src/ConsoleInternal/components/utils/camel-case-wrap.tsx +33 -0
  39. package/src/ConsoleInternal/components/utils/index.tsx +3 -0
  40. package/src/ConsoleInternal/components/utils/router.ts +47 -0
  41. package/src/ConsoleInternal/components/utils/status-box.tsx +94 -0
  42. package/src/ConsoleInternal/module/k8s/types.ts +53 -0
  43. package/src/ConsoleShared/index.ts +1 -0
  44. package/src/ConsoleShared/src/components/index.ts +7 -0
  45. package/src/ConsoleShared/src/components/layout/PageLayout.scss +29 -0
  46. package/src/ConsoleShared/src/components/markdown-extensions/MarkdownCopyClipboard.tsx +93 -0
  47. package/src/ConsoleShared/src/components/markdown-extensions/__tests__/MarkdownCopyClipboard.spec.tsx +25 -0
  48. package/src/ConsoleShared/src/components/markdown-extensions/__tests__/test-data.ts +5 -0
  49. package/src/ConsoleShared/src/components/markdown-extensions/admonition-extension.tsx +66 -0
  50. package/src/ConsoleShared/src/components/markdown-extensions/code-extension.tsx +25 -0
  51. package/src/ConsoleShared/src/components/markdown-extensions/const.ts +3 -0
  52. package/src/ConsoleShared/src/components/markdown-extensions/index.ts +5 -0
  53. package/src/ConsoleShared/src/components/markdown-extensions/inline-clipboard-extension.tsx +45 -0
  54. package/src/ConsoleShared/src/components/markdown-extensions/multiline-clipboard-extension.tsx +50 -0
  55. package/src/ConsoleShared/src/components/markdown-extensions/showdown-extension.scss +52 -0
  56. package/src/ConsoleShared/src/components/markdown-extensions/utils.ts +3 -0
  57. package/src/ConsoleShared/src/components/markdown-highlight-extension/MarkdownHighlightExtension.tsx +64 -0
  58. package/src/ConsoleShared/src/components/markdown-highlight-extension/highlight-consts.ts +9 -0
  59. package/src/ConsoleShared/src/components/markdown-highlight-extension/index.ts +1 -0
  60. package/src/ConsoleShared/src/components/modal/Modal.scss +3 -0
  61. package/src/ConsoleShared/src/components/modal/Modal.tsx +19 -0
  62. package/src/ConsoleShared/src/components/modal/index.ts +1 -0
  63. package/src/ConsoleShared/src/components/popper/Portal.tsx +23 -0
  64. package/src/ConsoleShared/src/components/popper/SimplePopper.tsx +90 -0
  65. package/src/ConsoleShared/src/components/popper/index.ts +2 -0
  66. package/src/ConsoleShared/src/components/spotlight/InteractiveSpotlight.tsx +58 -0
  67. package/src/ConsoleShared/src/components/spotlight/Spotlight.tsx +35 -0
  68. package/src/ConsoleShared/src/components/spotlight/StaticSpotlight.tsx +32 -0
  69. package/src/ConsoleShared/src/components/spotlight/index.ts +1 -0
  70. package/src/ConsoleShared/src/components/spotlight/spotlight.scss +63 -0
  71. package/src/ConsoleShared/src/components/status/GenericStatus.tsx +33 -0
  72. package/src/ConsoleShared/src/components/status/NotStartedIcon.tsx +27 -0
  73. package/src/ConsoleShared/src/components/status/PopoverStatus.tsx +42 -0
  74. package/src/ConsoleShared/src/components/status/Status.tsx +38 -0
  75. package/src/ConsoleShared/src/components/status/StatusIconAndText.tsx +42 -0
  76. package/src/ConsoleShared/src/components/status/icons.tsx +77 -0
  77. package/src/ConsoleShared/src/components/status/index.tsx +1 -0
  78. package/src/ConsoleShared/src/components/status/statuses.tsx +36 -0
  79. package/src/ConsoleShared/src/components/status/types.ts +7 -0
  80. package/src/ConsoleShared/src/components/utils/FallbackImg.tsx +20 -0
  81. package/src/ConsoleShared/src/components/utils/index.ts +1 -0
  82. package/src/ConsoleShared/src/constants/index.ts +1 -0
  83. package/src/ConsoleShared/src/constants/ui.ts +1 -0
  84. package/src/ConsoleShared/src/hooks/index.ts +6 -0
  85. package/src/ConsoleShared/src/hooks/scroll.ts +52 -0
  86. package/src/ConsoleShared/src/hooks/useBoundingClientRect.ts +18 -0
  87. package/src/ConsoleShared/src/hooks/useEventListener.ts +14 -0
  88. package/src/ConsoleShared/src/hooks/useForceRender.ts +6 -0
  89. package/src/ConsoleShared/src/hooks/useResizeObserver.ts +20 -0
  90. package/src/ConsoleShared/src/hooks/useScrollShadows.ts +45 -0
  91. package/src/ConsoleShared/src/index.ts +4 -0
  92. package/src/ConsoleShared/src/utils/index.ts +1 -0
  93. package/src/ConsoleShared/src/utils/useCombineRefs.ts +17 -0
  94. package/src/HelpTopicDrawer.tsx +124 -0
  95. package/src/HelpTopicPanelContent.tsx +152 -0
  96. package/src/QuickStartCatalogPage.tsx +190 -0
  97. package/src/QuickStartCloseModal.tsx +47 -0
  98. package/src/QuickStartController.tsx +113 -0
  99. package/src/QuickStartDrawer.scss +11 -0
  100. package/src/QuickStartDrawer.tsx +265 -0
  101. package/src/QuickStartMarkdownView.tsx +75 -0
  102. package/src/QuickStartPanelContent.scss +46 -0
  103. package/src/QuickStartPanelContent.tsx +153 -0
  104. package/src/__tests__/quick-start-utils.spec.tsx +16 -0
  105. package/src/catalog/Catalog/QuickStartCatalogHeader.tsx +18 -0
  106. package/src/catalog/Catalog/QuickStartCatalogSection.tsx +9 -0
  107. package/src/catalog/Catalog/QuickStartCatalogToolbar.tsx +12 -0
  108. package/src/catalog/Catalog/index.ts +3 -0
  109. package/src/catalog/QuickStartCatalog.scss +8 -0
  110. package/src/catalog/QuickStartCatalog.tsx +42 -0
  111. package/src/catalog/QuickStartTile.scss +11 -0
  112. package/src/catalog/QuickStartTile.tsx +105 -0
  113. package/src/catalog/QuickStartTileDescription.scss +29 -0
  114. package/src/catalog/QuickStartTileDescription.tsx +79 -0
  115. package/src/catalog/QuickStartTileFooter.tsx +101 -0
  116. package/src/catalog/QuickStartTileFooterExternal.tsx +40 -0
  117. package/src/catalog/QuickStartTileHeader.scss +12 -0
  118. package/src/catalog/QuickStartTileHeader.tsx +77 -0
  119. package/src/catalog/Toolbar/QuickStartCatalogFilter.scss +25 -0
  120. package/src/catalog/Toolbar/QuickStartCatalogFilter.tsx +34 -0
  121. package/src/catalog/Toolbar/QuickStartCatalogFilterItems.tsx +199 -0
  122. package/src/catalog/__tests__/QuickStartCatalog.spec.tsx +35 -0
  123. package/src/catalog/__tests__/QuickStartTile.spec.tsx +38 -0
  124. package/src/catalog/__tests__/QuickStartTileDescription.spec.tsx +44 -0
  125. package/src/catalog/index.ts +9 -0
  126. package/src/controller/QuickStartConclusion.tsx +63 -0
  127. package/src/controller/QuickStartContent.scss +12 -0
  128. package/src/controller/QuickStartContent.tsx +72 -0
  129. package/src/controller/QuickStartFooter.scss +13 -0
  130. package/src/controller/QuickStartFooter.tsx +128 -0
  131. package/src/controller/QuickStartIntroduction.scss +35 -0
  132. package/src/controller/QuickStartIntroduction.tsx +66 -0
  133. package/src/controller/QuickStartTaskHeader.scss +58 -0
  134. package/src/controller/QuickStartTaskHeader.tsx +116 -0
  135. package/src/controller/QuickStartTaskHeaderList.scss +17 -0
  136. package/src/controller/QuickStartTaskHeaderList.tsx +35 -0
  137. package/src/controller/QuickStartTaskReview.scss +30 -0
  138. package/src/controller/QuickStartTaskReview.tsx +81 -0
  139. package/src/controller/QuickStartTasks.scss +89 -0
  140. package/src/controller/QuickStartTasks.tsx +75 -0
  141. package/src/controller/__tests__/QuickStartConclusion.spec.tsx +95 -0
  142. package/src/controller/__tests__/QuickStartContent.spec.tsx +52 -0
  143. package/src/controller/__tests__/QuickStartFooter.spec.tsx +148 -0
  144. package/src/controller/__tests__/QuickStartTaskHeader.spec.tsx +56 -0
  145. package/src/controller/__tests__/QuickStartTaskReview.spec.tsx +45 -0
  146. package/src/controller/__tests__/QuickStartTasks.spec.tsx +81 -0
  147. package/src/data/mocks/json/explore-pipeline-quickstart.ts +66 -0
  148. package/src/data/mocks/json/explore-serverless-quickstart.ts +90 -0
  149. package/src/data/mocks/json/monitor-sampleapp-quickstart.ts +77 -0
  150. package/src/data/mocks/json/tour-icons.ts +3 -0
  151. package/src/data/mocks/yamls/add-healthchecks-quickstart.yaml +67 -0
  152. package/src/data/mocks/yamls/explore-pipeline-quickstart.yaml +57 -0
  153. package/src/data/mocks/yamls/explore-serverless-quickstart.yaml +83 -0
  154. package/src/data/mocks/yamls/install-associate-pipeline-quickstart.yaml +74 -0
  155. package/src/data/mocks/yamls/monitor-sampleapp-quickstart.yaml +66 -0
  156. package/src/data/mocks/yamls/sample-application-quickstart.yaml +97 -0
  157. package/src/data/mocks/yamls/serverless-application-quickstart.yaml +141 -0
  158. package/src/data/quick-start-test-data.ts +10 -0
  159. package/src/data/test-utils.ts +11 -0
  160. package/src/declaration.d.ts +2 -0
  161. package/src/index.ts +17 -0
  162. package/src/locales/en/quickstart.json +46 -0
  163. package/src/styles/_base.scss +54 -0
  164. package/src/styles/_dark-custom-override.scss +62 -0
  165. package/src/styles/legacy-bootstrap/README.md +21 -0
  166. package/src/styles/legacy-bootstrap/_code.scss +44 -0
  167. package/src/styles/legacy-bootstrap/_tables.scss +38 -0
  168. package/src/styles/legacy-bootstrap/_type.scss +90 -0
  169. package/src/styles/legacy-bootstrap/_variables.scss +48 -0
  170. package/src/styles/legacy-bootstrap.scss +5 -0
  171. package/src/styles/patternfly-global-entry.ts +1 -0
  172. package/src/styles/patternfly-global.scss +28 -0
  173. package/src/styles/patternfly-nested-entry.ts +1 -0
  174. package/src/styles/patternfly-nested.scss +18 -0
  175. package/src/styles/quickstarts-standalone-entry.ts +1 -0
  176. package/src/styles/quickstarts-standalone.scss +7 -0
  177. package/src/styles/style.scss +12 -0
  178. package/src/styles/vendor-entry.ts +1 -0
  179. package/src/styles/vendor.scss +7 -0
  180. package/src/utils/PluralResolver.ts +356 -0
  181. package/src/utils/asciidoc-procedure-parser.ts +132 -0
  182. package/src/utils/const.ts +10 -0
  183. package/src/utils/help-topic-context.tsx +74 -0
  184. package/src/utils/help-topic-types.ts +16 -0
  185. package/src/utils/quick-start-context.tsx +477 -0
  186. package/src/utils/quick-start-types.ts +72 -0
  187. package/src/utils/quick-start-utils.ts +92 -0
  188. package/src/utils/useLocalStorage.ts +38 -0
@@ -0,0 +1,305 @@
1
+ import * as React from 'react';
2
+ import { css } from '@patternfly/react-styles';
3
+ import { Converter } from 'showdown';
4
+ import { useForceRender } from '@console/shared';
5
+ import { QuickStartContext, QuickStartContextValues } from '../../utils/quick-start-context';
6
+ import './_markdown-view.scss';
7
+
8
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
9
+ const DOMPurify = require('dompurify');
10
+
11
+ // const tableTags = ['table', 'thead', 'tbody', 'tr', 'th', 'td'];
12
+
13
+ type ShowdownExtension = {
14
+ type: string;
15
+ regex?: RegExp;
16
+ replace?: (...args: any[]) => string;
17
+ };
18
+
19
+ export const markdownConvert = (markdown, extensions?: ShowdownExtension[]) => {
20
+ const converter = new Converter({
21
+ tables: true,
22
+ openLinksInNewWindow: true,
23
+ strikethrough: true,
24
+ emoji: false,
25
+ });
26
+
27
+ if (extensions) {
28
+ converter.addExtension(extensions);
29
+ }
30
+
31
+ DOMPurify.addHook('beforeSanitizeElements', function(node) {
32
+ // nodeType 1 = element type
33
+
34
+ // transform anchor tags
35
+ if (node.nodeType === 1 && node.nodeName.toLowerCase() === 'a') {
36
+ node.setAttribute('rel', 'noopener noreferrer');
37
+ return node;
38
+ }
39
+
40
+ // add PF class to ul and ol lists
41
+ if (
42
+ node.nodeType === 1 &&
43
+ (node.nodeName.toLowerCase() === 'ul' || node.nodeName.toLowerCase() === 'ol')
44
+ ) {
45
+ node.setAttribute('class', 'pf-c-list');
46
+ return node;
47
+ }
48
+ });
49
+
50
+ // Add a hook to make all links open a new window
51
+ DOMPurify.addHook('afterSanitizeAttributes', function(node) {
52
+ // set all elements owning target to target=_blank
53
+ if ('target' in node) {
54
+ node.setAttribute('target', '_blank');
55
+ }
56
+ // set non-HTML/MathML links to xlink:show=new
57
+ if (
58
+ !node.hasAttribute('target') &&
59
+ (node.hasAttribute('xlink:href') || node.hasAttribute('href'))
60
+ ) {
61
+ node.setAttribute('xlink:show', 'new');
62
+ }
63
+ });
64
+
65
+ return DOMPurify.sanitize(converter.makeHtml(markdown), {
66
+ USE_PROFILES: {
67
+ html: true,
68
+ svg: true,
69
+ },
70
+ // ALLOWED_TAGS: [
71
+ // 'b',
72
+ // 'i',
73
+ // 'strike',
74
+ // 's',
75
+ // 'del',
76
+ // 'em',
77
+ // 'strong',
78
+ // 'a',
79
+ // 'p',
80
+ // 'h1',
81
+ // 'h2',
82
+ // 'h3',
83
+ // 'h4',
84
+ // 'ul',
85
+ // 'ol',
86
+ // 'li',
87
+ // 'code',
88
+ // 'pre',
89
+ // 'button',
90
+ // ...tableTags,
91
+ // 'div',
92
+ // 'img',
93
+ // 'span',
94
+ // 'svg',
95
+ // ],
96
+ // ALLOWED_ATTR: ['href', 'target', 'rel', 'class', 'src', 'alt', 'id'],
97
+ // ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|didact):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i,
98
+ });
99
+ };
100
+
101
+ type SyncMarkdownProps = {
102
+ content?: string;
103
+ emptyMsg?: string;
104
+ exactHeight?: boolean;
105
+ /* truncateContent?: boolean; */
106
+ extensions?: ShowdownExtension[];
107
+ renderExtension?: (contentDocument: HTMLDocument, rootSelector: string) => React.ReactNode;
108
+ inline?: boolean;
109
+ className?: string;
110
+ };
111
+
112
+ type InnerSyncMarkdownProps = Pick<SyncMarkdownProps, 'renderExtension' | 'exactHeight'> & {
113
+ markup: string;
114
+ isEmpty: boolean;
115
+ className?: string;
116
+ };
117
+
118
+ export const SyncMarkdownView: React.FC<SyncMarkdownProps> = ({
119
+ // truncateContent,
120
+ content,
121
+ emptyMsg,
122
+ extensions,
123
+ renderExtension,
124
+ exactHeight,
125
+ inline,
126
+ className,
127
+ }) => {
128
+ const { getResource } = React.useContext<QuickStartContextValues>(QuickStartContext);
129
+ const markup = React.useMemo(() => {
130
+ return markdownConvert(content || emptyMsg || getResource('Not available'), extensions);
131
+ }, [content, emptyMsg, extensions, getResource]);
132
+ const innerProps: InnerSyncMarkdownProps = {
133
+ renderExtension: extensions?.length > 0 ? renderExtension : undefined,
134
+ exactHeight,
135
+ markup,
136
+ isEmpty: !content,
137
+ className,
138
+ };
139
+ return inline ? <InlineMarkdownView {...innerProps} /> : <IFrameMarkdownView {...innerProps} />;
140
+ };
141
+
142
+ const uniqueId = (function() {
143
+ let num = 0;
144
+ return function(prefix) {
145
+ const prefixStr = String(prefix) || '';
146
+ num += 1;
147
+ return prefixStr + num;
148
+ };
149
+ })();
150
+
151
+ type RenderExtensionProps = {
152
+ renderExtension: (contentDocument: HTMLDocument, rootSelector: string) => React.ReactNode;
153
+ selector: string;
154
+ markup: string;
155
+ docContext?: HTMLDocument;
156
+ };
157
+
158
+ const RenderExtension: React.FC<RenderExtensionProps> = ({
159
+ renderExtension,
160
+ selector,
161
+ markup,
162
+ docContext,
163
+ }) => {
164
+ const forceRender = useForceRender();
165
+ const markupRef = React.useRef<string>(null);
166
+ const shouldRenderExtension = React.useCallback(() => {
167
+ if (markupRef.current === markup) {
168
+ return true;
169
+ }
170
+ markupRef.current = markup;
171
+ return false;
172
+ }, [markup]);
173
+ /**
174
+ * During a render cycle in which markup changes, renderExtension receives an old copy of document
175
+ * because react is still updating the dom using `dangerouslySetInnerHTML` with latest markdown markup
176
+ * which causes the component rendered by renderExtension to receive old copy of document
177
+ * use forceRender to delay the rendering of extension by one render cycle
178
+ */
179
+ React.useEffect(() => {
180
+ if (renderExtension) {
181
+ forceRender();
182
+ }
183
+ // eslint-disable-next-line react-hooks/exhaustive-deps
184
+ }, [markup]);
185
+ return (
186
+ <>{shouldRenderExtension() ? renderExtension?.(docContext ?? document, selector) : null}</>
187
+ );
188
+ };
189
+
190
+ const InlineMarkdownView: React.FC<InnerSyncMarkdownProps> = ({
191
+ markup,
192
+ isEmpty,
193
+ renderExtension,
194
+ className,
195
+ }) => {
196
+ const id = React.useMemo(() => uniqueId('markdown'), []);
197
+ return (
198
+ <div className={css('pfext-markdown-view', { 'is-empty': isEmpty }, className)} id={id}>
199
+ <div dangerouslySetInnerHTML={{ __html: markup }} />
200
+ {renderExtension && (
201
+ <RenderExtension renderExtension={renderExtension} selector={`#${id}`} markup={markup} />
202
+ )}
203
+ </div>
204
+ );
205
+ };
206
+
207
+ const IFrameMarkdownView: React.FC<InnerSyncMarkdownProps> = ({
208
+ exactHeight,
209
+ markup,
210
+ isEmpty,
211
+ renderExtension,
212
+ className,
213
+ }) => {
214
+ const [frame, setFrame] = React.useState<HTMLIFrameElement>();
215
+ const [loaded, setLoaded] = React.useState(false);
216
+ const updateTimeoutHandle = React.useRef<number>();
217
+
218
+ const updateDimensions = React.useCallback(() => {
219
+ if (!frame?.contentWindow?.document.body.firstChild) {
220
+ return;
221
+ }
222
+ frame.style.height = `${frame.contentWindow.document.body.firstElementChild.scrollHeight}px`;
223
+
224
+ // Let the new height take effect, then reset again once we recompute
225
+ // @ts-ignore
226
+ updateTimeoutHandle.current = setTimeout(() => {
227
+ if (exactHeight) {
228
+ frame.style.height = `${frame.contentWindow.document.body.firstElementChild.scrollHeight}px`;
229
+ } else {
230
+ // Increase by 15px for the case where a horizontal scrollbar might appear
231
+ frame.style.height = `${frame.contentWindow.document.body.firstElementChild.scrollHeight +
232
+ 15}px`;
233
+ }
234
+ });
235
+ }, [frame, exactHeight]);
236
+
237
+ React.useEffect(
238
+ () => () => {
239
+ clearTimeout(updateTimeoutHandle.current);
240
+ },
241
+ [],
242
+ );
243
+
244
+ const onLoad = React.useCallback(() => {
245
+ updateDimensions();
246
+ setLoaded(true);
247
+ }, [updateDimensions]);
248
+
249
+ // Find the app's stylesheets and inject them into the frame to ensure consistent styling.
250
+ const filteredLinks = Array.from(document.getElementsByTagName('link')).filter((l) =>
251
+ l.href.includes('app-bundle'),
252
+ );
253
+
254
+ const linkRefs = filteredLinks.reduce(
255
+ (refs, link) => `${refs}
256
+ <link rel="stylesheet" href="${link.href}">`,
257
+ '',
258
+ );
259
+
260
+ const contents = `
261
+ ${linkRefs}
262
+ <style type="text/css">
263
+ body {
264
+ background-color: transparent !important;
265
+ color: ${isEmpty ? '#999' : '#333'};
266
+ font-family: var(--pf-global--FontFamily--sans-serif);
267
+ min-width: auto !important;
268
+ }
269
+ table {
270
+ display: block;
271
+ margin-bottom: 11.5px;
272
+ overflow-x: auto;
273
+ }
274
+ td,
275
+ th {
276
+ border-bottom: 1px solid #ededed;
277
+ padding: 10px;
278
+ vertical-align: top;
279
+ }
280
+ th {
281
+ padding-top: 0;
282
+ }
283
+ </style>
284
+ <body class="pf-m-redhat-font"><div style="overflow-y: auto;">${markup}</div></body>`;
285
+ return (
286
+ <>
287
+ <iframe
288
+ sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin"
289
+ srcDoc={contents}
290
+ style={{ border: '0px', display: 'block', width: '100%', height: '0' }}
291
+ ref={(r) => setFrame(r)}
292
+ onLoad={() => onLoad()}
293
+ className={className}
294
+ />
295
+ {loaded && frame && renderExtension && (
296
+ <RenderExtension
297
+ markup={markup}
298
+ selector={''}
299
+ renderExtension={renderExtension}
300
+ docContext={frame.contentDocument}
301
+ />
302
+ )}
303
+ </>
304
+ );
305
+ };
@@ -0,0 +1,58 @@
1
+ .pfext-status-box {
2
+ padding: 40px 20px;
3
+
4
+ &__loading-message {
5
+ margin-top: var(--pf-global--spacer--sm);
6
+ }
7
+ }
8
+
9
+ .pfext-status-box--loading {
10
+ align-items: center;
11
+ display: flex;
12
+ height: 100%;
13
+ justify-content: center;
14
+ min-height: 50px;
15
+ width: 100%;
16
+ flex-direction: column;
17
+ }
18
+
19
+ .pfext-m-loader {
20
+ min-width: 18px;
21
+ }
22
+
23
+ .pfext-m-loader-dot__one,
24
+ .pfext-m-loader-dot__two,
25
+ .pfext-m-loader-dot__three {
26
+ animation-delay: 0;
27
+ animation-direction: normal;
28
+ animation-duration: 1s;
29
+ animation-fill-mode: forwards;
30
+ animation-iteration-count: infinite;
31
+ animation-name: bouncedelay;
32
+ animation-play-state: running;
33
+ animation-timing-function: ease-in-out;
34
+ background: #419eda;
35
+ border-radius: 100%;
36
+ display: inline-block;
37
+ height: 6px;
38
+ width: 6px;
39
+ }
40
+
41
+ .pfext-m-loader-dot__one {
42
+ animation-delay: -0.32s;
43
+ }
44
+
45
+ .pfext-m-loader-dot__two {
46
+ animation-delay: -0.16s;
47
+ }
48
+
49
+ @keyframes bouncedelay {
50
+ 0%,
51
+ 80%,
52
+ 100% {
53
+ transform: scale(0.25, 0.25);
54
+ }
55
+ 40% {
56
+ transform: scale(1, 1);
57
+ }
58
+ }
@@ -0,0 +1,33 @@
1
+ import * as React from 'react';
2
+
3
+ const MEMO = {};
4
+
5
+ export const CamelCaseWrap: React.SFC<CamelCaseWrapProps> = ({ value, dataTest }) => {
6
+ if (!value) {
7
+ return '-';
8
+ }
9
+
10
+ if (MEMO[value]) {
11
+ return MEMO[value];
12
+ }
13
+
14
+ // Add word break points before capital letters (but keep consecutive capital letters together).
15
+ const words = value.match(/[A-Z]+[^A-Z]*|[^A-Z]+/g);
16
+ const rendered = (
17
+ <span data-test={dataTest}>
18
+ {words.map((word, i) => (
19
+ <React.Fragment key={i}>
20
+ {word}
21
+ {i !== words.length - 1 && <wbr />}
22
+ </React.Fragment>
23
+ ))}
24
+ </span>
25
+ );
26
+ MEMO[value] = rendered;
27
+ return rendered;
28
+ };
29
+
30
+ export type CamelCaseWrapProps = {
31
+ value: string;
32
+ dataTest?: string;
33
+ };
@@ -0,0 +1,3 @@
1
+ export * from './status-box';
2
+ export * from './router';
3
+ export * from './camel-case-wrap';
@@ -0,0 +1,47 @@
1
+ import { History, createBrowserHistory, createMemoryHistory } from 'history';
2
+ import { QUICKSTART_SEARCH_FILTER_KEY, QUICKSTART_STATUS_FILTER_KEY } from '../../../utils/const';
3
+
4
+ type AppHistory = History & { pushPath: History['push'] };
5
+
6
+ let createHistory;
7
+
8
+ try {
9
+ if (process.env.NODE_ENV === 'test') {
10
+ // Running in node. Can't use browser history
11
+ createHistory = createMemoryHistory;
12
+ } else {
13
+ createHistory = createBrowserHistory;
14
+ }
15
+ } catch (unused) {
16
+ createHistory = createBrowserHistory;
17
+ }
18
+
19
+ export const history: AppHistory = createHistory();
20
+
21
+ export const removeQueryArgument = (k: string) => {
22
+ const params = new URLSearchParams(window.location.search);
23
+ if (params.has(k)) {
24
+ params.delete(k);
25
+ const url = new URL(window.location.href);
26
+ // @ts-ignore
27
+ history.replace(`${url.pathname}?${params.toString()}${url.hash}`);
28
+ }
29
+ };
30
+
31
+ export const setQueryArgument = (k: string, v: string) => {
32
+ if (!v) {
33
+ return removeQueryArgument(k);
34
+ }
35
+ const params = new URLSearchParams(window.location.search);
36
+ if (params.get(k) !== v) {
37
+ params.set(k, v);
38
+ const url = new URL(window.location.href);
39
+ // @ts-ignore
40
+ history.replace(`${url.pathname}?${params.toString()}${url.hash}`);
41
+ }
42
+ };
43
+
44
+ export const clearFilterParams = () => {
45
+ removeQueryArgument(QUICKSTART_SEARCH_FILTER_KEY);
46
+ removeQueryArgument(QUICKSTART_STATUS_FILTER_KEY);
47
+ };
@@ -0,0 +1,94 @@
1
+ import * as React from 'react';
2
+ import { css } from '@patternfly/react-styles';
3
+ import { QuickStartContext, QuickStartContextValues } from '../../../utils/quick-start-context';
4
+
5
+ export const Box: React.FC<BoxProps> = ({ children, className }) => (
6
+ <div className={css('pfext-status-box', className)}>{children}</div>
7
+ );
8
+
9
+ export const Loading: React.FC<LoadingProps> = ({ className }) => (
10
+ <div className={css('pfext-m-loader', className)}>
11
+ <div className="pfext-m-loader-dot__one" />
12
+ <div className="pfext-m-loader-dot__two" />
13
+ <div className="pfext-m-loader-dot__three" />
14
+ </div>
15
+ );
16
+ Loading.displayName = 'Loading';
17
+
18
+ export const LoadingBox: React.FC<LoadingBoxProps> = ({ className, message }) => (
19
+ <Box className={css('pfext-status-box--loading', className)}>
20
+ <Loading />
21
+ {message && <div className="pfext-status-box__loading-message">{message}</div>}
22
+ </Box>
23
+ );
24
+ LoadingBox.displayName = 'LoadingBox';
25
+
26
+ export const EmptyBox: React.FC<EmptyBoxProps> = ({ label }) => {
27
+ const { getResource } = React.useContext<QuickStartContextValues>(QuickStartContext);
28
+ return (
29
+ <Box>
30
+ <div data-test="empty-message" className="text-center">
31
+ {label
32
+ ? getResource('No {{label}} found').replace('{{label}}', label)
33
+ : getResource('Not found')}
34
+ </div>
35
+ </Box>
36
+ );
37
+ };
38
+ EmptyBox.displayName = 'EmptyBox';
39
+
40
+ type BoxProps = {
41
+ children: React.ReactNode;
42
+ className?: string;
43
+ };
44
+
45
+ type LoadErrorProps = {
46
+ label: string;
47
+ className?: string;
48
+ message?: string;
49
+ canRetry?: boolean;
50
+ };
51
+
52
+ type LoadingProps = {
53
+ className?: string;
54
+ };
55
+
56
+ type LoadingBoxProps = {
57
+ className?: string;
58
+ message?: string;
59
+ };
60
+
61
+ type EmptyBoxProps = {
62
+ label?: string;
63
+ };
64
+
65
+ type MsgBoxProps = {
66
+ title?: string;
67
+ detail?: React.ReactNode;
68
+ className?: string;
69
+ };
70
+
71
+ type AccessDeniedProps = {
72
+ message?: string;
73
+ };
74
+
75
+ type DataProps = {
76
+ NoDataEmptyMsg?: React.ComponentType;
77
+ EmptyMsg?: React.ComponentType;
78
+ label?: string;
79
+ unfilteredData?: any;
80
+ data?: any;
81
+ children?: React.ReactNode;
82
+ };
83
+
84
+ type StatusBoxProps = {
85
+ label?: string;
86
+ loadError?: any;
87
+ loaded?: boolean;
88
+ data?: any;
89
+ unfilteredData?: any;
90
+ skeleton?: React.ReactNode;
91
+ NoDataEmptyMsg?: React.ComponentType;
92
+ EmptyMsg?: React.ComponentType;
93
+ children?: React.ReactNode;
94
+ };
@@ -0,0 +1,53 @@
1
+ export type AccessReviewResourceAttributes = {
2
+ group?: string;
3
+ resource?: string;
4
+ subresource?: string;
5
+ verb?: K8sVerb;
6
+ name?: string;
7
+ namespace?: string;
8
+ };
9
+
10
+ export type K8sVerb =
11
+ | 'create'
12
+ | 'get'
13
+ | 'list'
14
+ | 'update'
15
+ | 'patch'
16
+ | 'delete'
17
+ | 'deletecollection'
18
+ | 'watch';
19
+
20
+ export type OwnerReference = {
21
+ name: string;
22
+ kind: string;
23
+ uid: string;
24
+ apiVersion: string;
25
+ controller?: boolean;
26
+ blockOwnerDeletion?: boolean;
27
+ };
28
+
29
+ export type ObjectMetadata = {
30
+ name: string;
31
+ annotations?: { [key: string]: string };
32
+ clusterName?: string;
33
+ creationTimestamp?: string;
34
+ deletionGracePeriodSeconds?: number;
35
+ deletionTimestamp?: string;
36
+ finalizers?: string[];
37
+ generateName?: string;
38
+ generation?: number;
39
+ labels?: { [key: string]: string };
40
+ managedFields?: any[];
41
+ namespace?: string;
42
+ ownerReferences?: OwnerReference[];
43
+ resourceVersion?: string;
44
+ uid?: string;
45
+ // language can be: en
46
+ language?: string;
47
+ // country can be: US
48
+ country?: string;
49
+ // locale is a combination of language and country, for example: en_US
50
+ locale?: string;
51
+ // anything else to custom define
52
+ [key: string]: any;
53
+ };
@@ -0,0 +1 @@
1
+ export * from './src';
@@ -0,0 +1,7 @@
1
+ export * from './modal';
2
+ export * from './spotlight';
3
+ export * from './markdown-highlight-extension';
4
+ export * from './markdown-extensions';
5
+ export * from './popper';
6
+ export * from './utils';
7
+ export * from './status';
@@ -0,0 +1,29 @@
1
+ .pfext-page-layout {
2
+ &__content {
3
+ padding: var(--pf-global--spacer--lg);
4
+ flex: 1;
5
+ }
6
+
7
+ &__header {
8
+ padding-top: 1px;
9
+ background-color: var(--pf-global--BackgroundColor--light-100);
10
+ }
11
+
12
+ &__hint {
13
+ padding-left: var(--pf-global--spacer--lg);
14
+ padding-right: var(--pf-global--spacer--lg);
15
+ padding-bottom: var(--pf-global--spacer--md);
16
+ font-size: 14px;
17
+ }
18
+
19
+ &__title {
20
+ padding-left: var(--pf-global--spacer--lg);
21
+ padding-right: var(--pf-global--spacer--lg);
22
+ font-size: var(--pf-global--FontSize--2xl);
23
+ margin-top: 23px;
24
+ margin-bottom: 11.5px;
25
+ font-family: var(--pf-global--FontFamily--heading--sans-serif);
26
+ font-weight: var(--pf-global--FontWeight--normal);
27
+ line-height: 1.1;
28
+ }
29
+ }