@progress/sitefinity-nextjs-sdk
Version:
Provides OOB widgets developed using the Next.js framework, which includes an abstraction layer for Sitefinity communication. Additionally, it offers an expanded API, typings, and tools for further development and integration.
151 lines (150 loc) • 8.79 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React, { useEffect } from 'react';
import { VisibilityStyle } from '../styling/visibility-style';
import { invalidDataAttr, invalidateElement, serializeForm } from '../common/utils';
import { classNames } from '../../editor/utils/classNames';
import { RestClient } from '../../rest-sdk/rest-client';
import { SecurityService } from '../../services/security-service';
import { getUniqueId } from '../../editor/utils/getUniqueId';
export function ChangePasswordFormClient(props) {
const oldPasswordInputId = getUniqueId('sf-old-password-', props.widgetContext.model.Id);
const newPasswordInputId = getUniqueId('sf-new-password-', props.widgetContext.model.Id);
const repeatPasswordInputId = getUniqueId('sf-repeat-password-', props.widgetContext.model.Id);
const labels = props.labels;
const visibilityClassHidden = props.visibilityClasses[VisibilityStyle.Hidden];
const formRef = React.useRef(null);
const newPassInputRef = React.useRef(null);
const oldPassInputRef = React.useRef(null);
const repeatPassInputRef = React.useRef(null);
const [invalidInputs, setInvalidInputs] = React.useState({});
const [errorMessage, setErrorMessage] = React.useState('');
const [successMessage, setSuccessMessage] = React.useState('');
const [isUserLoaded, setIsUserLoaded] = React.useState(false);
const [hasUser, setHasUser] = React.useState(false);
const [externalProviderName, setExternalProviderName] = React.useState('');
useEffect(() => {
RestClient.getCurrentUser().then((user) => {
const hasUser = (user && user.IsAuthenticated);
setIsUserLoaded(true);
setHasUser(hasUser);
setExternalProviderName(user?.ExternalProviderName);
});
}, []);
const handleSubmit = (event) => {
event.preventDefault();
if (!validateForm(formRef.current)) {
return;
}
SecurityService.setAntiForgeryTokens().then(() => {
const model = { model: serializeForm(formRef.current) };
const submitUrl = formRef.current.attributes['action'].value;
window.fetch(submitUrl, { method: 'POST', body: JSON.stringify(model), headers: { 'Content-Type': 'application/json' } })
.then((response) => {
const status = response.status;
if (status === 0 || (status >= 200 && status < 400)) {
formRef.current.reset();
postPasswordChangeAction();
}
else {
response.json().then((res) => {
const errorMessage = res.error.message;
let element;
if (status === 400) {
element = newPassInputRef.current;
}
else if (status === 403) {
element = oldPassInputRef.current;
}
const emptyInputs = {};
invalidateElement(emptyInputs, element);
setInvalidInputs(emptyInputs);
setErrorMessage(errorMessage);
});
}
});
}, () => {
setErrorMessage('AntiForgery token retrieval failed');
});
};
const postPasswordChangeAction = () => {
const action = props.postPasswordChangeAction;
if (action === 'ViewAMessage') {
const message = props.postPasswordChangeMessage || '';
setSuccessMessage(message);
}
else if (action === 'RedirectToPage') {
const redirectUrl = props.redirectUrl || '';
window.location = redirectUrl;
}
};
const validateForm = (form) => {
setInvalidInputs({});
setErrorMessage('');
setSuccessMessage('');
const requiredInputs = form.querySelectorAll('input[data-sf-role=\'required\']');
const emptyInputs = {};
let isValid = true;
requiredInputs.forEach((input) => {
if (!input.value) {
invalidateElement(emptyInputs, input);
isValid = false;
}
});
if (!isValid) {
const errorMessage = labels.validationRequiredMessage || '';
setErrorMessage(errorMessage);
setInvalidInputs(emptyInputs);
return isValid;
}
const newPassword = newPassInputRef.current;
const repeatPassword = repeatPassInputRef.current;
if (isValid && repeatPassword.value !== newPassword.value) {
invalidateElement(emptyInputs, repeatPassword);
setInvalidInputs(emptyInputs);
isValid = false;
const errorMessage = labels.validationMismatchMessage || '';
setErrorMessage(errorMessage);
}
return isValid;
};
const inputValidationAttrs = (name) => {
return {
className: classNames('form-control', {
[props.invalidClass]: invalidInputs[name]
}),
[invalidDataAttr]: invalidInputs[name],
name: name
};
};
const errorMessageClass = classNames('alert alert-danger my-3', {
[visibilityClassHidden]: !errorMessage
});
const errorMessageStyles = {
display: !visibilityClassHidden ? errorMessage ? '' : 'none' : ''
};
const formElement = (_jsxs(_Fragment, { children: [_jsxs("form", { ref: formRef, onSubmit: handleSubmit, action: props.changePasswordHandlerPath, method: "post", role: "form", children: [_jsx("h2", { className: "mb-3", children: labels.header }), _jsx("div", { "data-sf-role": "error-message-container", className: errorMessageClass, style: errorMessageStyles, role: "alert", "aria-live": "assertive", children: errorMessage }), _jsx("div", { "data-sf-role": "success-message-container", className: classNames('alert alert-success my-3', {
[visibilityClassHidden]: !successMessage
}), style: {
display: !visibilityClassHidden ? successMessage ? '' : 'none' : ''
}, role: "alert", "aria-live": "assertive", children: successMessage }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: oldPasswordInputId, className: "form-label", children: labels.oldPassword }), _jsx("input", { ref: oldPassInputRef, type: "password", className: classNames('form-control', {
[props.invalidClass]: invalidInputs['OldPassword']
}), id: oldPasswordInputId, name: "OldPassword", "data-sf-role": "required", [invalidDataAttr]: invalidInputs['OldPassword'] })] }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: newPasswordInputId, className: "form-label", children: labels.newPassword }), _jsx("input", { ref: newPassInputRef, type: "password", id: newPasswordInputId, "data-sf-role": "required", ...inputValidationAttrs('NewPassword') })] }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: repeatPasswordInputId, className: "form-label", children: labels.repeatPassword }), _jsx("input", { ref: repeatPassInputRef, type: "password", id: repeatPasswordInputId, "data-sf-role": "required", ...inputValidationAttrs('RepeatPassword') })] }), _jsx("input", { type: "hidden", value: "", name: "sf_antiforgery" }), _jsx("input", { className: "btn btn-primary w-100", type: "submit", value: labels.submitButtonLabel })] }), _jsx("input", { type: "hidden", name: "redirectUrl", value: props.redirectUrl }), _jsx("input", { type: "hidden", name: "postChangeMessage", value: props.postPasswordChangeMessage }), _jsx("input", { type: "hidden", name: "postChangeAction", value: props.postPasswordChangeAction }), _jsx("input", { type: "hidden", name: "validationRequiredMessage", value: labels.validationRequiredMessage }), _jsx("input", { type: "hidden", name: "validationMismatchMessage", value: labels.validationMismatchMessage })] }));
if (!props.isLive) {
return formElement;
}
const externalProviderElement = (_jsx("div", { children: `${labels.externalProviderMessageFormat}${externalProviderName}` }));
const notLoggedUserElement = (_jsx("div", { className: "alert alert-danger my-3", children: labels.loginFirstMessage }));
if (isUserLoaded === true) {
if (!hasUser) {
return notLoggedUserElement;
}
else {
return externalProviderName ? externalProviderElement : formElement;
}
}
else {
return null;
}
}
;