@ansible/ansible-ui-framework 0.0.190

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/cjs/framework/BulkActionDialog.js +217 -0
  3. package/cjs/framework/BulkProgressDialog.js +240 -0
  4. package/cjs/framework/FilterDrawer.js +64 -0
  5. package/cjs/framework/PageBody.js +47 -0
  6. package/cjs/framework/PageCatalog.js +178 -0
  7. package/cjs/framework/PageCells.js +141 -0
  8. package/cjs/framework/PageColumnModal.js +130 -0
  9. package/cjs/framework/PageDataList.js +61 -0
  10. package/cjs/framework/PageDialog.js +28 -0
  11. package/cjs/framework/PageForm.js +376 -0
  12. package/cjs/framework/PageFramework.js +11 -0
  13. package/cjs/framework/PageHeader.js +96 -0
  14. package/cjs/framework/PageLayout.js +41 -0
  15. package/cjs/framework/PagePagination.js +28 -0
  16. package/cjs/framework/PageTable.js +205 -0
  17. package/cjs/framework/PageTabs.js +82 -0
  18. package/cjs/framework/PageToolbar.js +209 -0
  19. package/cjs/framework/Settings.js +122 -0
  20. package/cjs/framework/TypedActions.js +303 -0
  21. package/cjs/framework/components/BulkSelector.js +89 -0
  22. package/cjs/framework/components/Collapse.js +22 -0
  23. package/cjs/framework/components/DetailInfo.js +23 -0
  24. package/cjs/framework/components/Details.js +88 -0
  25. package/cjs/framework/components/Dotted.js +19 -0
  26. package/cjs/framework/components/DropdownControlled.js +28 -0
  27. package/cjs/framework/components/ErrorBoundary.js +45 -0
  28. package/cjs/framework/components/Grid.js +64 -0
  29. package/cjs/framework/components/Help.js +24 -0
  30. package/cjs/framework/components/IconWrapper.js +55 -0
  31. package/cjs/framework/components/LoadingPage.js +14 -0
  32. package/cjs/framework/components/Masonry.js +113 -0
  33. package/cjs/framework/components/Scrollable.js +87 -0
  34. package/cjs/framework/components/SingleSelect.js +70 -0
  35. package/cjs/framework/components/patternfly-colors.js +32 -0
  36. package/cjs/framework/components/useBreakPoint.js +145 -0
  37. package/cjs/framework/components/useOpen.js +36 -0
  38. package/cjs/framework/components/useWindowLocation.js +70 -0
  39. package/cjs/framework/index.js +39 -0
  40. package/cjs/framework/useFrameworkTranslations.js +38 -0
  41. package/cjs/framework/useSelectDialog.js +81 -0
  42. package/cjs/framework/useSelectMultipleDialog.js +62 -0
  43. package/cjs/framework/useTableItems.js +485 -0
  44. package/cjs/framework/useView.js +155 -0
  45. package/cjs/framework/utils/compare.js +59 -0
  46. package/cjs/framework/utils/download-file.js +23 -0
  47. package/cjs/framework/utils/random-string.js +17 -0
  48. package/cjs/frontend/controller/access/organizations/Organization.js +2 -0
  49. package/mjs/framework/BulkActionDialog.d.ts +25 -0
  50. package/mjs/framework/BulkActionDialog.js +104 -0
  51. package/mjs/framework/BulkProgressDialog.d.ts +20 -0
  52. package/mjs/framework/BulkProgressDialog.js +131 -0
  53. package/mjs/framework/FilterDrawer.d.ts +8 -0
  54. package/mjs/framework/FilterDrawer.js +24 -0
  55. package/mjs/framework/PageBody.d.ts +4 -0
  56. package/mjs/framework/PageBody.js +29 -0
  57. package/mjs/framework/PageCatalog.d.ts +113 -0
  58. package/mjs/framework/PageCatalog.js +140 -0
  59. package/mjs/framework/PageCells.d.ts +35 -0
  60. package/mjs/framework/PageCells.js +102 -0
  61. package/mjs/framework/PageColumnModal.d.ts +7 -0
  62. package/mjs/framework/PageColumnModal.js +64 -0
  63. package/mjs/framework/PageDataList.d.ts +46 -0
  64. package/mjs/framework/PageDataList.js +45 -0
  65. package/mjs/framework/PageDialog.d.ts +10 -0
  66. package/mjs/framework/PageDialog.js +12 -0
  67. package/mjs/framework/PageForm.d.ts +147 -0
  68. package/mjs/framework/PageForm.js +316 -0
  69. package/mjs/framework/PageFramework.d.ts +4 -0
  70. package/mjs/framework/PageFramework.js +7 -0
  71. package/mjs/framework/PageHeader.d.ts +45 -0
  72. package/mjs/framework/PageHeader.js +80 -0
  73. package/mjs/framework/PageLayout.d.ts +15 -0
  74. package/mjs/framework/PageLayout.js +23 -0
  75. package/mjs/framework/PagePagination.d.ts +10 -0
  76. package/mjs/framework/PagePagination.js +22 -0
  77. package/mjs/framework/PageTable.d.ts +68 -0
  78. package/mjs/framework/PageTable.js +170 -0
  79. package/mjs/framework/PageTabs.d.ts +15 -0
  80. package/mjs/framework/PageTabs.js +45 -0
  81. package/mjs/framework/PageToolbar.d.ts +57 -0
  82. package/mjs/framework/PageToolbar.js +148 -0
  83. package/mjs/framework/Settings.d.ts +19 -0
  84. package/mjs/framework/Settings.js +87 -0
  85. package/mjs/framework/TypedActions.d.ts +80 -0
  86. package/mjs/framework/TypedActions.js +251 -0
  87. package/mjs/framework/components/BulkSelector.d.ts +11 -0
  88. package/mjs/framework/components/BulkSelector.js +56 -0
  89. package/mjs/framework/components/Collapse.d.ts +5 -0
  90. package/mjs/framework/components/Collapse.js +7 -0
  91. package/mjs/framework/components/DetailInfo.d.ts +5 -0
  92. package/mjs/framework/components/DetailInfo.js +8 -0
  93. package/mjs/framework/components/Details.d.ts +38 -0
  94. package/mjs/framework/components/Details.js +68 -0
  95. package/mjs/framework/components/Dotted.d.ts +4 -0
  96. package/mjs/framework/components/Dotted.js +4 -0
  97. package/mjs/framework/components/DropdownControlled.d.ts +4 -0
  98. package/mjs/framework/components/DropdownControlled.js +8 -0
  99. package/mjs/framework/components/ErrorBoundary.d.ts +15 -0
  100. package/mjs/framework/components/ErrorBoundary.js +25 -0
  101. package/mjs/framework/components/Grid.d.ts +6 -0
  102. package/mjs/framework/components/Grid.js +27 -0
  103. package/mjs/framework/components/Help.d.ts +5 -0
  104. package/mjs/framework/components/Help.js +9 -0
  105. package/mjs/framework/components/IconWrapper.d.ts +8 -0
  106. package/mjs/framework/components/IconWrapper.js +40 -0
  107. package/mjs/framework/components/LoadingPage.d.ts +6 -0
  108. package/mjs/framework/components/LoadingPage.js +9 -0
  109. package/mjs/framework/components/Masonry.d.ts +6 -0
  110. package/mjs/framework/components/Masonry.js +69 -0
  111. package/mjs/framework/components/Scrollable.d.ts +7 -0
  112. package/mjs/framework/components/Scrollable.js +60 -0
  113. package/mjs/framework/components/SingleSelect.d.ts +18 -0
  114. package/mjs/framework/components/SingleSelect.js +37 -0
  115. package/mjs/framework/components/patternfly-colors.d.ts +13 -0
  116. package/mjs/framework/components/patternfly-colors.js +28 -0
  117. package/mjs/framework/components/useBreakPoint.d.ts +5 -0
  118. package/mjs/framework/components/useBreakPoint.js +118 -0
  119. package/mjs/framework/components/useOpen.d.ts +4 -0
  120. package/mjs/framework/components/useOpen.js +16 -0
  121. package/mjs/framework/components/useWindowLocation.d.ts +6 -0
  122. package/mjs/framework/components/useWindowLocation.js +48 -0
  123. package/mjs/framework/index.d.ts +23 -0
  124. package/mjs/framework/index.js +23 -0
  125. package/mjs/framework/useFrameworkTranslations.d.ts +17 -0
  126. package/mjs/framework/useFrameworkTranslations.js +22 -0
  127. package/mjs/framework/useSelectDialog.d.ts +30 -0
  128. package/mjs/framework/useSelectDialog.js +49 -0
  129. package/mjs/framework/useSelectMultipleDialog.d.ts +21 -0
  130. package/mjs/framework/useSelectMultipleDialog.js +29 -0
  131. package/mjs/framework/useTableItems.d.ts +76 -0
  132. package/mjs/framework/useTableItems.js +371 -0
  133. package/mjs/framework/useView.d.ts +15 -0
  134. package/mjs/framework/useView.js +108 -0
  135. package/mjs/framework/utils/compare.d.ts +3 -0
  136. package/mjs/framework/utils/compare.js +53 -0
  137. package/mjs/framework/utils/download-file.d.ts +2 -0
  138. package/mjs/framework/utils/download-file.js +18 -0
  139. package/mjs/framework/utils/random-string.d.ts +1 -0
  140. package/mjs/framework/utils/random-string.js +12 -0
  141. package/mjs/frontend/controller/access/organizations/Organization.d.ts +44 -0
  142. package/mjs/frontend/controller/access/organizations/Organization.js +1 -0
  143. package/package.json +39 -0
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.downloadCvsFile = exports.downloadTextFile = void 0;
4
+ function downloadTextFile(name, content) {
5
+ var file = new Blob(content.split('/n'), { type: 'text/plain' });
6
+ var element = document.createElement('a');
7
+ element.href = URL.createObjectURL(file);
8
+ element.download = name + '.txt';
9
+ document.body.appendChild(element);
10
+ element.click();
11
+ document.body.removeChild(element);
12
+ }
13
+ exports.downloadTextFile = downloadTextFile;
14
+ function downloadCvsFile(name, content) {
15
+ var file = new Blob(content, { type: 'text/csv' });
16
+ var element = document.createElement('a');
17
+ element.href = URL.createObjectURL(file);
18
+ element.download = name + '.csv';
19
+ document.body.appendChild(element);
20
+ element.click();
21
+ document.body.removeChild(element);
22
+ }
23
+ exports.downloadCvsFile = downloadCvsFile;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /* istanbul ignore file */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.randomString = void 0;
5
+ var randomCharacters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
6
+ function randomString(length, base) {
7
+ if (base === void 0) { base = randomCharacters.length; }
8
+ if (base > randomCharacters.length || base <= 0)
9
+ base = randomCharacters.length;
10
+ var text = '';
11
+ for (var i = 0; i < length; i++) {
12
+ var index = Math.floor(Math.random() * base) % base;
13
+ text += randomCharacters.charAt(index);
14
+ }
15
+ return text;
16
+ }
17
+ exports.randomString = randomString;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,25 @@
1
+ /// <reference types="react" />
2
+ import { ITableColumn } from './PageTable';
3
+ export interface BulkActionDialogProps {
4
+ isDanger?: boolean;
5
+ }
6
+ export declare function BulkActionDialog<T extends object>(props: {
7
+ title: string;
8
+ prompt?: string;
9
+ submitting: string;
10
+ submittingTitle: string;
11
+ submitText: string;
12
+ confirmText: string;
13
+ cancelText?: string;
14
+ error: string;
15
+ closeText?: string;
16
+ successText?: string;
17
+ pendingText?: string;
18
+ isDanger?: boolean;
19
+ items: T[];
20
+ columns: ITableColumn<T>[];
21
+ errorColumns: ITableColumn<T>[];
22
+ keyFn: (item: T) => string | number;
23
+ action: (item: T) => Promise<void>;
24
+ onClose?: (items: T[]) => void;
25
+ }): JSX.Element;
@@ -0,0 +1,104 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Checkbox, Modal, ModalBoxBody, ModalVariant, Progress, ProgressMeasureLocation, ProgressSize, ProgressVariant, } from '@patternfly/react-core';
3
+ import { CheckCircleIcon, ExclamationCircleIcon, PendingIcon } from '@patternfly/react-icons';
4
+ import pLimit from 'p-limit';
5
+ import { useCallback, useState } from 'react';
6
+ import { Collapse } from './components/Collapse';
7
+ import { usePageDialog } from './PageDialog';
8
+ import { PageTable } from './PageTable';
9
+ import { useFrameworkTranslations } from './useFrameworkTranslations';
10
+ import { usePaged } from './useTableItems';
11
+ export function BulkActionDialog(props) {
12
+ const [_, setDialog] = usePageDialog();
13
+ const [translations] = useFrameworkTranslations();
14
+ const [isSubmitting, setSubmitting] = useState(false);
15
+ const [isSubmited, setSubmited] = useState(false);
16
+ const [progress, setProgress] = useState(0);
17
+ const [error, setError] = useState('');
18
+ const [statuses, setStatuses] = useState();
19
+ const onClose = useCallback(() => {
20
+ props.onClose?.(props.items.filter((item) => statuses?.[props.keyFn(item)] === null));
21
+ setDialog(undefined);
22
+ }, [props, setDialog, statuses]);
23
+ const onConfirm = () => {
24
+ async function handleConfirm() {
25
+ const limit = pLimit(5);
26
+ setSubmitting(true);
27
+ let progress = 0;
28
+ await Promise.all(props.items.map((item) => limit(async () => {
29
+ const key = props.keyFn(item);
30
+ try {
31
+ await props.action(item);
32
+ setStatuses((statuses) => ({ ...(statuses ?? {}), [key]: null }));
33
+ }
34
+ catch (err) {
35
+ if (err instanceof Error) {
36
+ const message = err.message;
37
+ setStatuses((statuses) => ({ ...(statuses ?? {}), [key]: message }));
38
+ }
39
+ else {
40
+ setStatuses((statuses) => ({
41
+ ...(statuses ?? {}),
42
+ [key]: `Unknown error`,
43
+ }));
44
+ }
45
+ setError(props.error);
46
+ }
47
+ finally {
48
+ setProgress(++progress);
49
+ }
50
+ })));
51
+ setSubmitting(false);
52
+ setSubmited(true);
53
+ }
54
+ void handleConfirm();
55
+ };
56
+ const { paged, page, perPage, setPage, setPerPage } = usePaged(props.items);
57
+ const [confirmed, setConfirmed] = useState(!props.confirmText);
58
+ return (_jsx(Modal, { titleIconVariant: props.isDanger ? 'warning' : undefined, title: props.title, variant: ModalVariant.medium, isOpen: true, onClose: onClose, actions: !isSubmited
59
+ ? [
60
+ _jsx(Button, { variant: props.isDanger ? 'danger' : 'primary', onClick: onConfirm, isDisabled: !confirmed || isSubmitting || isSubmited, isLoading: isSubmitting, children: isSubmitting
61
+ ? props.submitting ?? translations.submittingText
62
+ : props.submitText ?? translations.submitText }, "submit"),
63
+ _jsx(Button, { variant: "link", onClick: onClose, children: props.cancelText ?? translations.cancelText }, "cancel"),
64
+ ]
65
+ : [
66
+ _jsx(Button, { variant: "secondary", onClick: onClose, children: props.closeText ?? translations.closeText }, "close"),
67
+ ], description: _jsx(Collapse, { open: !isSubmitting && !isSubmited, children: props.prompt }), hasNoBodyWrapper: true, children: _jsxs(ModalBoxBody, { style: { paddingLeft: 0, paddingRight: 0 }, children: [_jsx(Collapse, { open: isSubmitting || isSubmited, children: _jsx(ModalBoxBody, { style: { paddingTop: 0 }, children: _jsx(Progress, { value: (progress / props.items.length) * 100, title: error
68
+ ? props.error
69
+ : progress === props.items.length
70
+ ? props.successText ?? translations.successText
71
+ : props.submittingTitle, size: ProgressSize.lg, variant: error
72
+ ? ProgressVariant.danger
73
+ : progress === props.items.length
74
+ ? ProgressVariant.success
75
+ : undefined, measureLocation: error && progress === props.items.length ? ProgressMeasureLocation.none : undefined }) }) }), _jsx("div", { style: {
76
+ display: 'flex',
77
+ flexDirection: 'column',
78
+ maxHeight: 500,
79
+ overflow: 'hidden',
80
+ borderTop: 'thin solid var(--pf-global--BorderColor--100)',
81
+ }, children: !isSubmitting && !isSubmited ? (_jsx(PageTable, { pageItems: paged, itemCount: props.items.length, tableColumns: props.columns, keyFn: props.keyFn, page: page, perPage: perPage, setPage: setPage, setPerPage: setPerPage, compact: true, errorStateTitle: "Error", emptyStateTitle: "No items" }, "items")) : (_jsx(PageTable, { pageItems: [...paged], itemCount: props.items.length, tableColumns: [
82
+ ...props.errorColumns,
83
+ {
84
+ header: 'Status',
85
+ cell: (item) => {
86
+ const key = props.keyFn(item);
87
+ const status = statuses?.[key];
88
+ if (status === undefined) {
89
+ return (_jsxs("span", { style: {
90
+ color: 'var(--pf-global--info-color--100)',
91
+ }, children: [_jsx(PendingIcon, {}), "\u00A0 ", props.pendingText ?? translations.pendingText, ' ', JSON.stringify(status)] }));
92
+ }
93
+ if (status === null) {
94
+ return (_jsxs("span", { style: {
95
+ color: 'var(--pf-global--success-color--100)',
96
+ }, children: [_jsx(CheckCircleIcon, {}), "\u00A0", ' ', props.successText ?? translations.successText] }));
97
+ }
98
+ return (_jsxs("span", { style: {
99
+ color: 'var(--pf-global--danger-color--100)',
100
+ }, children: [_jsx(ExclamationCircleIcon, {}), "\u00A0 ", statuses?.[key]] }));
101
+ },
102
+ },
103
+ ], keyFn: props.keyFn, page: page, perPage: perPage, setPage: setPage, setPerPage: setPerPage, compact: true, errorStateTitle: "", emptyStateTitle: "No items" }, "status")) }), props.confirmText && (_jsx(Collapse, { open: !isSubmitting && !isSubmited, children: _jsx("div", { style: { marginLeft: 32, marginTop: 0, marginBottom: 8 }, children: _jsx(Checkbox, { id: "confirm", label: props.confirmText, isChecked: confirmed, onChange: setConfirmed }) }) }))] }) }));
104
+ }
@@ -0,0 +1,20 @@
1
+ /// <reference types="react" />
2
+ import { ITableColumn } from './PageTable';
3
+ export interface BulkProgressDialogProps<T extends object> {
4
+ title: string;
5
+ keyFn: (item: T) => string | number;
6
+ items: T[];
7
+ columns: ITableColumn<T>[];
8
+ actionFn: (item: T, signal: AbortSignal) => Promise<unknown>;
9
+ onClose?: (items: T[]) => void;
10
+ processingText?: string;
11
+ errorText?: string;
12
+ successText?: string;
13
+ itemPendingText?: string;
14
+ itemSuccessText?: string;
15
+ cancelText?: string;
16
+ closeText?: string;
17
+ isDanger?: boolean;
18
+ }
19
+ export declare function BulkProgressDialog<T extends object>(props: BulkProgressDialogProps<T>): JSX.Element;
20
+ export declare function useBulkProgressDialog<T extends object>(): import("react").Dispatch<import("react").SetStateAction<BulkProgressDialogProps<T> | undefined>>;
@@ -0,0 +1,131 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Modal, ModalBoxBody, ModalVariant, Progress, ProgressSize, ProgressVariant, } from '@patternfly/react-core';
3
+ import { CheckCircleIcon, ExclamationCircleIcon, PendingIcon } from '@patternfly/react-icons';
4
+ import pLimit from 'p-limit';
5
+ import { useCallback, useEffect, useState } from 'react';
6
+ import { usePageDialog } from './PageDialog';
7
+ import { PageTable } from './PageTable';
8
+ import { useFrameworkTranslations } from './useFrameworkTranslations';
9
+ import { usePaged } from './useTableItems';
10
+ export function BulkProgressDialog(props) {
11
+ const { title, keyFn, items, columns, actionFn, onClose, processingText, errorText, itemPendingText, itemSuccessText, successText, cancelText, closeText, isDanger, } = props;
12
+ const [translations] = useFrameworkTranslations();
13
+ const [isProcessing, setProcessing] = useState(true);
14
+ const [progress, setProgress] = useState(0);
15
+ const [error, setError] = useState('');
16
+ const [statuses, setStatuses] = useState();
17
+ const [abortController] = useState(() => new AbortController());
18
+ const onCancelClicked = useCallback(() => {
19
+ abortController.abort();
20
+ setProcessing(false);
21
+ }, [abortController]);
22
+ const onCloseClicked = useCallback(() => {
23
+ onClose?.(items.filter((item) => statuses?.[keyFn(item)] === null));
24
+ }, [items, keyFn, onClose, statuses]);
25
+ useEffect(() => {
26
+ async function process() {
27
+ const limit = pLimit(5);
28
+ let progress = 0;
29
+ await Promise.all(items.map((item) => limit(async () => {
30
+ if (abortController.signal.aborted)
31
+ return;
32
+ const key = keyFn(item);
33
+ try {
34
+ await actionFn(item, abortController.signal);
35
+ if (!abortController.signal.aborted) {
36
+ setStatuses((statuses) => ({ ...(statuses ?? {}), [key]: null }));
37
+ }
38
+ }
39
+ catch (err) {
40
+ if (!abortController.signal.aborted) {
41
+ if (err instanceof Error) {
42
+ const message = err.message;
43
+ setStatuses((statuses) => ({
44
+ ...(statuses ?? {}),
45
+ [key]: message,
46
+ }));
47
+ }
48
+ else {
49
+ setStatuses((statuses) => ({
50
+ ...(statuses ?? {}),
51
+ [key]: `Unknown error`,
52
+ }));
53
+ }
54
+ setError(errorText ?? translations.errorText);
55
+ }
56
+ }
57
+ finally {
58
+ if (!abortController.signal.aborted) {
59
+ setProgress(++progress);
60
+ }
61
+ }
62
+ })));
63
+ if (!abortController.signal.aborted) {
64
+ setProcessing(false);
65
+ }
66
+ }
67
+ void process();
68
+ }, [abortController, actionFn, errorText, items, keyFn, translations.errorText]);
69
+ const { paged, page, perPage, setPage, setPerPage } = usePaged(items);
70
+ return (_jsxs(Modal, { titleIconVariant: isDanger ? 'warning' : undefined, title: title, variant: ModalVariant.medium, isOpen: true, onClose: () => {
71
+ onCancelClicked();
72
+ onCloseClicked();
73
+ }, actions: isProcessing
74
+ ? [
75
+ _jsx(Button, { variant: "link", onClick: onCancelClicked, children: cancelText ?? translations.cancelText }, "cancel"),
76
+ ]
77
+ : [
78
+ _jsx(Button, { variant: "secondary", onClick: onCloseClicked, children: closeText ?? translations.closeText }, "close"),
79
+ ], hasNoBodyWrapper: true, children: [_jsx(ModalBoxBody, { children: _jsx(Progress, { value: (progress / items.length) * 100, title: abortController.signal.aborted
80
+ ? 'Cancelled'
81
+ : error
82
+ ? errorText ?? translations.errorText
83
+ : progress === items.length
84
+ ? successText ?? translations.successText
85
+ : processingText ?? translations.processingText, size: ProgressSize.lg, variant: error
86
+ ? ProgressVariant.danger
87
+ : progress === items.length
88
+ ? ProgressVariant.success
89
+ : undefined }) }), _jsx("div", { style: {
90
+ display: 'flex',
91
+ flexDirection: 'column',
92
+ maxHeight: 560,
93
+ overflow: 'hidden',
94
+ paddingTop: 16,
95
+ }, children: _jsx(PageTable, { pageItems: [...paged], itemCount: items.length, tableColumns: [
96
+ ...columns,
97
+ {
98
+ header: 'Status',
99
+ cell: (item) => {
100
+ const key = keyFn(item);
101
+ const status = statuses?.[key];
102
+ if (status === undefined) {
103
+ return (_jsxs("span", { style: { color: 'var(--pf-global--info-color--100)' }, children: [_jsx(PendingIcon, {}), "\u00A0 ", itemPendingText ?? translations.pendingText, ' ', JSON.stringify(status)] }));
104
+ }
105
+ if (status === null) {
106
+ return (_jsxs("span", { style: {
107
+ color: 'var(--pf-global--success-color--100)',
108
+ }, children: [_jsx(CheckCircleIcon, {}), "\u00A0 ", itemSuccessText ?? translations.successText] }));
109
+ }
110
+ return (_jsxs("span", { style: { color: 'var(--pf-global--danger-color--100)' }, children: [_jsx(ExclamationCircleIcon, {}), "\u00A0 ", statuses?.[key]] }));
111
+ },
112
+ },
113
+ ], keyFn: keyFn, page: page, perPage: perPage, setPage: setPage, setPerPage: setPerPage, compact: true, errorStateTitle: "", emptyStateTitle: "No items" }, "status") })] }));
114
+ }
115
+ export function useBulkProgressDialog() {
116
+ const [_, setDialog] = usePageDialog();
117
+ const [props, setProps] = useState();
118
+ useEffect(() => {
119
+ if (props) {
120
+ const onCloseHandler = (items) => {
121
+ setProps(undefined);
122
+ props.onClose?.(items);
123
+ };
124
+ setDialog(_jsx(BulkProgressDialog, { ...props, onClose: onCloseHandler }));
125
+ }
126
+ else {
127
+ setDialog(undefined);
128
+ }
129
+ }, [props, setDialog]);
130
+ return setProps;
131
+ }
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { IFilterState, IItemFilter, SetFilterValues } from './PageToolbar';
3
+ export declare function FilterDrawer<T extends object>(props: {
4
+ filters?: IItemFilter<T>[];
5
+ filterState: IFilterState;
6
+ setFilterValues: SetFilterValues<T>;
7
+ t?: (t: string) => string;
8
+ }): JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
3
+ /* eslint-disable @typescript-eslint/no-empty-function */
4
+ import { Checkbox, DrawerPanelBody, DrawerPanelContent, DrawerSection, Stack, Title, } from '@patternfly/react-core';
5
+ import { Fragment, useCallback } from 'react';
6
+ export function FilterDrawer(props) {
7
+ let { t } = props;
8
+ t = t ? t : (t) => t;
9
+ const { filters, filterState, setFilterValues } = props;
10
+ const toggleFilterValue = useCallback((filter, filterValues, option) => {
11
+ if (filterValues?.includes(option)) {
12
+ setFilterValues(filter, filterValues.filter((o) => o !== option));
13
+ }
14
+ else {
15
+ setFilterValues(filter, [...(filterValues ?? []), option]);
16
+ }
17
+ }, [setFilterValues]);
18
+ if (!filters)
19
+ return _jsx(Fragment, {});
20
+ return (_jsx(DrawerPanelContent, { minSize: "250px", defaultSize: "250px", maxSize: "250px", children: _jsxs(DrawerPanelBody, { children: [_jsx(Title, { headingLevel: "h2", style: { paddingBottom: 24 }, children: t('Filters') }), filters?.map((filter) => {
21
+ const filterValues = filterState[filter.label];
22
+ return (_jsx(DrawerSection, { style: { paddingBottom: 32 }, children: _jsxs(Stack, { hasGutter: true, children: [_jsx(Title, { headingLevel: "h4", children: filter.label }), filter.options.map((option) => (_jsx(Checkbox, { id: option.label, isChecked: filterValues?.includes(option.value), onChange: () => toggleFilterValue(filter, filterValues, option.value), label: option.label }, option.label)))] }) }, filter.label));
23
+ })] }) }));
24
+ }
@@ -0,0 +1,4 @@
1
+ import { ReactNode } from 'react';
2
+ export declare function PageBody(props: {
3
+ children: ReactNode;
4
+ }): JSX.Element;
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useTranslation } from 'react-i18next';
3
+ import { useBreakpoint } from '.';
4
+ import ErrorBoundary from './components/ErrorBoundary';
5
+ import { useSettings } from './Settings';
6
+ export function PageBody(props) {
7
+ const usePadding = useBreakpoint('xxl');
8
+ const settings = useSettings();
9
+ const { t } = useTranslation();
10
+ return (_jsx(ErrorBoundary, { message: t('Error'), children: _jsx("div", { style: {
11
+ display: 'flex',
12
+ flexDirection: 'column',
13
+ height: '100%',
14
+ maxHeight: '100%',
15
+ overflow: 'hidden',
16
+ backgroundColor: 'var(--pf-c-page__main-section--BackgroundColor)',
17
+ }, children: _jsx("div", { style: {
18
+ display: 'flex',
19
+ flexDirection: 'column',
20
+ height: '100%',
21
+ maxHeight: '100%',
22
+ margin: usePadding ? 24 : 0,
23
+ overflow: 'hidden',
24
+ border: settings.borders && usePadding
25
+ ? 'thin solid var(--pf-global--BorderColor--100)'
26
+ : undefined,
27
+ backgroundColor: 'var(--pf-global--BackgroundColor--100)',
28
+ }, children: props.children }) }) }));
29
+ }
@@ -0,0 +1,113 @@
1
+ import { ReactNode } from 'react';
2
+ import { ITypedAction } from './TypedActions';
3
+ declare type CatalogFilterValue = string;
4
+ interface ICatalogFilterGroup {
5
+ id: string;
6
+ label: string;
7
+ filters?: ICatalogFilter[];
8
+ }
9
+ interface ICatalogFilter {
10
+ id?: string;
11
+ label?: string;
12
+ value: CatalogFilterValue;
13
+ filters?: ICatalogFilter[];
14
+ }
15
+ export declare function Catalog<T extends object>(props: {
16
+ keyFn: (item: T) => string;
17
+ items: T[];
18
+ itemToCardFn: (item: T) => ICatalogCard;
19
+ filterGroups?: ICatalogFilterGroup[];
20
+ onBack?: () => void;
21
+ cardWidth?: number;
22
+ selectItem: (item: T) => void;
23
+ unselectItem: (item: T) => void;
24
+ isSelected: (item: T) => boolean;
25
+ itemActions?: ITypedAction<T>[];
26
+ showSelect: boolean;
27
+ }): JSX.Element;
28
+ export declare enum CatalogIconColor {
29
+ 'red' = "red",
30
+ 'green' = "green",
31
+ 'blue' = "blue",
32
+ 'yellow' = "yellow"
33
+ }
34
+ export declare enum CatalogColor {
35
+ blue = "blue",
36
+ cyan = "cyan",
37
+ green = "green",
38
+ orange = "orange",
39
+ purple = "purple",
40
+ red = "red",
41
+ grey = "grey"
42
+ }
43
+ export interface ICatalogCard {
44
+ id: string;
45
+ icon?: ReactNode;
46
+ title: string;
47
+ items?: CatalogCardItem[];
48
+ labels?: {
49
+ label: string;
50
+ color?: CatalogColor;
51
+ }[];
52
+ learnMore?: string;
53
+ badge?: string;
54
+ badgeColor?: CatalogColor;
55
+ badgeTooltip?: string;
56
+ badgeTooltipTitle?: string;
57
+ alertTitle?: string;
58
+ alertContent?: ReactNode;
59
+ alertVariant?: 'success' | 'danger' | 'warning' | 'info' | 'default';
60
+ onClick?: () => void;
61
+ }
62
+ export interface ICatalogCardFeatureGroup {
63
+ title: string;
64
+ features: string[];
65
+ }
66
+ export declare enum CatalogCardItemType {
67
+ Description = "description",
68
+ List = "list"
69
+ }
70
+ export interface ICatalogCardDescription {
71
+ type: CatalogCardItemType.Description;
72
+ title?: string;
73
+ description: string;
74
+ }
75
+ export interface ICatalogCardList {
76
+ type: CatalogCardItemType.List;
77
+ title: string;
78
+ items: ICatalogCardListItem[];
79
+ horizontal?: boolean;
80
+ icon?: ReactNode;
81
+ }
82
+ export declare enum CatalogCardListItemIcon {
83
+ Checkmark = "checkmark",
84
+ Plus = "plus",
85
+ CheckCircle = "check-circle",
86
+ ExclamationCircle = "exclamation-circle"
87
+ }
88
+ export interface ICatalogCardListItem {
89
+ icon?: ReactNode;
90
+ text: string;
91
+ helpTitle?: string;
92
+ help?: ReactNode;
93
+ }
94
+ export declare type CatalogCardItem = ICatalogCardDescription | ICatalogCardList;
95
+ export declare function CatalogCard<T extends object>(props: {
96
+ item: T;
97
+ itemToCardFn: (item: T) => ICatalogCard;
98
+ isSelected: (item: T) => boolean;
99
+ selectItem: (item: T) => void;
100
+ unselectItem: (item: T) => void;
101
+ itemActions?: ITypedAction<T>[];
102
+ showSelect: boolean;
103
+ t?: (t: string) => string;
104
+ }): JSX.Element;
105
+ export declare function CardSection(props: {
106
+ title?: string;
107
+ children: ReactNode;
108
+ }): JSX.Element;
109
+ export declare function CardList(props: {
110
+ icon?: ReactNode;
111
+ items: ICatalogCardListItem[];
112
+ }): JSX.Element;
113
+ export {};
@@ -0,0 +1,140 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
3
+ /* eslint-disable @typescript-eslint/no-empty-function */
4
+ import { Alert, Button, Card, CardActions, CardBody, CardFooter, CardHeader, CardTitle, Checkbox, DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, Dropdown, DropdownSeparator, KebabToggle, Label, LabelGroup, List, ListItem, PageSection, Popover, Split, SplitItem, Stack, StackItem, Title, Truncate, } from '@patternfly/react-core';
5
+ import { ExternalLinkAltIcon, OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
6
+ import { Fragment, useCallback, useMemo, useState } from 'react';
7
+ import { Grid } from './components/Grid';
8
+ import { IconWrapper } from './components/IconWrapper';
9
+ import { Scrollable } from './components/Scrollable';
10
+ export function Catalog(props) {
11
+ const { keyFn, items, itemToCardFn, isSelected, selectItem, unselectItem, itemActions, showSelect, } = props;
12
+ const catalogCards = useMemo(() => {
13
+ return (_jsx(Grid, { size: props.cardWidth ?? 470, children: items.map((item) => (_jsx(CatalogCard, { item: item, itemToCardFn: itemToCardFn, isSelected: isSelected, selectItem: selectItem, unselectItem: unselectItem, itemActions: itemActions, showSelect: showSelect }, keyFn(item)))) }));
14
+ }, [
15
+ props.cardWidth,
16
+ items,
17
+ keyFn,
18
+ itemToCardFn,
19
+ isSelected,
20
+ selectItem,
21
+ unselectItem,
22
+ itemActions,
23
+ showSelect,
24
+ ]);
25
+ return (_jsx(PageSection, { style: { flexGrow: 1 }, children: _jsx("div", { children: catalogCards }) }));
26
+ }
27
+ export var CatalogIconColor;
28
+ (function (CatalogIconColor) {
29
+ CatalogIconColor["red"] = "red";
30
+ CatalogIconColor["green"] = "green";
31
+ CatalogIconColor["blue"] = "blue";
32
+ CatalogIconColor["yellow"] = "yellow";
33
+ })(CatalogIconColor || (CatalogIconColor = {}));
34
+ export var CatalogColor;
35
+ (function (CatalogColor) {
36
+ CatalogColor["blue"] = "blue";
37
+ CatalogColor["cyan"] = "cyan";
38
+ CatalogColor["green"] = "green";
39
+ CatalogColor["orange"] = "orange";
40
+ CatalogColor["purple"] = "purple";
41
+ CatalogColor["red"] = "red";
42
+ CatalogColor["grey"] = "grey";
43
+ })(CatalogColor || (CatalogColor = {}));
44
+ export var CatalogCardItemType;
45
+ (function (CatalogCardItemType) {
46
+ CatalogCardItemType["Description"] = "description";
47
+ CatalogCardItemType["List"] = "list";
48
+ })(CatalogCardItemType || (CatalogCardItemType = {}));
49
+ export var CatalogCardListItemIcon;
50
+ (function (CatalogCardListItemIcon) {
51
+ CatalogCardListItemIcon["Checkmark"] = "checkmark";
52
+ CatalogCardListItemIcon["Plus"] = "plus";
53
+ CatalogCardListItemIcon["CheckCircle"] = "check-circle";
54
+ CatalogCardListItemIcon["ExclamationCircle"] = "exclamation-circle";
55
+ })(CatalogCardListItemIcon || (CatalogCardListItemIcon = {}));
56
+ export function CatalogCard(props) {
57
+ let { t } = props;
58
+ t = t ? t : (t) => t;
59
+ const { item, itemToCardFn, isSelected, selectItem, unselectItem, itemActions, showSelect } = props;
60
+ const card = useMemo(() => itemToCardFn(item), [item, itemToCardFn]);
61
+ const [isOpen, setIsOpen] = useState(false);
62
+ const onSelect = useCallback(() => { }, []);
63
+ const onClick = useCallback(() => {
64
+ if (isSelected(item)) {
65
+ unselectItem(item);
66
+ }
67
+ else {
68
+ selectItem(item);
69
+ }
70
+ }, [isSelected, item, selectItem, unselectItem]);
71
+ const showDropdown = itemActions !== undefined && itemActions.length > 0;
72
+ const showActions = showSelect || showDropdown;
73
+ const dropdownItems = useMemo(() => itemActions?.map((itemAction, index) => {
74
+ // if (isItemActionClick(itemAction)) {
75
+ // return (
76
+ // <DropdownItem
77
+ // key={itemAction.label}
78
+ // onClick={() => {
79
+ // itemAction.onClick(item)
80
+ // setIsOpen(false)
81
+ // }}
82
+ // >
83
+ // {itemAction.label}
84
+ // </DropdownItem>
85
+ // )
86
+ // }
87
+ return _jsx(DropdownSeparator, {}, index);
88
+ }), [itemActions]);
89
+ const disabled = !card.onClick;
90
+ return (_jsxs(Card, { id: card.id, onClick: card.onClick, isFlat: true, isLarge: true, isSelectable: !disabled, isRounded: true, style: {
91
+ transition: 'box-shadow 0.25s',
92
+ cursor: !disabled ? 'pointer' : undefined,
93
+ }, children: [_jsxs(CardHeader, { style: { opacity: !disabled ? undefined : '0.5' }, children: [_jsxs(Split, { hasGutter: true, style: { width: '100%' }, children: [_jsx(SplitItem, { isFilled: true, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [card.icon && (_jsx("div", { style: {
94
+ display: 'flex',
95
+ height: 40,
96
+ width: 40,
97
+ marginTop: -20,
98
+ marginBottom: -20,
99
+ marginRight: 12,
100
+ alignItems: 'center',
101
+ justifyItems: 'stretch',
102
+ }, children: _jsx(IconWrapper, { size: "lg", children: card.icon }) })), _jsx(CardTitle, { children: card.title })] }) }), card.badge && card.badgeTooltip && (_jsx(SplitItem, { children: _jsx("div", { onClick: (e) => e.stopPropagation(), children: _jsx(Popover, { headerContent: card.badgeTooltipTitle, bodyContent: card.badgeTooltip, removeFindDomNode: true, children: _jsx(Label, { color: card.badgeColor, children: card.badge }) }) }) })), card.badge && !card.badgeTooltip && (_jsx(SplitItem, { children: _jsx(Label, { color: card.badgeColor, children: card.badge }) }))] }), showActions && (_jsxs(CardActions, { hasNoOffset: true, children: [showDropdown && (_jsx(Dropdown, { onSelect: onSelect, toggle: _jsx(KebabToggle, { onToggle: setIsOpen }), isOpen: isOpen, isPlain: true, dropdownItems: dropdownItems, position: "right" })), showSelect && (_jsx(Checkbox, { isChecked: isSelected(item), onChange: onClick, "aria-label": "card checkbox example", id: "check-1", name: "check1" }))] }))] }), card.items && (_jsx(Scrollable, { children: _jsx(CardBody, { style: { paddingTop: 0, opacity: !disabled ? undefined : '0.5' }, children: _jsx(DescriptionList, { children: card.items &&
103
+ card.items.map((item, index) => {
104
+ switch (item.type) {
105
+ case CatalogCardItemType.Description:
106
+ return (_jsx(DescriptionList, { children: _jsx(DescriptionListGroup, { children: _jsx("span", { style: { opacity: 9 }, children: item.description }) }) }, index));
107
+ case CatalogCardItemType.List:
108
+ return (_jsx(DescriptionList, { orientation: item.horizontal ? { sm: 'horizontal' } : undefined, children: _jsxs(DescriptionListGroup, { children: [_jsx(DescriptionListTerm, { children: item.title }), _jsx(DescriptionListDescription, { children: _jsx(CardList, { icon: item.icon, items: item.items }) })] }) }, index));
109
+ default:
110
+ return _jsx(Fragment, {}, index);
111
+ }
112
+ }) }) }) })), (card.labels || card.learnMore) && (_jsx(CardFooter, { children: _jsxs("div", { style: {
113
+ display: 'flex',
114
+ flexDirection: 'row',
115
+ alignItems: 'end',
116
+ gap: 16,
117
+ }, children: [_jsx("div", { style: { flexGrow: 1, opacity: !disabled ? undefined : '0.5' }, children: card.labels && (_jsx(LabelGroup, { children: card.labels.map((item) => (_jsx(Label, { color: item.color, children: _jsx(Truncate, { content: item.label, style: { minWidth: 0 } }) }, item.label))) })) }), card.learnMore && (_jsxs(Button, { variant: "link", icon: _jsx(ExternalLinkAltIcon, {}), isInline: true, onClick: () => window.open(card.learnMore, '_blank'), children: ["\u00A0", t('Learn more')] }))] }) })), card.alertTitle && (_jsx(Alert, { title: card.alertTitle, isInline: true, variant: card.alertVariant, children: card.alertContent }))] }, card.id ?? card.title));
118
+ }
119
+ export function CardSection(props) {
120
+ return (_jsxs(Stack, { children: [props.title && (_jsx(StackItem, { children: _jsx(Title, { headingLevel: "h6", style: { paddingBottom: 8 }, children: props.title }) })), props.children] }));
121
+ }
122
+ export function CardList(props) {
123
+ const { items, icon } = props;
124
+ return (_jsx(List, { isPlain: true, children: items?.map((listItem, index) => {
125
+ let itemIcon;
126
+ if (listItem.icon) {
127
+ itemIcon = (_jsx(IconWrapper, { size: "md", noPadding: true, children: listItem.icon }));
128
+ }
129
+ else if (icon) {
130
+ itemIcon = (_jsx(IconWrapper, { size: "md", noPadding: true, children: icon }));
131
+ }
132
+ return (_jsxs(ListItem, { icon: itemIcon, style: { opacity: 0.85 }, children: [listItem.text, listItem.help && (
133
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
134
+ _jsx("div", { onClick: (e) => e.stopPropagation(), children: _jsx(Popover, { headerContent: listItem.helpTitle, bodyContent: listItem.help, removeFindDomNode: true, children: _jsx(Button, { variant: "link", style: {
135
+ padding: 0,
136
+ marginLeft: '8px',
137
+ verticalAlign: 'middle',
138
+ }, children: _jsx(OutlinedQuestionCircleIcon, {}) }) }) }))] }, index));
139
+ }) }));
140
+ }