@openshift-assisted/ui-lib
Version:
React component library for the Assisted Installer UI
151 lines • 9.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_core_1 = require("@patternfly/react-core");
const formik_1 = require("formik");
const Yup = tslib_1.__importStar(require("yup"));
const global_palette_blue_300_1 = require("@patternfly/react-tokens/dist/js/global_palette_blue_300");
const info_circle_icon_1 = require("@patternfly/react-icons/dist/js/icons/info-circle-icon");
const ui_1 = require("../ui");
const utils_1 = require("./utils");
const use_translation_wrapper_1 = require("../../hooks/use-translation-wrapper");
const api_1 = require("../../api"); // eslint-disable-line no-restricted-imports
require("./MassChangeHostnameModal.css");
const getHostname = (host) => {
const inventory = (0, utils_1.getInventory)(host);
return (0, utils_1.getHostname)(host, inventory) || '';
};
const templateToHostname = (index, values) => values.hostname.replace(/{{n+}}/g, `${index + 1}`);
const getNewHostnames = (values, selectedHosts, canChangeHostname) => {
let index = 0;
return selectedHosts.map((h) => {
const [changeEnabled, reason] = canChangeHostname(h);
const hostnameRes = {
newHostname: changeEnabled ? templateToHostname(index, values) : undefined,
reason: changeEnabled ? undefined : reason,
};
if (changeEnabled) {
index++;
}
return hostnameRes;
});
};
const initialValues = {
hostname: '',
};
const validationSchema = (initialValues, usedHostnames, t) => Yup.object().shape({
hostname: (0, ui_1.richHostnameValidationSchema)(t, usedHostnames, initialValues.hostname).required(t('ai:Required field')),
});
const updateHostnameValidationResult = (validationResult, message) => {
validationResult = Object.assign(Object.assign({}, (validationResult || {})), { hostname: ((validationResult === null || validationResult === void 0 ? void 0 : validationResult.hostname) || []).concat(message) });
return validationResult;
};
const withTemplate = (selectedHosts, hosts, schema, canChangeHostname, t) => (values) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
const newHostnames = getNewHostnames(values, selectedHosts, canChangeHostname)
.filter((h) => !h.reason)
.map(({ newHostname }) => newHostname);
const usedHostnames = hosts.reduce((acc, host) => {
if (!selectedHosts.find((a) => a.id === host.id)) {
acc.push(getHostname(host));
}
return acc;
}, []);
let validationResult = yield (0, ui_1.getRichTextValidation)(schema)(Object.assign(Object.assign({}, values), { hostname: newHostnames[0] || '' }));
if (newHostnames.some((newHostname) => usedHostnames.includes(newHostname || '')) ||
new Set(newHostnames).size !== newHostnames.length) {
validationResult = updateHostnameValidationResult(validationResult, (0, ui_1.hostnameValidationMessages)(t).NOT_UNIQUE);
}
if (newHostnames.some((hostname) => ui_1.FORBIDDEN_HOSTNAMES.includes(hostname || ''))) {
validationResult = updateHostnameValidationResult(validationResult, (0, ui_1.hostnameValidationMessages)(t).LOCALHOST_ERR);
}
return validationResult;
});
const MassChangeHostnameForm = ({ selectedHosts: initHosts, isOpen, patchingHost, onClose, canChangeHostname, }) => {
var _a;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { values, handleSubmit, isSubmitting, status, isValid } = (0, formik_1.useFormikContext)();
const hostnameInputRef = React.useRef();
const ref = React.useRef(initHosts);
React.useEffect(() => {
var _a;
isOpen && ((_a = hostnameInputRef.current) === null || _a === void 0 ? void 0 : _a.focus());
}, [isOpen]);
React.useCallback(() => {
if (!isSubmitting) {
ref.current = initHosts;
}
}, [initHosts, isSubmitting]);
const selectedHosts = ref.current;
const newHostnames = getNewHostnames(values, selectedHosts, canChangeHostname);
const { t } = (0, use_translation_wrapper_1.useTranslation)();
return (React.createElement(react_core_1.Form, { onSubmit: handleSubmit },
React.createElement(react_core_1.ModalBoxBody, null,
React.createElement(react_core_1.Stack, { hasGutter: true },
React.createElement(react_core_1.StackItem, null,
React.createElement("div", null, t('ai:Rename hostnames using the custom template:')),
React.createElement("div", null,
React.createElement("strong", null, `{{n}}`),
" ",
t('ai:to add a number.'))),
React.createElement(react_core_1.StackItem, null,
React.createElement(ui_1.RichInputField, { name: "hostname", ref: hostnameInputRef, isRequired: true, richValidationMessages: (0, ui_1.hostnameValidationMessages)(t) }),
React.createElement(react_core_1.HelperText, null,
React.createElement(react_core_1.HelperTextItem, { variant: "indeterminate" }, t('ai:For example: host-{{n}}', {
interpolation: { suffix: '###', prefix: '###' },
})))),
React.createElement(react_core_1.StackItem, null,
t('ai:Preview'),
React.createElement("div", { className: "hostname-preview" }, selectedHosts.map((h, index) => {
const { newHostname, reason } = newHostnames[index];
return (React.createElement(react_core_1.Split, { key: h.id || index, hasGutter: true },
React.createElement(react_core_1.SplitItem, { className: "hostname-column" },
React.createElement("div", { className: "hostname-column__text" },
React.createElement("strong", null, getHostname(h)))),
React.createElement(react_core_1.SplitItem, null,
React.createElement("div", null,
React.createElement("strong", null, '>'))),
React.createElement(react_core_1.SplitItem, { isFilled: true }, reason ? (React.createElement(react_core_1.Popover, { "aria-label": t('ai:Cannot change hostname popover'), headerContent: React.createElement("div", null, t('ai:Hostname cannot be changed')), bodyContent: React.createElement("div", null, reason) },
React.createElement(react_core_1.Button, { variant: "link", icon: React.createElement(info_circle_icon_1.InfoCircleIcon, { color: global_palette_blue_300_1.global_palette_blue_300.value }), isInline: true }, t('ai:Not changeable')))) : (newHostname || t('ai:New hostname will appear here...')))));
}))),
React.createElement(react_core_1.StackItem, null,
React.createElement(ui_1.ModalProgress
// eslint-disable-next-line
, {
// eslint-disable-next-line
error: status === null || status === void 0 ? void 0 : status.error, progress: isSubmitting ? (100 * (patchingHost + 1)) / selectedHosts.length : null })))),
React.createElement(react_core_1.ModalBoxFooter, null,
React.createElement(react_core_1.Button, { key: "submit", type: react_core_1.ButtonType.submit, isDisabled: isSubmitting || !isValid || !((_a = hostnameInputRef.current) === null || _a === void 0 ? void 0 : _a.value.trim()) }, t('ai:Change')),
React.createElement(react_core_1.Button, { onClick: onClose, variant: react_core_1.ButtonVariant.secondary, isDisabled: isSubmitting }, t('ai:Cancel')))));
};
const MassChangeHostnameModal = ({ isOpen, onClose, selectedHostIDs, hosts, onChangeHostname, canChangeHostname, reloadCluster, onHostSaveError, }) => {
const [patchingHost, setPatchingHost] = React.useState(0);
const selectedHosts = hosts.filter((h) => selectedHostIDs.includes(h.id));
const { t } = (0, use_translation_wrapper_1.useTranslation)();
return (React.createElement(react_core_1.Modal, { "aria-label": t('ai:Change hostnames dialog'), title: t('ai:Change hostnames'), isOpen: isOpen, onClose: onClose, hasNoBodyWrapper: true, id: "mass-change-hostname-modal", variant: "small" },
React.createElement(formik_1.Formik, { initialValues: initialValues, validate: withTemplate(selectedHosts, hosts, validationSchema(initialValues, [], t), canChangeHostname, t), onSubmit: (values, formikActions) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
let i = 0;
try {
for (const agent of selectedHosts) {
setPatchingHost(i);
const newHostname = templateToHostname(i, values);
yield onChangeHostname(agent, newHostname);
i++;
}
reloadCluster && reloadCluster();
onClose();
}
catch (e) {
formikActions.setStatus({
error: {
title: t('ai:Failed to update host'),
message: (0, api_1.getApiErrorMessage)(e),
},
});
onHostSaveError && onHostSaveError(e);
}
}) },
React.createElement(MassChangeHostnameForm, { isOpen: isOpen, selectedHosts: selectedHosts, patchingHost: patchingHost, onClose: onClose, canChangeHostname: canChangeHostname }))));
};
exports.default = MassChangeHostnameModal;
//# sourceMappingURL=MassChangeHostnameModal.js.map