@devtron-labs/devtron-fe-common-lib 0.0.7-beta-51 → 0.0.9-beta-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ import { DeleteComponentProps } from './types';
3
+ declare function DeleteComponent({ setDeleting, toggleConfirmation, deleteComponent, title, component, payload, confirmationDialogDescription, redirectTo, url, reload, configuration, closeCustomComponent, }: DeleteComponentProps): JSX.Element;
4
+ export default DeleteComponent;
@@ -0,0 +1,15 @@
1
+ export interface DeleteComponentProps {
2
+ setDeleting: (boolean: any) => void;
3
+ toggleConfirmation: any;
4
+ deleteComponent: (any: any) => Promise<any>;
5
+ title: string;
6
+ component: string;
7
+ payload: any;
8
+ confirmationDialogDescription?: string;
9
+ redirectTo?: boolean;
10
+ url?: string;
11
+ reload?: () => void;
12
+ configuration?: string;
13
+ dataTestid?: string;
14
+ closeCustomComponent?: () => void;
15
+ }
@@ -17,4 +17,26 @@ export declare function not(e: any): boolean;
17
17
  export declare function useEffectAfterMount(cb: any, dependencies: any): void;
18
18
  export declare function getCookie(sKey: any): string;
19
19
  export declare function getLoginInfo(): any;
20
+ export declare function useForm(stateSchema: any, validationSchema: {}, callback: any): {
21
+ state: any;
22
+ disable: boolean;
23
+ handleOnChange: (event: any) => void;
24
+ handleOnSubmit: (event: any) => void;
25
+ };
26
+ export declare function CustomInput({ name, value, error, onChange, onBlur, onFocus, label, type, disabled, autoComplete, labelClassName, placeholder, tabIndex, dataTestid, }: {
27
+ name: any;
28
+ value: any;
29
+ error: any;
30
+ onChange: any;
31
+ onBlur?: (e: any) => void;
32
+ onFocus?: (e: any) => void;
33
+ label: any;
34
+ type?: string;
35
+ disabled?: boolean;
36
+ autoComplete?: string;
37
+ labelClassName?: string;
38
+ placeholder?: string;
39
+ tabIndex?: number;
40
+ dataTestid?: string;
41
+ }): JSX.Element;
20
42
  export {};
@@ -46,7 +46,7 @@ export interface CheckboxProps {
46
46
  export interface TippyCustomizedProps {
47
47
  theme: TippyTheme;
48
48
  visible?: boolean;
49
- heading?: string;
49
+ heading?: ReactNode | string;
50
50
  headingInfo?: string;
51
51
  infoTextHeading?: string;
52
52
  placement: Placement;
@@ -237,6 +237,8 @@ export interface CommonNodeAttr {
237
237
  userApprovalConfig?: UserApprovalConfigType;
238
238
  requestedUserId?: number;
239
239
  showPluginWarning?: boolean;
240
+ helmPackageName?: string;
241
+ isVirtualEnvironment?: boolean;
240
242
  }
241
243
  export interface VulnerabilityType {
242
244
  name: string;
@@ -30,3 +30,4 @@ export { default as Toggle } from './Toggle/Toggle';
30
30
  export { default as ScanVulnerabilitiesTable } from './Security/ScanVulnerabilitiesTable';
31
31
  export { default as StyledRadioGroup } from './RadioGroup/RadioGroup';
32
32
  export * from './CIPipeline.Types';
33
+ export { default as DeleteComponent } from './DeleteComponentModal/DeleteComponent';
package/dist/index.js CHANGED
@@ -520,15 +520,15 @@ function styleInject(css, ref) {
520
520
  var css_248z$6 = ".empty-state {\n height: 100%;\n}\n.empty-state img {\n height: 40%;\n max-height: 200px;\n width: auto;\n max-width: 250px;\n}\n.empty-state svg {\n height: 40%;\n max-height: 200px;\n width: auto;\n}\n.empty-state h1,\n.empty-state h2,\n.empty-state h3,\n.empty-state h4,\n.empty-state h5,\n.empty-state h6 {\n color: var(--N900);\n}\n.empty-state .subtitle {\n font-size: 13px;\n width: 300px;\n font-weight: 400;\n text-align: center;\n line-height: 1.5;\n margin-bottom: 20px;\n}\n.empty-state .cta {\n height: 36px;\n}\n.empty-state p {\n width: 300px;\n text-align: center;\n font-size: 13px;\n color: var(--N700);\n}\n.empty-state strong {\n font-size: 16px;\n margin-bottom: 4px;\n color: var(--N900);\n font-weight: normal;\n}\n.empty-state .select-popup {\n height: min-content;\n max-height: 250px;\n overflow: auto;\n padding: 8px 0;\n}\n.empty-state .empty-state__loader {\n width: 34px;\n height: 34px;\n margin-bottom: 16px;\n}\n.empty-state .empty-state__loading-text {\n font-size: 12px;\n width: 200px;\n font-weight: normal;\n font-stretch: normal;\n font-style: normal;\n line-height: 1.5;\n letter-spacing: normal;\n text-align: center;\n color: var(--N900);\n}\n.empty-state .button__icon {\n width: 16px;\n height: 16px;\n margin-left: 8px;\n}";
521
521
  styleInject(css_248z$6);
522
522
 
523
- var _g$2;
524
- function _extends$b() { _extends$b = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$b.apply(this, arguments); }
523
+ var _g$3;
524
+ function _extends$c() { _extends$c = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$c.apply(this, arguments); }
525
525
  var SvgIcProgressing = function SvgIcProgressing(props) {
526
- return /*#__PURE__*/React__namespace.createElement("svg", _extends$b({
526
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$c({
527
527
  xmlns: "http://www.w3.org/2000/svg",
528
528
  viewBox: "0 0 24 24",
529
529
  width: "1em",
530
530
  height: "1em"
531
- }, props), _g$2 || (_g$2 = /*#__PURE__*/React__namespace.createElement("g", {
531
+ }, props), _g$3 || (_g$3 = /*#__PURE__*/React__namespace.createElement("g", {
532
532
  fill: "none"
533
533
  }, /*#__PURE__*/React__namespace.createElement("animateTransform", {
534
534
  attributeName: "transform",
@@ -575,8 +575,8 @@ EmptyState.Loading = Loading;
575
575
 
576
576
  function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);else for(t in e)e[t]&&(n&&(n+=" "),n+=t);return n}function clsx(){for(var e,t,f=0,n="";f<arguments.length;)(e=arguments[f++])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
577
577
 
578
- function _extends$a() {
579
- _extends$a = Object.assign || function (target) {
578
+ function _extends$b() {
579
+ _extends$b = Object.assign || function (target) {
580
580
  for (var i = 1; i < arguments.length; i++) {
581
581
  var source = arguments[i];
582
582
 
@@ -590,7 +590,7 @@ function _extends$a() {
590
590
  return target;
591
591
  };
592
592
 
593
- return _extends$a.apply(this, arguments);
593
+ return _extends$b.apply(this, arguments);
594
594
  }
595
595
 
596
596
  function _objectWithoutPropertiesLoose$2(source, excluded) {
@@ -1316,7 +1316,7 @@ function ProgressBar(_ref) {
1316
1316
  isIn = _ref.isIn,
1317
1317
  theme = _ref.theme;
1318
1318
 
1319
- var style = _extends$a({}, userStyle, {
1319
+ var style = _extends$b({}, userStyle, {
1320
1320
  animationDuration: delay + "ms",
1321
1321
  animationPlayState: isRunning ? 'running' : 'paused',
1322
1322
  opacity: hide ? 0 : 1
@@ -1593,9 +1593,9 @@ var ToastContainer = function ToastContainer(props) {
1593
1593
  ,
1594
1594
  id: containerId
1595
1595
  }, getToastToRender(function (position, toastList) {
1596
- var containerStyle = !toastList.length ? _extends$a({}, style, {
1596
+ var containerStyle = !toastList.length ? _extends$b({}, style, {
1597
1597
  pointerEvents: 'none'
1598
- }) : _extends$a({}, style);
1598
+ }) : _extends$b({}, style);
1599
1599
  return React.createElement("div", {
1600
1600
  className: getClassName(position),
1601
1601
  style: containerStyle,
@@ -1702,7 +1702,7 @@ function dispatchToast(content, options) {
1702
1702
 
1703
1703
 
1704
1704
  function mergeOptions(type, options) {
1705
- return _extends$a({}, options, {
1705
+ return _extends$b({}, options, {
1706
1706
  type: options && options.type || type,
1707
1707
  toastId: getToastId(options)
1708
1708
  });
@@ -1719,7 +1719,7 @@ function toast(content, options) {
1719
1719
  }
1720
1720
 
1721
1721
  toast.loading = function (content, options) {
1722
- return dispatchToast(content, mergeOptions(TYPE.DEFAULT, _extends$a({
1722
+ return dispatchToast(content, mergeOptions(TYPE.DEFAULT, _extends$b({
1723
1723
  isLoading: true,
1724
1724
  autoClose: false,
1725
1725
  closeOnClick: false,
@@ -1735,7 +1735,7 @@ function handlePromise(promise, _ref2, options) {
1735
1735
  var id;
1736
1736
 
1737
1737
  if (pending) {
1738
- id = isStr(pending) ? toast.loading(pending, options) : toast.loading(pending.render, _extends$a({}, options, pending));
1738
+ id = isStr(pending) ? toast.loading(pending, options) : toast.loading(pending.render, _extends$b({}, options, pending));
1739
1739
  }
1740
1740
 
1741
1741
  var resetParams = {
@@ -1754,7 +1754,7 @@ function handlePromise(promise, _ref2, options) {
1754
1754
  return;
1755
1755
  }
1756
1756
 
1757
- var baseParams = _extends$a({
1757
+ var baseParams = _extends$b({
1758
1758
  type: type
1759
1759
  }, resetParams, options, {
1760
1760
  data: result
@@ -1765,10 +1765,10 @@ function handlePromise(promise, _ref2, options) {
1765
1765
  } : input; // if the id is set we know that it's an update
1766
1766
 
1767
1767
  if (id) {
1768
- toast.update(id, _extends$a({}, baseParams, params));
1768
+ toast.update(id, _extends$b({}, baseParams, params));
1769
1769
  } else {
1770
1770
  // using toast.promise without loading
1771
- toast(params.render, _extends$a({}, baseParams, params));
1771
+ toast(params.render, _extends$b({}, baseParams, params));
1772
1772
  }
1773
1773
 
1774
1774
  return result;
@@ -1792,7 +1792,7 @@ toast.warning = /*#__PURE__*/createToastByType(TYPE.WARNING);
1792
1792
  toast.warn = toast.warning;
1793
1793
 
1794
1794
  toast.dark = function (content, options) {
1795
- return dispatchToast(content, mergeOptions(TYPE.DEFAULT, _extends$a({
1795
+ return dispatchToast(content, mergeOptions(TYPE.DEFAULT, _extends$b({
1796
1796
  theme: 'dark'
1797
1797
  }, options)));
1798
1798
  };
@@ -1849,7 +1849,7 @@ toast.update = function (toastId, options) {
1849
1849
  var oldOptions = toast.props,
1850
1850
  oldContent = toast.content;
1851
1851
 
1852
- var nextOptions = _extends$a({}, oldOptions, options, {
1852
+ var nextOptions = _extends$b({}, oldOptions, options, {
1853
1853
  toastId: options.toastId || toastId,
1854
1854
  updateId: generateToastId()
1855
1855
  });
@@ -2002,7 +2002,7 @@ var AppNotDeployed = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAGQCAYA
2002
2002
 
2003
2003
  function GenericEmptyState(_a) {
2004
2004
  var title = _a.title, image = _a.image, subTitle = _a.subTitle, isButtonAvailable = _a.isButtonAvailable, classname = _a.classname, styles = _a.styles, heightToDeduct = _a.heightToDeduct, imageType = _a.imageType, renderButton = _a.renderButton, imageClassName = _a.imageClassName, children = _a.children, noImage = _a.noImage;
2005
- return (jsxRuntime.jsxs("div", __assign({ className: "flex column empty-state dc__align-reload-center ".concat(classname ? classname : ''), style: styles, "data-testid": "generic-empty-state" }, (heightToDeduct >= 0 && { style: __assign(__assign({}, styles), { height: "calc(100vh - ".concat(heightToDeduct, "px)") }) }), { children: [!noImage && jsxRuntime.jsx("img", { className: imageClassName ? imageClassName : '', src: image || AppNotDeployed, width: imageType === exports.ImageType.Medium ? '200' : '250', height: imageType === exports.ImageType.Medium ? '160' : '200', alt: "empty-state" }), jsxRuntime.jsx("h4", __assign({ className: "title fw-6 cn-9 mb-8" }, { children: title })), subTitle && jsxRuntime.jsx("p", __assign({ className: "subtitle" }, { children: subTitle })), isButtonAvailable && renderButton(), children] })));
2005
+ return (jsxRuntime.jsxs("div", __assign({ className: "flex column empty-state dc__align-reload-center ".concat(classname ? classname : ''), style: styles, "data-testid": "generic-empty-state" }, (heightToDeduct >= 0 && { style: __assign(__assign({}, styles), { height: "calc(100vh - ".concat(heightToDeduct, "px)") }) }), { children: [!noImage && jsxRuntime.jsx("img", { className: imageClassName ? imageClassName : '', src: image || AppNotDeployed, width: imageType === exports.ImageType.Medium ? '200' : '250', height: imageType === exports.ImageType.Medium ? '160' : '200', alt: "empty-state" }), jsxRuntime.jsx("h4", __assign({ className: "title fw-6 cn-9 mb-8 mt-20" }, { children: title })), subTitle && jsxRuntime.jsx("p", __assign({ className: "subtitle" }, { children: subTitle })), isButtonAvailable && renderButton(), children] })));
2006
2006
  }
2007
2007
 
2008
2008
  function ErrorScreenNotFound() {
@@ -3944,6 +3944,28 @@ function captureException(exception, captureContext) {
3944
3944
  return getCurrentHub().captureException(exception, { captureContext });
3945
3945
  }
3946
3946
 
3947
+ var _g$2;
3948
+ function _extends$a() { _extends$a = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$a.apply(this, arguments); }
3949
+ var SvgIcWarning = function SvgIcWarning(props) {
3950
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$a({
3951
+ xmlns: "http://www.w3.org/2000/svg",
3952
+ width: "1em",
3953
+ height: "1em",
3954
+ viewBox: "0 0 32 32"
3955
+ }, props), _g$2 || (_g$2 = /*#__PURE__*/React__namespace.createElement("g", {
3956
+ fill: "none",
3957
+ fillRule: "evenodd"
3958
+ }, /*#__PURE__*/React__namespace.createElement("path", {
3959
+ d: "M0 0h32v32H0z"
3960
+ }), /*#__PURE__*/React__namespace.createElement("path", {
3961
+ fill: "#FFCB5D",
3962
+ d: "M18.315 5.052 29.72 25.01A2.667 2.667 0 0 1 27.405 29H4.595a2.667 2.667 0 0 1-2.315-3.99L13.685 5.052a2.667 2.667 0 0 1 4.63 0z"
3963
+ }), /*#__PURE__*/React__namespace.createElement("path", {
3964
+ fill: "#FFF",
3965
+ d: "M16 22.667a1.333 1.333 0 1 1 0 2.666 1.333 1.333 0 0 1 0-2.666zM16 12c.736 0 1.333.597 1.333 1.333v6.334a1.333 1.333 0 1 1-2.666 0v-6.334c0-.736.597-1.333 1.333-1.333z"
3966
+ }))));
3967
+ };
3968
+
3947
3969
  toast.configure({
3948
3970
  autoClose: 3000,
3949
3971
  hideProgressBar: true,
@@ -4082,6 +4104,110 @@ function getLoginInfo() {
4082
4104
  return null;
4083
4105
  }
4084
4106
  }
4107
+ }
4108
+ function useForm(stateSchema, validationSchema, callback) {
4109
+ if (validationSchema === void 0) { validationSchema = {}; }
4110
+ var _a = __read(React.useState(stateSchema), 2), state = _a[0], setState = _a[1];
4111
+ var _b = __read(React.useState(true), 2), disable = _b[0], setDisable = _b[1];
4112
+ var _c = __read(React.useState(false), 2), isDirty = _c[0], setIsDirty = _c[1];
4113
+ // Disable button in initial render.
4114
+ React.useEffect(function () {
4115
+ setDisable(true);
4116
+ }, []);
4117
+ // For every changed in our state this will be fired
4118
+ // To be able to disable the button
4119
+ React.useEffect(function () {
4120
+ if (isDirty) {
4121
+ setDisable(validateState(state));
4122
+ }
4123
+ }, [state, isDirty]);
4124
+ // Used to disable submit button if there's an error in state
4125
+ // or the required field in state has no value.
4126
+ // Wrapped in useCallback to cached the function to avoid intensive memory leaked
4127
+ // in every re-render in component
4128
+ var validateState = React.useCallback(function (state) {
4129
+ //check errors in all fields
4130
+ var hasErrorInState = Object.keys(validationSchema).some(function (key) {
4131
+ var isInputFieldRequired = validationSchema[key].required;
4132
+ var stateValue = state[key].value; // state value
4133
+ var stateError = state[key].error; // state error
4134
+ return (isInputFieldRequired && !stateValue) || stateError;
4135
+ });
4136
+ return hasErrorInState;
4137
+ }, [state, validationSchema]);
4138
+ function validateField(name, value) {
4139
+ if (validationSchema[name].required) {
4140
+ if (!value) {
4141
+ return 'This is a required field.';
4142
+ }
4143
+ }
4144
+ function _validateSingleValidator(validator, value) {
4145
+ if (value && !validator.regex.test(value)) {
4146
+ return false;
4147
+ }
4148
+ return true;
4149
+ }
4150
+ // single validator
4151
+ var _validator = validationSchema[name].validator;
4152
+ if (_validator && typeof _validator === 'object') {
4153
+ if (!_validateSingleValidator(_validator, value)) {
4154
+ return _validator.error;
4155
+ }
4156
+ }
4157
+ // multiple validators
4158
+ var _validators = validationSchema[name].validators;
4159
+ if (_validators && typeof _validators === 'object' && Array.isArray(_validators)) {
4160
+ var errors_1 = [];
4161
+ _validators.forEach(function (_validator) {
4162
+ if (!_validateSingleValidator(_validator, value)) {
4163
+ errors_1.push(_validator.error);
4164
+ }
4165
+ });
4166
+ if (errors_1.length > 0) {
4167
+ return errors_1;
4168
+ }
4169
+ }
4170
+ return '';
4171
+ }
4172
+ var handleOnChange = React.useCallback(function (event) {
4173
+ setIsDirty(true);
4174
+ var _a = event.target, name = _a.name, value = _a.value;
4175
+ var error = validateField(name, value);
4176
+ setState(function (prevState) {
4177
+ var _a;
4178
+ return (__assign(__assign({}, prevState), (_a = {}, _a[name] = { value: value, error: error }, _a)));
4179
+ });
4180
+ }, [validationSchema]);
4181
+ var handleOnSubmit = function (event) {
4182
+ event.preventDefault();
4183
+ var newState = Object.keys(validationSchema).reduce(function (agg, curr) {
4184
+ agg[curr] = __assign(__assign({}, state[curr]), { error: validateField(curr, state[curr].value) });
4185
+ return agg;
4186
+ }, state);
4187
+ if (!validateState(newState)) {
4188
+ callback(state);
4189
+ }
4190
+ else {
4191
+ setState(__assign({}, newState));
4192
+ }
4193
+ };
4194
+ return { state: state, disable: disable, handleOnChange: handleOnChange, handleOnSubmit: handleOnSubmit };
4195
+ }
4196
+ function handleError(error) {
4197
+ if (!error) {
4198
+ return [];
4199
+ }
4200
+ if (!Array.isArray(error)) {
4201
+ return [error];
4202
+ }
4203
+ return error;
4204
+ }
4205
+ function CustomInput(_a) {
4206
+ var name = _a.name, value = _a.value, error = _a.error, onChange = _a.onChange, _b = _a.onBlur, onBlur = _b === void 0 ? function (e) { } : _b, _c = _a.onFocus, onFocus = _c === void 0 ? function (e) { } : _c, label = _a.label, _d = _a.type, type = _d === void 0 ? 'text' : _d, _e = _a.disabled, disabled = _e === void 0 ? false : _e; _a.autoComplete; var _g = _a.labelClassName, labelClassName = _g === void 0 ? '' : _g, _h = _a.placeholder, placeholder = _h === void 0 ? '' : _h, _j = _a.tabIndex, tabIndex = _j === void 0 ? 1 : _j, _k = _a.dataTestid, dataTestid = _k === void 0 ? '' : _k;
4207
+ return (jsxRuntime.jsxs("div", __assign({ className: "flex column left top" }, { children: [jsxRuntime.jsx("label", __assign({ className: "form__label ".concat(labelClassName) }, { children: label })), jsxRuntime.jsx("input", { "data-testid": dataTestid, type: type, name: name, autoComplete: "off", className: "form__input", onChange: function (e) {
4208
+ e.persist();
4209
+ onChange(e);
4210
+ }, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder, value: value, disabled: disabled, tabIndex: tabIndex }), handleError(error).map(function (err) { return (jsxRuntime.jsxs("div", __assign({ className: "form__error" }, { children: [jsxRuntime.jsx(SvgIcWarning, { className: "form__icon form__icon--error" }), err] }))); })] })));
4085
4211
  }
4086
4212
 
4087
4213
  function Progressing(_a) {
@@ -8566,7 +8692,7 @@ function TippyCustomized(props) {
8566
8692
  };
8567
8693
  var getTippyContent = function () {
8568
8694
  var Icon = props.Icon, iconPath = props.iconPath, iconClass = props.iconClass, iconSize = props.iconSize, onImageLoadError = props.onImageLoadError, heading = props.heading, headingInfo = props.headingInfo, infoTextHeading = props.infoTextHeading, infoText = props.infoText, showCloseButton = props.showCloseButton, additionalContent = props.additionalContent, documentationLink = props.documentationLink, documentationLinkText = props.documentationLinkText;
8569
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", __assign({ className: "dc__word-break dc__hyphens-auto flex left ".concat(isWhiteTheme ? 'p-12 dc__border-bottom-n1 cn-9' : 'pt-20 pb-12 pr-20 pl-20 cn-0 top') }, { children: [iconPath ? (jsxRuntime.jsx("img", { className: "icon-dim-".concat(iconSize || 20, " mr-6 ").concat(iconClass || ''), src: iconPath, alt: heading, onError: onImageLoadError })) : (Icon && (jsxRuntime.jsx("div", __assign({ className: "icon-dim-".concat(iconSize || 20, " mr-6") }, { children: jsxRuntime.jsx(Icon, { className: "icon-dim-".concat(iconSize || 20, " ").concat(iconClass || '') }) })))), heading && jsxRuntime.jsx("span", __assign({ className: "fs-14 fw-6 lh-20 ".concat(showCloseButton ? 'mr-6' : '') }, { children: heading })), headingInfo && (jsxRuntime.jsx("div", __assign({ className: "icon-dim-20 cursor", onClick: toggleHeadingInfo }, { children: jsxRuntime.jsx(SvgIcHelp, { className: "icon-dim-20" }) }))), showCloseButton && (jsxRuntime.jsx("div", __assign({ className: "icon-dim-16 ml-auto" }, { children: jsxRuntime.jsx(SvgIcCross, { className: "icon-dim-16 cursor ".concat(isWhiteTheme ? 'fcn-9' : 'fcn-0'), onClick: closeTippy }) })))] })), showHeadingInfo && (jsxRuntime.jsxs("div", __assign({ className: "flex left bcv-1 fs-13 fw-4 lh-20 pt-8 pb-8 ".concat(isWhiteTheme ? 'pl-12 pr-12' : 'pl-20 pr-20') }, { children: [jsxRuntime.jsx("div", __assign({ className: "icon-dim-20 mr-8" }, { children: jsxRuntime.jsx(SvgIcHelp, { className: "icon-dim-20 fcv-5" }) })), jsxRuntime.jsx("div", __assign({ className: "dc__word-break dc__hyphens-auto" }, { children: headingInfo }))] }))), infoTextHeading && (jsxRuntime.jsx("div", __assign({ className: "dc__word-break dc__hyphens-auto fs-14 fw-6 lh-20 ".concat(isWhiteTheme ? 'pl-12 pr-12' : 'pl-20 pr-20') }, { children: infoTextHeading }))), infoText && (jsxRuntime.jsx("div", __assign({ className: "dc__word-break dc__hyphens-auto fs-13 fw-4 lh-20 ".concat(isWhiteTheme
8695
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", __assign({ className: "dc__word-break dc__hyphens-auto flex left ".concat(isWhiteTheme ? 'p-12 dc__border-bottom-n1 cn-9' : 'pt-20 pb-12 pr-20 pl-20 cn-0 top') }, { children: [iconPath ? (jsxRuntime.jsx("img", { className: "icon-dim-".concat(iconSize || 20, " mr-6 ").concat(iconClass || ''), src: iconPath, alt: "Heading", onError: onImageLoadError })) : (Icon && (jsxRuntime.jsx("div", __assign({ className: "icon-dim-".concat(iconSize || 20, " mr-6") }, { children: jsxRuntime.jsx(Icon, { className: "icon-dim-".concat(iconSize || 20, " ").concat(iconClass || '') }) })))), heading && jsxRuntime.jsx("span", __assign({ className: "fs-14 fw-6 lh-20 ".concat(showCloseButton ? 'mr-6' : '') }, { children: heading })), headingInfo && (jsxRuntime.jsx("div", __assign({ className: "icon-dim-20 cursor", onClick: toggleHeadingInfo }, { children: jsxRuntime.jsx(SvgIcHelp, { className: "icon-dim-20" }) }))), showCloseButton && (jsxRuntime.jsx("div", __assign({ className: "icon-dim-16 ml-auto" }, { children: jsxRuntime.jsx(SvgIcCross, { className: "icon-dim-16 cursor ".concat(isWhiteTheme ? 'fcn-9' : 'fcn-0'), onClick: closeTippy }) })))] })), showHeadingInfo && (jsxRuntime.jsxs("div", __assign({ className: "flex left bcv-1 fs-13 fw-4 lh-20 pt-8 pb-8 ".concat(isWhiteTheme ? 'pl-12 pr-12' : 'pl-20 pr-20') }, { children: [jsxRuntime.jsx("div", __assign({ className: "icon-dim-20 mr-8" }, { children: jsxRuntime.jsx(SvgIcHelp, { className: "icon-dim-20 fcv-5" }) })), jsxRuntime.jsx("div", __assign({ className: "dc__word-break dc__hyphens-auto" }, { children: headingInfo }))] }))), infoTextHeading && (jsxRuntime.jsx("div", __assign({ className: "dc__word-break dc__hyphens-auto fs-14 fw-6 lh-20 ".concat(isWhiteTheme ? 'pl-12 pr-12' : 'pl-20 pr-20') }, { children: infoTextHeading }))), infoText && (jsxRuntime.jsx("div", __assign({ className: "dc__word-break dc__hyphens-auto fs-13 fw-4 lh-20 ".concat(isWhiteTheme
8570
8696
  ? 'p-12'
8571
8697
  : "pl-20 pr-20 pt-4 ".concat(additionalContent && documentationLink ? 'pb-12' : 'pb-20')) }, { children: infoText }))), additionalContent, documentationLink && (jsxRuntime.jsx("div", __assign({ className: "pl-12 pb-12" }, { children: jsxRuntime.jsx("a", __assign({ href: documentationLink, target: "_blank", rel: "noreferrer noopener", className: "fs-13 cb-5", onClick: closeTippy }, { children: documentationLinkText || 'Learn more' })) })))] }));
8572
8698
  };
@@ -16664,6 +16790,67 @@ exports.CIBuildType = void 0;
16664
16790
  CIBuildType["BUILDPACK_BUILD_TYPE"] = "buildpack-build";
16665
16791
  })(exports.CIBuildType || (exports.CIBuildType = {}));
16666
16792
 
16793
+ var info = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2032%2032%22%3E%20%20%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M0%200h32v32H0z%22%2F%3E%20%20%20%20%20%20%20%20%3Cpath%20fill%3D%22%2306C%22%20d%3D%22M16%202.667C8.64%202.667%202.667%208.64%202.667%2016S8.64%2029.333%2016%2029.333%2029.333%2023.36%2029.333%2016%2023.36%202.667%2016%202.667z%22%2F%3E%20%20%20%20%20%20%20%20%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M16%2014.667c.736%200%201.333.597%201.333%201.333v5.333a1.333%201.333%200%201%201-2.666%200V16c0-.736.597-1.333%201.333-1.333zm0-5.334A1.333%201.333%200%201%201%2016%2012a1.333%201.333%200%200%201%200-2.667z%22%2F%3E%20%20%20%20%3C%2Fg%3E%3C%2Fsvg%3E";
16794
+
16795
+ function DeleteComponent(_a) {
16796
+ var setDeleting = _a.setDeleting, toggleConfirmation = _a.toggleConfirmation, deleteComponent = _a.deleteComponent, title = _a.title, component = _a.component, payload = _a.payload, _b = _a.confirmationDialogDescription, confirmationDialogDescription = _b === void 0 ? '' : _b, _c = _a.redirectTo, redirectTo = _c === void 0 ? false : _c, _d = _a.url, url = _d === void 0 ? '' : _d, reload = _a.reload, _e = _a.configuration, configuration = _e === void 0 ? '' : _e, closeCustomComponent = _a.closeCustomComponent;
16797
+ var _f = __read(React.useState(false), 2), showCannotDeleteDialogModal = _f[0], setCannotDeleteDialogModal = _f[1];
16798
+ var push = reactRouterDom.useHistory().push;
16799
+ function handleDelete() {
16800
+ return __awaiter(this, void 0, void 0, function () {
16801
+ var serverError_1;
16802
+ return __generator(this, function (_a) {
16803
+ switch (_a.label) {
16804
+ case 0:
16805
+ setDeleting(true);
16806
+ _a.label = 1;
16807
+ case 1:
16808
+ _a.trys.push([1, 3, 4, 5]);
16809
+ return [4 /*yield*/, deleteComponent(payload)];
16810
+ case 2:
16811
+ _a.sent();
16812
+ toast.success('Successfully deleted');
16813
+ toggleConfirmation(false);
16814
+ if (redirectTo) {
16815
+ push(url);
16816
+ }
16817
+ else {
16818
+ reload();
16819
+ }
16820
+ if (typeof closeCustomComponent === 'function') {
16821
+ closeCustomComponent();
16822
+ }
16823
+ return [3 /*break*/, 5];
16824
+ case 3:
16825
+ serverError_1 = _a.sent();
16826
+ if (serverError_1 instanceof ServerErrors && serverError_1.code === 500) {
16827
+ setCannotDeleteDialogModal(true);
16828
+ }
16829
+ return [3 /*break*/, 5];
16830
+ case 4:
16831
+ setDeleting(false);
16832
+ return [7 /*endfinally*/];
16833
+ case 5: return [2 /*return*/];
16834
+ }
16835
+ });
16836
+ });
16837
+ }
16838
+ var handleConfirmation = function () {
16839
+ setCannotDeleteDialogModal(false);
16840
+ toggleConfirmation(false);
16841
+ if (typeof closeCustomComponent === 'function') {
16842
+ closeCustomComponent();
16843
+ }
16844
+ };
16845
+ var renderCannotDeleteDialogModal = function () {
16846
+ return (jsxRuntime.jsxs(ConfirmationDialog, __assign({ className: "confirmation-dialog__body--w-360" }, { children: [jsxRuntime.jsx(ConfirmationDialog.Icon, { src: info }), jsxRuntime.jsx(ConfirmationDialog.Body, { title: "Cannot delete ".concat(component, " '").concat(title, "'") }), jsxRuntime.jsx("p", __assign({ className: "fs-13 cn-7 " }, { children: confirmationDialogDescription })), jsxRuntime.jsx(ConfirmationDialog.ButtonGroup, { children: jsxRuntime.jsx("button", __assign({ type: "button", className: "cta", onClick: handleConfirmation }, { children: "Okay" })) })] })));
16847
+ };
16848
+ var renderDeleteDialog = function () {
16849
+ return (jsxRuntime.jsx(DeleteDialog, __assign({ title: "Delete ".concat(component, " '").concat(title, "'"), delete: handleDelete, closeDelete: function () { return toggleConfirmation(false); }, dataTestId: "delete-dialog" }, { children: jsxRuntime.jsx(DeleteDialog.Description, { children: jsxRuntime.jsxs("p", { children: ["Are you sure you want to delete this ", configuration ? configuration : component, "? "] }) }) })));
16850
+ };
16851
+ return (jsxRuntime.jsxs("div", { children: [!showCannotDeleteDialogModal && renderDeleteDialog(), showCannotDeleteDialogModal && renderCannotDeleteDialogModal()] }));
16852
+ }
16853
+
16667
16854
  exports.BreadCrumb = BreadCrumb;
16668
16855
  exports.BreadcrumbStore = Store;
16669
16856
  exports.BuildStageVariable = BuildStageVariable;
@@ -16672,10 +16859,12 @@ exports.Checkbox = Checkbox;
16672
16859
  exports.ClearIndicator = ClearIndicator;
16673
16860
  exports.ConditionalWrap = ConditionalWrap;
16674
16861
  exports.ConfirmationDialog = ConfirmationDialog;
16862
+ exports.CustomInput = CustomInput;
16675
16863
  exports.CustomSelect = CustomSelect;
16676
16864
  exports.DEFAULT_TAG_DATA = DEFAULT_TAG_DATA;
16677
16865
  exports.DOCUMENTATION = DOCUMENTATION;
16678
16866
  exports.DOCUMENTATION_HOME_PAGE = DOCUMENTATION_HOME_PAGE;
16867
+ exports.DeleteComponent = DeleteComponent;
16679
16868
  exports.DeleteDialog = DeleteDialog;
16680
16869
  exports.DetailsProgressing = DetailsProgressing;
16681
16870
  exports.DialogForm = DialogForm;
@@ -16743,4 +16932,5 @@ exports.toastAccessDenied = toastAccessDenied;
16743
16932
  exports.trash = trash;
16744
16933
  exports.useBreadcrumb = useBreadcrumb;
16745
16934
  exports.useEffectAfterMount = useEffectAfterMount;
16935
+ exports.useForm = useForm;
16746
16936
  exports.useThrottledEffect = useThrottledEffect;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devtron-labs/devtron-fe-common-lib",
3
- "version": "0.0.7-beta-51",
3
+ "version": "0.0.9-beta-1",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -0,0 +1,7 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 32 32">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <path d="M0 0h32v32H0z"/>
4
+ <path fill="#06C" d="M16 2.667C8.64 2.667 2.667 8.64 2.667 16S8.64 29.333 16 29.333 29.333 23.36 29.333 16 23.36 2.667 16 2.667z"/>
5
+ <path fill="#FFF" d="M16 14.667c.736 0 1.333.597 1.333 1.333v5.333a1.333 1.333 0 1 1-2.666 0V16c0-.736.597-1.333 1.333-1.333zm0-5.334A1.333 1.333 0 1 1 16 12a1.333 1.333 0 0 1 0-2.667z"/>
6
+ </g>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <path d="M0 0h32v32H0z"/>
4
+ <path fill="#FFCB5D" d="M18.315 5.052L29.72 25.01A2.667 2.667 0 0 1 27.405 29H4.595a2.667 2.667 0 0 1-2.315-3.99L13.685 5.052a2.667 2.667 0 0 1 4.63 0z"/>
5
+ <path fill="#FFF" d="M16 22.667a1.333 1.333 0 1 1 0 2.666 1.333 1.333 0 0 1 0-2.666zM16 12c.736 0 1.333.597 1.333 1.333v6.334a1.333 1.333 0 1 1-2.666 0v-6.334c0-.736.597-1.333 1.333-1.333z"/>
6
+ </g>
7
+ </svg>
@@ -0,0 +1,95 @@
1
+ import React, { useState } from 'react'
2
+ import { useHistory } from 'react-router-dom'
3
+ import { toast } from 'react-toastify'
4
+ import info from '../../Assets/Icon/ic-info-filled.svg'
5
+ import { ConfirmationDialog, DeleteDialog } from '../Dialogs'
6
+ import { ServerErrors } from '../ServerError'
7
+ import { DeleteComponentProps } from './types'
8
+
9
+
10
+ function DeleteComponent({
11
+ setDeleting,
12
+ toggleConfirmation,
13
+ deleteComponent,
14
+ title,
15
+ component,
16
+ payload,
17
+ confirmationDialogDescription = '',
18
+ redirectTo = false,
19
+ url = '',
20
+ reload,
21
+ configuration = '',
22
+ closeCustomComponent,
23
+ }: DeleteComponentProps) {
24
+ const [showCannotDeleteDialogModal, setCannotDeleteDialogModal] = useState(false)
25
+ const { push } = useHistory()
26
+
27
+ async function handleDelete() {
28
+ setDeleting(true)
29
+ try {
30
+ await deleteComponent(payload)
31
+ toast.success('Successfully deleted')
32
+ toggleConfirmation(false)
33
+ if (redirectTo) {
34
+ push(url)
35
+ } else {
36
+ reload()
37
+ }
38
+ if (typeof closeCustomComponent === 'function') {
39
+ closeCustomComponent()
40
+ }
41
+ } catch (serverError) {
42
+ if (serverError instanceof ServerErrors && serverError.code === 500) {
43
+ setCannotDeleteDialogModal(true)
44
+ }
45
+ } finally {
46
+ setDeleting(false)
47
+ }
48
+ }
49
+
50
+ const handleConfirmation = () => {
51
+ setCannotDeleteDialogModal(false)
52
+ toggleConfirmation(false)
53
+ if (typeof closeCustomComponent === 'function') {
54
+ closeCustomComponent()
55
+ }
56
+ }
57
+
58
+ const renderCannotDeleteDialogModal = () => {
59
+ return (
60
+ <ConfirmationDialog className="confirmation-dialog__body--w-360">
61
+ <ConfirmationDialog.Icon src={info} />
62
+ <ConfirmationDialog.Body title={`Cannot delete ${component} '${title}'`} />
63
+ <p className="fs-13 cn-7 ">{confirmationDialogDescription}</p>
64
+ <ConfirmationDialog.ButtonGroup>
65
+ <button type="button" className="cta" onClick={handleConfirmation}>
66
+ Okay
67
+ </button>
68
+ </ConfirmationDialog.ButtonGroup>
69
+ </ConfirmationDialog>
70
+ )
71
+ }
72
+
73
+ const renderDeleteDialog = () => {
74
+ return (
75
+ <DeleteDialog
76
+ title={`Delete ${component} '${title}'`}
77
+ delete={handleDelete}
78
+ closeDelete={() => toggleConfirmation(false)}
79
+ dataTestId="delete-dialog"
80
+ >
81
+ <DeleteDialog.Description>
82
+ <p>Are you sure you want to delete this {configuration ? configuration : component}? </p>
83
+ </DeleteDialog.Description>
84
+ </DeleteDialog>
85
+ )
86
+ }
87
+ return (
88
+ <div>
89
+ {!showCannotDeleteDialogModal && renderDeleteDialog()}
90
+ {showCannotDeleteDialogModal && renderCannotDeleteDialogModal()}
91
+ </div>
92
+ )
93
+ }
94
+
95
+ export default DeleteComponent
@@ -0,0 +1,15 @@
1
+ export interface DeleteComponentProps {
2
+ setDeleting: (boolean) => void
3
+ toggleConfirmation: any
4
+ deleteComponent: (any) => Promise<any>
5
+ title: string
6
+ component: string
7
+ payload: any
8
+ confirmationDialogDescription?: string
9
+ redirectTo?: boolean
10
+ url?: string
11
+ reload?: () => void
12
+ configuration?: string
13
+ dataTestid?: string
14
+ closeCustomComponent?: () => void
15
+ }
@@ -30,7 +30,7 @@ function GenericEmptyState({
30
30
  height={imageType === ImageType.Medium ? '160' : '200'}
31
31
  alt="empty-state"
32
32
  />}
33
- <h4 className="title fw-6 cn-9 mb-8">{title}</h4>
33
+ <h4 className="title fw-6 cn-9 mb-8 mt-20">{title}</h4>
34
34
  {subTitle && <p className="subtitle">{subTitle}</p>}
35
35
  {isButtonAvailable && renderButton()}
36
36
  {children}
@@ -1,48 +1,49 @@
1
- import React, { useEffect, useRef } from 'react'
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react'
2
2
  import { ServerErrors } from './ServerError'
3
3
  import { toast } from 'react-toastify'
4
4
  import * as Sentry from '@sentry/browser'
5
5
  import { toastAccessDenied } from './ToastBody'
6
6
  import { ERROR_EMPTY_SCREEN, TOKEN_COOKIE_NAME } from './Constants'
7
+ import { ReactComponent as FormError } from '../Assets/Icon/ic-warning.svg'
7
8
 
8
9
  toast.configure({
9
- autoClose: 3000,
10
- hideProgressBar: true,
11
- pauseOnHover: true,
12
- pauseOnFocusLoss: true,
13
- closeOnClick: false,
14
- newestOnTop: true,
15
- toastClassName: 'devtron-toast',
16
- bodyClassName: 'devtron-toast__body',
10
+ autoClose: 3000,
11
+ hideProgressBar: true,
12
+ pauseOnHover: true,
13
+ pauseOnFocusLoss: true,
14
+ closeOnClick: false,
15
+ newestOnTop: true,
16
+ toastClassName: 'devtron-toast',
17
+ bodyClassName: 'devtron-toast__body',
17
18
  })
18
19
 
19
20
  export function showError(serverError, showToastOnUnknownError = true, hideAccessError = false) {
20
- if (serverError instanceof ServerErrors && Array.isArray(serverError.errors)) {
21
- serverError.errors.map(({ userMessage, internalMessage }) => {
22
- if (
23
- serverError.code === 403 &&
24
- (userMessage === ERROR_EMPTY_SCREEN.UNAUTHORIZED || userMessage === ERROR_EMPTY_SCREEN.FORBIDDEN)
25
- ) {
26
- if (!hideAccessError) {
27
- toastAccessDenied()
28
- }
29
- } else {
30
- toast.error(userMessage || internalMessage)
31
- }
32
- })
33
- } else {
34
- if (serverError.code !== 403 && serverError.code !== 408) {
35
- Sentry.captureException(serverError)
36
- }
37
-
38
- if (showToastOnUnknownError) {
39
- if (serverError.message) {
40
- toast.error(serverError.message)
41
- } else {
42
- toast.error('Some Error Occurred')
43
- }
44
- }
45
- }
21
+ if (serverError instanceof ServerErrors && Array.isArray(serverError.errors)) {
22
+ serverError.errors.map(({ userMessage, internalMessage }) => {
23
+ if (
24
+ serverError.code === 403 &&
25
+ (userMessage === ERROR_EMPTY_SCREEN.UNAUTHORIZED || userMessage === ERROR_EMPTY_SCREEN.FORBIDDEN)
26
+ ) {
27
+ if (!hideAccessError) {
28
+ toastAccessDenied()
29
+ }
30
+ } else {
31
+ toast.error(userMessage || internalMessage)
32
+ }
33
+ })
34
+ } else {
35
+ if (serverError.code !== 403 && serverError.code !== 408) {
36
+ Sentry.captureException(serverError)
37
+ }
38
+
39
+ if (showToastOnUnknownError) {
40
+ if (serverError.message) {
41
+ toast.error(serverError.message)
42
+ } else {
43
+ toast.error('Some Error Occurred')
44
+ }
45
+ }
46
+ }
46
47
  }
47
48
 
48
49
  interface ConditionalWrapper<T> {
@@ -167,4 +168,166 @@ export function getLoginInfo() {
167
168
  return null
168
169
  }
169
170
  }
170
- }
171
+ }
172
+
173
+ export function useForm(stateSchema, validationSchema = {}, callback) {
174
+ const [state, setState] = useState(stateSchema)
175
+ const [disable, setDisable] = useState(true)
176
+ const [isDirty, setIsDirty] = useState(false)
177
+
178
+ // Disable button in initial render.
179
+ useEffect(() => {
180
+ setDisable(true)
181
+ }, [])
182
+
183
+ // For every changed in our state this will be fired
184
+ // To be able to disable the button
185
+ useEffect(() => {
186
+ if (isDirty) {
187
+ setDisable(validateState(state))
188
+ }
189
+ }, [state, isDirty])
190
+
191
+ // Used to disable submit button if there's an error in state
192
+ // or the required field in state has no value.
193
+ // Wrapped in useCallback to cached the function to avoid intensive memory leaked
194
+ // in every re-render in component
195
+ const validateState = useCallback(
196
+ (state) => {
197
+ //check errors in all fields
198
+ const hasErrorInState = Object.keys(validationSchema).some((key) => {
199
+ const isInputFieldRequired = validationSchema[key].required
200
+ const stateValue = state[key].value // state value
201
+ const stateError = state[key].error // state error
202
+ return (isInputFieldRequired && !stateValue) || stateError
203
+ })
204
+ return hasErrorInState
205
+ },
206
+ [state, validationSchema],
207
+ )
208
+
209
+ function validateField(name, value): string | string[] {
210
+ if (validationSchema[name].required) {
211
+ if (!value) {
212
+ return 'This is a required field.'
213
+ }
214
+ }
215
+
216
+ function _validateSingleValidator(validator, value) {
217
+ if (value && !validator.regex.test(value)) {
218
+ return false
219
+ }
220
+ return true
221
+ }
222
+
223
+ // single validator
224
+ let _validator = validationSchema[name].validator
225
+ if (_validator && typeof _validator === 'object') {
226
+ if (!_validateSingleValidator(_validator, value)) {
227
+ return _validator.error
228
+ }
229
+ }
230
+
231
+ // multiple validators
232
+ let _validators = validationSchema[name].validators
233
+ if (_validators && typeof _validators === 'object' && Array.isArray(_validators)) {
234
+ let errors = []
235
+ _validators.forEach((_validator) => {
236
+ if (!_validateSingleValidator(_validator, value)) {
237
+ errors.push(_validator.error)
238
+ }
239
+ })
240
+ if (errors.length > 0) {
241
+ return errors
242
+ }
243
+ }
244
+
245
+ return ''
246
+ }
247
+
248
+ const handleOnChange = useCallback(
249
+ (event) => {
250
+ setIsDirty(true)
251
+
252
+ const { name, value } = event.target
253
+ let error = validateField(name, value)
254
+ setState((prevState) => ({
255
+ ...prevState,
256
+ [name]: { value, error },
257
+ }))
258
+ },
259
+ [validationSchema],
260
+ )
261
+
262
+ const handleOnSubmit = (event) => {
263
+ event.preventDefault()
264
+ const newState = Object.keys(validationSchema).reduce((agg, curr) => {
265
+ agg[curr] = { ...state[curr], error: validateField(curr, state[curr].value) }
266
+ return agg
267
+ }, state)
268
+ if (!validateState(newState)) {
269
+ callback(state)
270
+ } else {
271
+ setState({ ...newState })
272
+ }
273
+ }
274
+ return { state, disable, handleOnChange, handleOnSubmit }
275
+ }
276
+
277
+ function handleError(error: any): any[] {
278
+ if (!error) {
279
+ return []
280
+ }
281
+
282
+ if (!Array.isArray(error)) {
283
+ return [error]
284
+ }
285
+
286
+ return error
287
+ }
288
+
289
+ export function CustomInput({
290
+ name,
291
+ value,
292
+ error,
293
+ onChange,
294
+ onBlur = (e) => {},
295
+ onFocus = (e) => {},
296
+ label,
297
+ type = 'text',
298
+ disabled = false,
299
+ autoComplete = 'off',
300
+ labelClassName = '',
301
+ placeholder = '',
302
+ tabIndex = 1,
303
+ dataTestid = '',
304
+ }) {
305
+ return (
306
+ <div className="flex column left top">
307
+ <label className={`form__label ${labelClassName}`}>{label}</label>
308
+ <input
309
+ data-testid={dataTestid}
310
+ type={type}
311
+ name={name}
312
+ autoComplete="off"
313
+ className="form__input"
314
+ onChange={(e) => {
315
+ e.persist()
316
+ onChange(e)
317
+ }}
318
+ onBlur={onBlur}
319
+ onFocus={onFocus}
320
+ placeholder={placeholder}
321
+ value={value}
322
+ disabled={disabled}
323
+ tabIndex={tabIndex}
324
+ />
325
+ {handleError(error).map((err) => (
326
+ <div className="form__error">
327
+ <FormError className="form__icon form__icon--error" />
328
+ {err}
329
+ </div>
330
+ ))}
331
+ </div>
332
+ )
333
+ }
@@ -67,7 +67,7 @@ export function TippyCustomized(props: TippyCustomizedProps) {
67
67
  <img
68
68
  className={`icon-dim-${iconSize || 20} mr-6 ${iconClass || ''}`}
69
69
  src={iconPath}
70
- alt={heading}
70
+ alt="Heading"
71
71
  onError={onImageLoadError}
72
72
  />
73
73
  ) : (
@@ -52,7 +52,7 @@ export interface CheckboxProps {
52
52
  export interface TippyCustomizedProps {
53
53
  theme: TippyTheme
54
54
  visible?: boolean
55
- heading?: string
55
+ heading?: ReactNode | string
56
56
  headingInfo?: string
57
57
  infoTextHeading?: string
58
58
  placement: Placement
@@ -260,6 +260,8 @@ export interface CommonNodeAttr {
260
260
  userApprovalConfig?: UserApprovalConfigType
261
261
  requestedUserId?: number
262
262
  showPluginWarning?: boolean
263
+ helmPackageName?: string
264
+ isVirtualEnvironment?: boolean
263
265
  }
264
266
 
265
267
 
@@ -30,3 +30,4 @@ export { default as Toggle } from './Toggle/Toggle'
30
30
  export { default as ScanVulnerabilitiesTable } from './Security/ScanVulnerabilitiesTable'
31
31
  export { default as StyledRadioGroup } from './RadioGroup/RadioGroup'
32
32
  export * from './CIPipeline.Types'
33
+ export { default as DeleteComponent } from './DeleteComponentModal/DeleteComponent'