@patternfly/quickstarts 1.4.1-rc.1 → 2.1.0

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/README.md CHANGED
@@ -99,7 +99,7 @@ const App = () => {
99
99
  setTimeout(() => {
100
100
  // simulate loading time to get the quick starts from somewhere
101
101
  load();
102
- }, 1500);
102
+ }, 500);
103
103
  }, []);
104
104
 
105
105
  const withQueryParams = true;
@@ -166,38 +166,17 @@ See above usage of `useLegacyHeaderColors` boolean to opt-out of update. Should
166
166
 
167
167
  ## Quick starts format
168
168
 
169
- Quick starts are parsed as markdown. To write your own quick start, if you use Typescript you can [check out the type definition here](https://github.com/patternfly/patternfly-quickstarts/blob/d52b194119f1ff16e69bf589d49a14931a19ac4b/packages/module/src/utils/quick-start-types.ts#L6).
170
-
171
- A basic quick start has this structure:
172
- ```yaml
173
- metadata:
174
- name: id-of-this-quick-start
175
- spec:
176
- displayName: Get started with Node
177
- durationMinutes: 10
178
- description: 'Import a Node Application from git, build, and deploy it onto OpenShift.'
179
- introduction: >-
180
- **Node.js** is based on the V8 JavaScript engine and allows you to write
181
- server-side JavaScript applications. It provides an I/O model based on
182
- events and non-blocking operations that enables you to write efficient
183
- applications.
184
- tasks:
185
- - title: Create a Node application
186
- description: First task description
187
- review:
188
- failedTaskHelp: This task isn’t verified yet. Try the task again.
189
- instructions: >-
190
- The application is represented by the light grey area with the white border. The deployment is a white circle. Verify that the application was successfully created.
191
- - title: View the build status
192
- description: Second task description
193
- review:
194
- failedTaskHelp: This task isn’t verified yet. Try the task again.
195
- instructions: >-
196
- This build may take a few minutes. When it's finished, a **Complete** badge will surface on the page header beside build name **nodejsrest-http-redhat-1**. Did this badge appear?
197
- conclusion: Your Node application is deployed and ready.
198
- ```
169
+ Quick starts are parsed as markdown. To write your own quick start, if you use Typescript you can [check out the type definition here](https://github.com/patternfly/patternfly-quickstarts/blob/main/packages/module/src/utils/quick-start-types.ts).
170
+
171
+ Here's a [yaml template](https://github.com/patternfly/patternfly-quickstarts/blob/main/packages/dev/src/quickstarts-data/yaml/template.yaml) to get you started on writing your own quick starts.
172
+
173
+ ## Writing quick starts
199
174
 
200
- For more examples of quick starts, [you can go here](https://github.com/patternfly/patternfly-quickstarts/tree/main/packages/dev/src/quickstarts-data/mocks/yamls).
175
+ Quick starts are typically written in yaml, but we've also seen projects use asciidoc and json. As long as you can pass in an [array of quick starts](https://github.com/patternfly/patternfly-quickstarts/blob/b086faefb0699e4259ca23d058ed330df1d87f8a/packages/module/src/QuickStartDrawer.tsx#L18) it doesn't really matter in what format your content is sourced.
176
+ - We have a [yaml starter template here](https://github.com/patternfly/patternfly-quickstarts/blob/main/packages/dev/src/quickstarts-data/yaml/template.yaml)
177
+ - The easiest way to preview the content as you're writing it, is to use Visual Studio code with our [quickstarts-preview extension](https://marketplace.visualstudio.com/items?itemName=PatternFly.quickstarts-preview).
178
+ - Alternatively, you can use [github.dev](https://github.dev/) which is basically VS Code on the web, and install the extension there, then edit your yaml content!
179
+ - For guidelines on writing a quick start, the fine folks at OpenShift have created [this guide](https://docs.openshift.com/container-platform/4.9/web_console/creating-quick-start-tutorials.html)
201
180
 
202
181
  ### Highlighting elements
203
182
 
@@ -250,4 +229,4 @@ return (
250
229
  Use this [file](https://github.com/patternfly/patternfly-quickstarts/blob/main/packages/module/src/locales/en/quickstart.json) as a base for your translations.
251
230
  Each language is different, especially when it comes to plurals. Try [this utility](https://jsfiddle.net/6bpxsgd4) sourced from [i18next](https://www.i18next.com/translation-function/plurals#how-to-find-the-correct-plural-suffix) to determine the suffixes for the right plural format.
252
231
 
253
- ####
232
+ For localizing the content of quick starts files, we provide the option to include `language` and `countryCode` key to your translated file. Based on these keys you can filter out quick starts. We have a demo of this behaviour in our [demo app](https://quickstarts.netlify.app/quickstarts-localized). You can have a look at the code [here](https://github.com/patternfly/patternfly-quickstarts/blob/main/packages/dev/src/AppLocalized.tsx).
@@ -16,6 +16,7 @@ export declare type OwnerReference = {
16
16
  blockOwnerDeletion?: boolean;
17
17
  };
18
18
  export declare type ObjectMetadata = {
19
+ name: string;
19
20
  annotations?: {
20
21
  [key: string]: string;
21
22
  };
@@ -30,9 +31,12 @@ export declare type ObjectMetadata = {
30
31
  [key: string]: string;
31
32
  };
32
33
  managedFields?: any[];
33
- name?: string;
34
34
  namespace?: string;
35
35
  ownerReferences?: OwnerReference[];
36
36
  resourceVersion?: string;
37
37
  uid?: string;
38
+ language?: string;
39
+ country?: string;
40
+ locale?: string;
41
+ [key: string]: any;
38
42
  };
@@ -0,0 +1,7 @@
1
+ import './showdown-extension.scss';
2
+ declare const useAdmonitionShowdownExtension: () => {
3
+ type: string;
4
+ regex: RegExp;
5
+ replace: (text: string, content: string, admonitionLabel: string, admonitionType: string, groupId: string) => string;
6
+ };
7
+ export default useAdmonitionShowdownExtension;
@@ -1,3 +1,4 @@
1
1
  export { default as MarkdownCopyClipboard } from './MarkdownCopyClipboard';
2
2
  export { default as useInlineCopyClipboardShowdownExtension } from './inline-clipboard-extension';
3
3
  export { default as useMultilineCopyClipboardShowdownExtension } from './multiline-clipboard-extension';
4
+ export { default as useAdmonitionShowdownExtension } from './admonition-extension';
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { QuickStart } from './utils/quick-start-types';
3
- declare type QuickStartCatalogPageProps = {
3
+ export declare type QuickStartCatalogPageProps = {
4
4
  quickStarts?: QuickStart[];
5
5
  showFilter?: boolean;
6
6
  sortFnc?: (q1: QuickStart, q2: QuickStart) => number;
@@ -12,4 +12,3 @@ export declare const QuickStartCatalogEmptyState: ({ clearFilters }: {
12
12
  clearFilters: any;
13
13
  }) => JSX.Element;
14
14
  export declare const QuickStartCatalogPage: React.FC<QuickStartCatalogPageProps>;
15
- export {};
@@ -9,6 +9,7 @@ declare type QuickStartTaskHeaderProps = {
9
9
  size?: 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
10
10
  isActiveTask?: boolean;
11
11
  onTaskSelect: (index: number) => void;
12
+ chidlren?: React.ReactNode;
12
13
  };
13
14
  declare const QuickStartTaskHeader: React.FC<QuickStartTaskHeaderProps>;
14
15
  export default QuickStartTaskHeader;
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { createContext, useCallback, useEffect, useState } from 'react';
3
- import { Card, CardHeader, CardActions, CardTitle, CardBody, CardFooter, Modal as Modal$1, Tooltip, Popover, PopoverPosition, Button, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectVariant, SelectOption, Toolbar, ToolbarContent, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStatePrimary, Divider, ModalVariant, WizardNavItem, List, ExpandableSection, ListItem, Alert, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody } from '@patternfly/react-core';
3
+ import { Card, CardHeader, CardActions, CardTitle, CardBody, CardFooter, Modal as Modal$1, Tooltip, Alert, Popover, PopoverPosition, Button, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectVariant, SelectOption, Toolbar, ToolbarContent, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStatePrimary, Divider, ModalVariant, WizardNavItem, List, ExpandableSection, ListItem, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody } from '@patternfly/react-core';
4
4
  import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
5
5
  import { css } from '@patternfly/react-styles';
6
6
  import RocketIcon from '@patternfly/react-icons/dist/js/icons/rocket-icon';
@@ -8,6 +8,8 @@ import { __rest } from 'tslib';
8
8
  import * as ReactDOM from 'react-dom';
9
9
  import { renderToStaticMarkup } from 'react-dom/server';
10
10
  import CopyIcon from '@patternfly/react-icons/dist/js/icons/copy-icon';
11
+ import LightbulbIcon from '@patternfly/react-icons/dist/js/icons/lightbulb-icon';
12
+ import FireIcon from '@patternfly/react-icons/dist/js/icons/fire-icon';
11
13
  import SyncAltIcon from '@patternfly/react-icons/dist/js/icons/sync-alt-icon';
12
14
  import CheckCircleIcon from '@patternfly/react-icons/dist/js/icons/check-circle-icon';
13
15
  import ExclamationCircleIcon from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
@@ -125,6 +127,7 @@ var Yes = "Yes";
125
127
  var No = "No";
126
128
  var Cancel = "Cancel";
127
129
  var Leave = "Leave";
130
+ var Type = "Quick start";
128
131
  var en = {
129
132
  "No results found": "No results found",
130
133
  "No results match the filter criteria. Remove filters or clear all filters to show results.": "No results match the filter criteria. Remove filters or clear all filters to show results.",
@@ -168,7 +171,8 @@ var en = {
168
171
  "Not available": "Not available",
169
172
  "Copy to clipboard": "Copy to clipboard",
170
173
  "Successfully copied to clipboard!": "Successfully copied to clipboard!",
171
- "Quick start • {{duration, number}} minutes": "Quick start • {{duration, number}} minutes"
174
+ Type: Type,
175
+ "{{type}} • {{duration, number}} minutes": "{{type}} • {{duration, number}} minutes"
172
176
  };
173
177
 
174
178
  /* eslint-disable */
@@ -581,7 +585,7 @@ const QuickStartContextDefaults = {
581
585
  useLegacyHeaderColors: false,
582
586
  markdown: null,
583
587
  loading: false,
584
- alwaysShowTaskReview: false,
588
+ alwaysShowTaskReview: true,
585
589
  };
586
590
  const QuickStartContext = createContext(QuickStartContextDefaults);
587
591
  const getResource = (resource, options, resourceBundle, lng) => {
@@ -678,7 +682,7 @@ const useValuesForQuickStartContext = (value = {}) => {
678
682
  useQueryParams && setQueryArgument(QUICKSTART_ID_FILTER_KEY, id);
679
683
  return id;
680
684
  });
681
- setAllQuickStartStates((qs) => (Object.assign(Object.assign({}, qs), { [quickStartId]: getDefaultQuickStartState(totalTasks, QuickStartStatus.IN_PROGRESS) })));
685
+ setAllQuickStartStates((qs) => (Object.assign(Object.assign({}, qs), { [quickStartId]: getDefaultQuickStartState(totalTasks, QuickStartStatus.NOT_STARTED) })));
682
686
  }, [setActiveQuickStartID, setAllQuickStartStates, useQueryParams]);
683
687
  // When alwaysShowTaskReview preference is enabled, skip visited step and go directly to review
684
688
  const stepAfterInitial = alwaysShowTaskReview
@@ -1276,6 +1280,39 @@ const useMultilineCopyClipboardShowdownExtension = () => {
1276
1280
  }), [getResource]);
1277
1281
  };
1278
1282
 
1283
+ var AdmonitionType;
1284
+ (function (AdmonitionType) {
1285
+ AdmonitionType["TIP"] = "TIP";
1286
+ AdmonitionType["NOTE"] = "NOTE";
1287
+ AdmonitionType["IMPORTANT"] = "IMPORTANT";
1288
+ AdmonitionType["WARNING"] = "WARNING";
1289
+ AdmonitionType["CAUTION"] = "CAUTION";
1290
+ })(AdmonitionType || (AdmonitionType = {}));
1291
+ const admonitionToAlertVariantMap = {
1292
+ [AdmonitionType.NOTE]: { variant: 'info' },
1293
+ [AdmonitionType.TIP]: { variant: 'default', customIcon: React.createElement(LightbulbIcon, null) },
1294
+ [AdmonitionType.IMPORTANT]: { variant: 'danger' },
1295
+ [AdmonitionType.CAUTION]: { variant: 'warning', customIcon: React.createElement(FireIcon, null) },
1296
+ [AdmonitionType.WARNING]: { variant: 'warning' },
1297
+ };
1298
+ const useAdmonitionShowdownExtension = () => {
1299
+ // const { getResource } = React.useContext<QuickStartContextValues>(QuickStartContext);
1300
+ return React.useMemo(() => ({
1301
+ type: 'lang',
1302
+ regex: /\[([\d\w\s-()$!]+)]{{(admonition) ([\w-]+)}}/g,
1303
+ replace: (text, content, admonitionLabel, admonitionType, groupId) => {
1304
+ if (!content || !admonitionLabel || !admonitionType || !groupId) {
1305
+ return text;
1306
+ }
1307
+ admonitionType = admonitionType.toUpperCase();
1308
+ const { variant, customIcon } = admonitionToAlertVariantMap[admonitionType];
1309
+ const style = admonitionType === AdmonitionType.CAUTION ? { backgroundColor: '#ec7a0915' } : {};
1310
+ const pfAlert = (React.createElement(Alert, { variant: variant, customIcon: customIcon && customIcon, isInline: true, title: admonitionType, className: "pfext-markdown-admonition", style: style }, content));
1311
+ return removeTemplateWhitespace(renderToStaticMarkup(pfAlert));
1312
+ },
1313
+ }), []);
1314
+ };
1315
+
1279
1316
  const FallbackImg = ({ src, alt, className, fallback }) => {
1280
1317
  const [isSrcValid, setIsSrcValid] = React.useState(true);
1281
1318
  if (src && isSrcValid) {
@@ -1353,13 +1390,31 @@ const markdownConvert = (markdown, extensions) => {
1353
1390
  if (extensions) {
1354
1391
  converter.addExtension(extensions);
1355
1392
  }
1356
- // add hook to transform anchor tags
1357
1393
  DOMPurify.addHook('beforeSanitizeElements', function (node) {
1358
1394
  // nodeType 1 = element type
1395
+ // transform anchor tags
1359
1396
  if (node.nodeType === 1 && node.nodeName.toLowerCase() === 'a') {
1360
1397
  node.setAttribute('rel', 'noopener noreferrer');
1361
1398
  return node;
1362
1399
  }
1400
+ // add PF class to ul and ol lists
1401
+ if (node.nodeType === 1 &&
1402
+ (node.nodeName.toLowerCase() === 'ul' || node.nodeName.toLowerCase() === 'ol')) {
1403
+ node.setAttribute('class', 'pf-c-list');
1404
+ return node;
1405
+ }
1406
+ });
1407
+ // Add a hook to make all links open a new window
1408
+ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
1409
+ // set all elements owning target to target=_blank
1410
+ if ('target' in node) {
1411
+ node.setAttribute('target', '_blank');
1412
+ }
1413
+ // set non-HTML/MathML links to xlink:show=new
1414
+ if (!node.hasAttribute('target') &&
1415
+ (node.hasAttribute('xlink:href') || node.hasAttribute('href'))) {
1416
+ node.setAttribute('xlink:show', 'new');
1417
+ }
1363
1418
  });
1364
1419
  return DOMPurify.sanitize(converter.makeHtml(markdown), {
1365
1420
  USE_PROFILES: {
@@ -1497,6 +1552,7 @@ const QuickStartMarkdownView = ({ content, exactHeight, className, }) => {
1497
1552
  const { markdown } = React.useContext(QuickStartContext);
1498
1553
  const inlineCopyClipboardShowdownExtension = useInlineCopyClipboardShowdownExtension();
1499
1554
  const multilineCopyClipboardShowdownExtension = useMultilineCopyClipboardShowdownExtension();
1555
+ const admonitionShowdownExtension = useAdmonitionShowdownExtension();
1500
1556
  return (React.createElement(SyncMarkdownView, { inline: true, content: content, exactHeight: exactHeight, extensions: [
1501
1557
  {
1502
1558
  type: 'lang',
@@ -1518,6 +1574,7 @@ const QuickStartMarkdownView = ({ content, exactHeight, className, }) => {
1518
1574
  },
1519
1575
  inlineCopyClipboardShowdownExtension,
1520
1576
  multilineCopyClipboardShowdownExtension,
1577
+ admonitionShowdownExtension,
1521
1578
  ...(markdown ? markdown.extensions : []),
1522
1579
  ], renderExtension: (docContext, rootSelector) => (React.createElement(React.Fragment, null,
1523
1580
  React.createElement(MarkdownHighlightExtension, { docContext: docContext, rootSelector: rootSelector }),
@@ -1628,7 +1685,9 @@ const QuickStartTile = ({ quickStart, status, isActive, onClick = () => { }, })
1628
1685
  // @ts-ignore
1629
1686
  component: "div", style: {
1630
1687
  cursor: 'pointer',
1631
- }, icon: quickStartIcon, className: "pfext-quick-start-tile", "data-testid": `qs-card-${camelize(displayName)}`, featured: isActive, title: React.createElement(QuickStartTileHeader, { name: displayName, status: status, duration: durationMinutes, type: type, quickStartId: id }), onClick: handleClick, "data-test": `tile ${id}`, description: React.createElement(QuickStartTileDescription, { description: description, prerequisites: prerequisites }), footer: footerComponent })));
1688
+ }, icon: quickStartIcon, className: "pfext-quick-start-tile", "data-testid": `qs-card-${camelize(displayName)}`, featured: isActive, title: React.createElement(QuickStartTileHeader, { name: displayName, status: status, duration: durationMinutes, type: type, quickStartId: id }), onClick: handleClick,
1689
+ // https://github.com/patternfly/patternfly-react/issues/7039
1690
+ href: "#", "data-test": `tile ${id}`, description: React.createElement(QuickStartTileDescription, { description: description, prerequisites: prerequisites }), footer: footerComponent })));
1632
1691
  };
1633
1692
 
1634
1693
  const QuickStartCatalog = ({ quickStarts }) => {
@@ -1779,7 +1838,9 @@ const QuickStartCatalogPage = ({ quickStarts, showFilter, sortFnc = (q1, q2) =>
1779
1838
  const filteredQs = showFilter
1780
1839
  ? filterQuickStarts(allQuickStarts, filter.keyword, filter.status.statusFilters, allQuickStartStates).sort(sortFncCallback)
1781
1840
  : allQuickStarts;
1782
- if (filteredQs.length !== filteredQuickStarts.length) {
1841
+ // also needs a check whether the content of the QS changed
1842
+ if (filteredQs.length !== filteredQuickStarts.length ||
1843
+ JSON.stringify(filteredQs) !== JSON.stringify(filteredQuickStarts)) {
1783
1844
  setFilteredQuickStarts(filteredQs);
1784
1845
  }
1785
1846
  }, [
@@ -1868,14 +1929,17 @@ const TaskIcon = ({ taskIndex, taskStatus }) => {
1868
1929
  }
1869
1930
  return React.createElement("span", { className: classNames }, content);
1870
1931
  };
1871
- const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, isActiveTask, onTaskSelect, }) => {
1932
+ const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, isActiveTask, onTaskSelect, children, }) => {
1872
1933
  const classNames = css('pfext-quick-start-task-header__title', {
1873
1934
  'pfext-quick-start-task-header__title-success': taskStatus === QuickStartTaskStatus.SUCCESS,
1874
1935
  'pfext-quick-start-task-header__title-failed': taskStatus === (QuickStartTaskStatus.FAILED || QuickStartTaskStatus.VISITED),
1875
1936
  });
1876
- const notCompleted = taskStatus === QuickStartTaskStatus.VISITED;
1877
- const skippedReviewOrFailed = taskStatus === QuickStartTaskStatus.REVIEW || taskStatus === QuickStartTaskStatus.FAILED;
1878
- const tryAgain = !isActiveTask && (skippedReviewOrFailed || notCompleted) && (React.createElement(React.Fragment, null,
1937
+ // const notCompleted = taskStatus === QuickStartTaskStatus.VISITED;
1938
+ // const skippedReview = taskStatus === QuickStartTaskStatus.REVIEW;
1939
+ const failedReview = taskStatus === QuickStartTaskStatus.FAILED;
1940
+ // TODO: toned down when this is shown, investigate further when we should display it
1941
+ // related: https://github.com/patternfly/patternfly-quickstarts/issues/104
1942
+ const tryAgain = failedReview && (React.createElement(React.Fragment, null,
1879
1943
  React.createElement("div", null),
1880
1944
  React.createElement("div", { className: "pfext-quick-start-task-header__tryagain" }, "Try the steps again.")));
1881
1945
  const content = (React.createElement("div", { className: "pfext-quick-start-task-header" },
@@ -1886,7 +1950,7 @@ const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, is
1886
1950
  ' ',
1887
1951
  subtitle))),
1888
1952
  tryAgain));
1889
- return (React.createElement(WizardNavItem, { content: content, step: taskIndex, onNavItemClick: () => onTaskSelect(taskIndex - 1), navItemComponent: "button", isCurrent: isActiveTask }));
1953
+ return (React.createElement(WizardNavItem, { content: content, step: taskIndex, onNavItemClick: () => onTaskSelect(taskIndex - 1), navItemComponent: "button", isCurrent: isActiveTask }, children));
1890
1954
  };
1891
1955
 
1892
1956
  const QuickStartTaskHeaderList = ({ tasks, allTaskStatuses, onTaskSelect, }) => {
@@ -1920,7 +1984,8 @@ const QuickStartIntroduction = ({ tasks, introduction, allTaskStatuses, prerequi
1920
1984
  const prereqList = (prereqs === null || prereqs === void 0 ? void 0 : prereqs.length) > 0 && (React.createElement(ExpandableSection, { toggleText: getResource('View Prerequisites ({{totalPrereqs}})').replace('{{totalPrereqs}}', prereqs.length), onToggle: () => setIsPrereqsExpanded(!isPrereqsExpanded), className: "pfext-quick-start-intro__prereq" },
1921
1985
  React.createElement(List, { className: "pfext-quick-start-intro__prereq-list" }, prereqs.map((pr) => {
1922
1986
  return (React.createElement(ListItem, { key: pr, className: "pfext-quick-start-intro__prereq-list__item" },
1923
- React.createElement("span", { className: "pfext-quick-start-intro__prereq-list__item-content" }, pr)));
1987
+ React.createElement("span", { className: "pfext-quick-start-intro__prereq-list__item-content" },
1988
+ React.createElement(QuickStartMarkdownView, { content: pr }))));
1924
1989
  }))));
1925
1990
  return (React.createElement(React.Fragment, null,
1926
1991
  React.createElement(QuickStartMarkdownView, { content: introduction }),
@@ -1949,7 +2014,7 @@ const QuickStartTaskReview = ({ review, taskStatus, onTaskReview, }) => {
1949
2014
  'pfext-quick-start-task-review--failed': taskStatus === QuickStartTaskStatus.FAILED,
1950
2015
  });
1951
2016
  const title = React.createElement("span", { className: alertClassNames }, getResource('Check your work'));
1952
- return (React.createElement(Alert, { className: "pfext-quick-start-task-review-alert", variant: getAlertVariant(taskStatus), title: title, isInline: true },
2017
+ return (React.createElement(Alert, { className: "pfext-quick-start-task-review-alert", variant: getAlertVariant(taskStatus), title: title, isInline: true, role: "alert" },
1953
2018
  React.createElement(QuickStartMarkdownView, { content: instructions }),
1954
2019
  React.createElement("span", { className: "pfext-quick-start-task-review__actions" },
1955
2020
  React.createElement(Radio, { id: "review-success", name: "review-success", "data-testid": "qs-drawer-check-yes", label: getResource('Yes'), className: "pfext-quick-start-task-review__radio", isChecked: taskStatus === QuickStartTaskStatus.SUCCESS, onChange: () => onTaskReview(QuickStartTaskStatus.SUCCESS) }),
@@ -1959,22 +2024,22 @@ const QuickStartTaskReview = ({ review, taskStatus, onTaskReview, }) => {
1959
2024
 
1960
2025
  const QuickStartTasks = ({ tasks, taskNumber, allTaskStatuses, onTaskReview, onTaskSelect, }) => {
1961
2026
  const { getResource, alwaysShowTaskReview } = React.useContext(QuickStartContext);
1962
- return (React.createElement("div", { className: "pfext-quick-start-tasks__list" }, tasks
1963
- .filter((_, index) => allTaskStatuses[index] !== QuickStartTaskStatus.INIT)
1964
- .map((task, index) => {
1965
- const { title, description, review } = task;
1966
- const isActiveTask = index === taskNumber;
1967
- const taskStatus = allTaskStatuses[index];
1968
- const shouldShowTaskReview = (!QUICKSTART_TASKS_INITIAL_STATES.includes(taskStatus) || alwaysShowTaskReview) &&
1969
- review;
1970
- return (React.createElement(React.Fragment, { key: title },
1971
- React.createElement(QuickStartTaskHeader, { taskIndex: index + 1, title: title, size: "md", subtitle: getResource('{{index, number}} of {{tasks, number}}')
1972
- .replace('{{index, number}}', index + 1)
1973
- .replace('{{tasks, number}}', tasks.length), taskStatus: taskStatus, isActiveTask: isActiveTask, onTaskSelect: onTaskSelect }),
1974
- isActiveTask && (React.createElement("div", { className: "pfext-quick-start-task__content" },
1975
- React.createElement(QuickStartMarkdownView, { content: description }),
1976
- shouldShowTaskReview && (React.createElement(QuickStartTaskReview, { review: review, taskStatus: taskStatus, onTaskReview: onTaskReview }))))));
1977
- })));
2027
+ return (React.createElement("div", { className: "pfext-quick-start-tasks__list" },
2028
+ React.createElement("ul", null, tasks
2029
+ .filter((_, index) => allTaskStatuses[index] !== QuickStartTaskStatus.INIT)
2030
+ .map((task, index) => {
2031
+ const { title, description, review } = task;
2032
+ const isActiveTask = index === taskNumber;
2033
+ const taskStatus = allTaskStatuses[index];
2034
+ const shouldShowTaskReview = (!QUICKSTART_TASKS_INITIAL_STATES.includes(taskStatus) || alwaysShowTaskReview) &&
2035
+ review;
2036
+ return (React.createElement(React.Fragment, { key: title },
2037
+ React.createElement(QuickStartTaskHeader, { taskIndex: index + 1, title: title, size: "md", subtitle: getResource('{{index, number}} of {{tasks, number}}')
2038
+ .replace('{{index, number}}', index + 1)
2039
+ .replace('{{tasks, number}}', tasks.length), taskStatus: taskStatus, isActiveTask: isActiveTask, onTaskSelect: onTaskSelect }, isActiveTask && (React.createElement("div", { className: "pfext-quick-start-task__content" },
2040
+ React.createElement(QuickStartMarkdownView, { content: description }),
2041
+ shouldShowTaskReview && (React.createElement(QuickStartTaskReview, { review: review, taskStatus: taskStatus, onTaskReview: onTaskReview })))))));
2042
+ }))));
1978
2043
  };
1979
2044
 
1980
2045
  const QuickStartContent = React.forwardRef(({ quickStart, nextQuickStarts = [], taskNumber, allTaskStatuses, onTaskSelect, onTaskReview, onQuickStartChange, }, ref) => {
@@ -2116,7 +2181,10 @@ const QuickStartPanelContent = (_a) => {
2116
2181
  React.createElement(Title, { headingLevel: "h1", size: "xl", className: "pfext-quick-start-panel-content__name", style: { marginRight: 'var(--pf-global--spacer--md)' } }, quickStart === null || quickStart === void 0 ? void 0 :
2117
2182
  quickStart.spec.displayName,
2118
2183
  ' ',
2119
- React.createElement("small", { className: "pfext-quick-start-panel-content__duration" }, getResource('Quick start • {{duration, number}} minutes', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes).replace('{{duration, number}}', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)))),
2184
+ React.createElement("small", { className: "pfext-quick-start-panel-content__duration" }, (quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes) ? getResource('{{type}} • {{duration, number}} minutes', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)
2185
+ .replace('{{duration, number}}', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)
2186
+ .replace('{{type}}', getResource('Type'))
2187
+ : getResource('Type')))),
2120
2188
  showClose && (React.createElement(DrawerActions, null,
2121
2189
  React.createElement(DrawerCloseButton, { onClick: handleClose, className: "pfext-quick-start-panel-content__close-button", "data-testid": "qs-drawer-close" }))))),
2122
2190
  React.createElement(DrawerPanelBody, { hasNoPadding: true, className: "pfext-quick-start-panel-content__body", "data-test": "content" },
@@ -2128,7 +2196,7 @@ const QuickStartPanelContent = (_a) => {
2128
2196
  };
2129
2197
 
2130
2198
  const QuickStartContainer = (_a) => {
2131
- var { quickStarts, children, activeQuickStartID, allQuickStartStates, setActiveQuickStartID, setAllQuickStartStates, appendTo, fullWidth, onCloseInProgress, onCloseNotInProgress, resourceBundle, showCardFooters, useLegacyHeaderColors, language, loading = false, useQueryParams = true, markdown, contextProps, alwaysShowTaskReview = false } = _a, props = __rest(_a, ["quickStarts", "children", "activeQuickStartID", "allQuickStartStates", "setActiveQuickStartID", "setAllQuickStartStates", "appendTo", "fullWidth", "onCloseInProgress", "onCloseNotInProgress", "resourceBundle", "showCardFooters", "useLegacyHeaderColors", "language", "loading", "useQueryParams", "markdown", "contextProps", "alwaysShowTaskReview"]);
2199
+ var { quickStarts, children, activeQuickStartID, allQuickStartStates, setActiveQuickStartID, setAllQuickStartStates, appendTo, fullWidth, onCloseInProgress, onCloseNotInProgress, resourceBundle, showCardFooters, useLegacyHeaderColors, language, loading = false, useQueryParams = true, markdown, contextProps, alwaysShowTaskReview = true } = _a, props = __rest(_a, ["quickStarts", "children", "activeQuickStartID", "allQuickStartStates", "setActiveQuickStartID", "setAllQuickStartStates", "appendTo", "fullWidth", "onCloseInProgress", "onCloseNotInProgress", "resourceBundle", "showCardFooters", "useLegacyHeaderColors", "language", "loading", "useQueryParams", "markdown", "contextProps", "alwaysShowTaskReview"]);
2132
2200
  const valuesForQuickstartContext = useValuesForQuickStartContext(Object.assign({ allQuickStarts: quickStarts, activeQuickStartID,
2133
2201
  setActiveQuickStartID,
2134
2202
  allQuickStartStates,
@@ -2166,7 +2234,7 @@ const QuickStartDrawer = (_a) => {
2166
2234
  // if there is a quick start param, but the quick start is not active, set it
2167
2235
  // this can happen if a new browser session is opened or an incognito window for example
2168
2236
  const quickStartIdFromParam = params.get(QUICKSTART_ID_FILTER_KEY) || '';
2169
- if (quickStartIdFromParam && !activeQuickStartID) {
2237
+ if (quickStartIdFromParam && activeQuickStartID !== quickStartIdFromParam) {
2170
2238
  const activeQuickStart = getQuickStartByName(quickStartIdFromParam, combinedQuickStarts);
2171
2239
  // don't try to load a quick start that is actually just an external resource (spec.link)
2172
2240
  if (combinedQuickStarts.length > 0 && activeQuickStart && !activeQuickStart.spec.link) {