UNPKG

@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.

211 lines (210 loc) 14.5 kB
'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, isValidEmail, serializeForm, SF_WEBSERVICE_API_KEY_HEADER } from '../common/utils'; import { classNames } from '../../editor/utils/classNames'; import { getQueryParams } from '../common/query-params'; import { useSearchParams } from 'next/navigation'; import { SecurityService } from '../../services/security-service'; import { ExternalLoginBase } from '../external-login-base'; import { getUniqueId } from '../../editor/utils/getUniqueId'; export function RegistrationFormClient(props) { const searchParams = useSearchParams(); const viewProps = { ...props.viewProps }; const context = viewProps.widgetContext.requestContext; const firstNameInputId = getUniqueId('sf-first-name-', viewProps.widgetContext.model.Id); const lastNameInputId = getUniqueId('sf-last-name-', viewProps.widgetContext.model.Id); const emailInputId = getUniqueId('sf-email-', viewProps.widgetContext.model.Id); const passwordInputId = getUniqueId('sf-new-password-', viewProps.widgetContext.model.Id); const repeatPasswordInputId = getUniqueId('sf-repeat-password-', viewProps.widgetContext.model.Id); const questionInputId = getUniqueId('sf-secret-question-', viewProps.widgetContext.model.Id); const answerInputId = getUniqueId('sf-secret-answer-', viewProps.widgetContext.model.Id); const labels = viewProps.labels; const visibilityClassHidden = viewProps.visibilityClasses[VisibilityStyle.Hidden]; const formRef = React.useRef(null); const passwordInputRef = React.useRef(null); const repeatPasswordInputRef = React.useRef(null); const emailInputRef = React.useRef(null); const [invalidInputs, setInvalidInputs] = React.useState({}); const [errorMessage, setErrorMessage] = React.useState(''); const [showFormContainer, setShowFormContainer] = React.useState(true); const [showSuccessRegistrationContainer, setSuccessRegistrationContainer] = React.useState(false); const [showSuccessContainer, setSuccessContainer] = React.useState(false); const [activationLinkMessage, setActivationLinkMessage] = React.useState(''); const [externalProvidersData, setExternalProvidersData] = React.useState([]); useEffect(() => { const externalProviderData = viewProps.externalProviders?.map(provider => { const providerClass = ExternalLoginBase.GetExternalLoginButtonCssClass(provider.Name); const externalLoginPath = ExternalLoginBase.GetExternalLoginPath(getQueryParams(searchParams), provider.Name); return { cssClass: providerClass, externalLoginPath: externalLoginPath, label: provider.Value }; }) ?? []; setExternalProvidersData(externalProviderData); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const postRegistrationAction = () => { let action = viewProps.postRegistrationAction; let activationMethod = viewProps.activationMethod; if (action === 'ViewMessage') { if (activationMethod === 'AfterConfirmation') { showSuccessAndConfirmationSentMessage(); } else { showSuccessMessage(); } } else if (action === 'RedirectToPage') { let redirectUrl = viewProps.redirectUrl; window.location = redirectUrl; } }; const onRegistrationError = (errorMessage) => { setErrorMessage(errorMessage); }; const handleSubmit = (event) => { event.preventDefault(); if (!validateForm(formRef.current)) { return; } SecurityService.setAntiForgeryTokens().then(() => { submitFormHandler(formRef.current, '', postRegistrationAction, onRegistrationError); }, () => { setErrorMessage('AntiForgery token retrieval failed'); }); }; const submitFormHandler = (form, url, onSuccess, onError) => { url = url || form.attributes['action'].value; let model = { model: serializeForm(form) }; const headers = { 'Content-Type': 'application/json' }; if (props.viewProps.webserviceApiKey) { headers[SF_WEBSERVICE_API_KEY_HEADER] = props.viewProps.webserviceApiKey; } window.fetch(url, { method: 'POST', body: JSON.stringify(model), headers }).then((response) => { let status = response.status; if (status === 0 || (status >= 200 && status < 400)) { if (onSuccess) { onSuccess(); } } else { response.json().then((res) => { let message = res.error.message; if (onError) { onError(message); } }); } }); }; const postResendAction = () => { const sendAgainLabel = labels.sendAgainLabel; const formData = new FormData(formRef.current); const email = formData.get('Email')?.valueOf(); setActivationLinkMessage(sendAgainLabel.replace('{0}', email)); }; const invalidateElement = (emptyInputs, element) => { if (element) { emptyInputs[element.name] = true; } }; const validateForm = (form) => { let isValid = true; setInvalidInputs({}); const emptyInputs = {}; let requiredInputs = form.querySelectorAll('input[data-sf-role=\'required\']'); requiredInputs.forEach((input) => { if (!input.value) { invalidateElement(emptyInputs, input); setInvalidInputs(emptyInputs); isValid = false; } }); if (!isValid) { setErrorMessage(labels.validationRequiredMessage); return isValid; } let emailInput = emailInputRef.current; if (!isValidEmail(emailInput.value)) { invalidateElement(emptyInputs, emailInput); setInvalidInputs(emptyInputs); setErrorMessage(labels.validationInvalidEmailMessage); return false; } if (passwordInputRef.current.value !== repeatPasswordInputRef.current.value) { invalidateElement(emptyInputs, repeatPasswordInputRef.current); setInvalidInputs(emptyInputs); setErrorMessage(labels.validationMismatchMessage); return false; } return isValid; }; const showSuccessMessage = () => { setErrorMessage(''); setShowFormContainer(false); setSuccessRegistrationContainer(true); }; const showSuccessAndConfirmationSentMessage = () => { setShowFormContainer(false); setSuccessContainer(true); const activationLinkLabel = labels.activationLinkLabel; const formData = new FormData(formRef.current); const email = formData.get('Email'); setActivationLinkMessage(`${activationLinkLabel} ${email}`); }; const handleSendAgain = (event) => { const resendUrl = viewProps.resendConfirmationEmailHandlerPath; event.preventDefault(); submitFormHandler(formRef.current, resendUrl, postResendAction); }; const formContainerClass = classNames({ [visibilityClassHidden]: !showFormContainer }); const formContainerStyle = { display: !visibilityClassHidden ? showFormContainer ? '' : 'none' : '' }; const errorMessageClass = classNames('alert alert-danger my-3', { [visibilityClassHidden]: !errorMessage }); const errorMessageStyles = { display: !visibilityClassHidden ? errorMessage ? '' : 'none' : '' }; const confirmContainerClass = classNames({ [visibilityClassHidden]: !showSuccessContainer }); const confirmContainerStyle = { display: !visibilityClassHidden ? showSuccessContainer ? '' : 'none' : '' }; const successRegistrationContainerClass = classNames({ [visibilityClassHidden]: !showSuccessRegistrationContainer }); const successRegistrationContainerStyle = { display: !visibilityClassHidden ? showSuccessRegistrationContainer ? '' : 'none' : '' }; const inputValidationAttrs = (name) => { return { className: classNames('form-control', { [viewProps.invalidClass]: invalidInputs[name] }), [invalidDataAttr]: invalidInputs[name], name: name }; }; if (context.isLive && !viewProps.activationPageUrl?.toUpperCase().startsWith('HTTP')) { viewProps.activationPageUrl = typeof window !== 'undefined' ? window.location.protocol + '//' + viewProps.activationPageUrl : ''; } return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-sf-role": "form-container", className: formContainerClass, style: formContainerStyle, 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 }), _jsxs("form", { ref: formRef, role: "form", noValidate: true, method: "post", action: props.action, onSubmit: handleSubmit, children: [_jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: firstNameInputId, className: "form-label", children: labels.firstNameLabel }), _jsx("input", { id: firstNameInputId, type: "text", "data-sf-role": "required", ...inputValidationAttrs('FirstName') })] }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: lastNameInputId, className: "form-label", children: labels.lastNameLabel }), _jsx("input", { id: lastNameInputId, type: "text", "data-sf-role": "required", ...inputValidationAttrs('LastName') })] }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: emailInputId, className: "form-label", children: labels.emailLabel }), _jsx("input", { ref: emailInputRef, id: emailInputId, type: "email", "data-sf-role": "required", ...inputValidationAttrs('Email') })] }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: passwordInputId, className: "form-label", children: labels.passwordLabel }), _jsx("input", { ref: passwordInputRef, id: passwordInputId, type: "password", "data-sf-role": "required", ...inputValidationAttrs('Password') })] }), _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: repeatPasswordInputId, className: "form-label", children: labels.repeatPasswordLabel }), _jsx("input", { ref: repeatPasswordInputRef, id: repeatPasswordInputId, type: "password", "data-sf-role": "required", ...inputValidationAttrs('RepeatPassword') })] }), viewProps.requiresQuestionAndAnswer && _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: questionInputId, className: "form-label", children: labels.secretQuestionLabel }), _jsx("input", { id: questionInputId, type: "text", "data-sf-role": "required", ...inputValidationAttrs('Question') })] }), viewProps.requiresQuestionAndAnswer && _jsxs("div", { className: "mb-3", children: [_jsx("label", { htmlFor: answerInputId, className: "form-label", children: labels.secretAnswerLabel }), _jsx("input", { id: answerInputId, type: "text", "data-sf-role": "required", ...inputValidationAttrs('Answer') })] }), _jsx("input", { className: "btn btn-primary w-100", type: "submit", value: labels.registerButtonLabel }), _jsx("input", { type: "hidden", name: "ActivationPageUrl", defaultValue: viewProps.activationPageUrl }), _jsx("input", { type: "hidden", value: "", name: "sf_antiforgery" })] }), viewProps.loginPageUrl && _jsx("div", { className: "mt-3", children: labels.loginLabel }), viewProps.loginPageUrl && _jsx("a", { href: viewProps.loginPageUrl, className: "text-decoration-none", children: labels.loginLink }), externalProvidersData.length > 0 && (_jsxs(_Fragment, { children: [_jsx("h3", { className: "mt-3", children: labels.externalProvidersHeader }), externalProvidersData.map((providerData, idx) => { return (_jsx("a", { className: classNames('btn border fs-5 w-100 mt-2', providerData.cssClass), href: providerData.externalLoginPath, "data-sf-test": "extPrv", children: providerData.label }, idx)); })] })), _jsxs(_Fragment, { children: [_jsx("input", { type: "hidden", name: "RedirectUrl", defaultValue: viewProps.redirectUrl }), _jsx("input", { type: "hidden", name: "PostRegistrationAction", defaultValue: viewProps.postRegistrationAction }), _jsx("input", { type: "hidden", name: "ActivationMethod", defaultValue: viewProps.activationMethod }), _jsx("input", { type: "hidden", name: "ValidationRequiredMessage", value: labels.validationRequiredMessage }), _jsx("input", { type: "hidden", name: "ValidationMismatchMessage", value: labels.validationMismatchMessage }), _jsx("input", { type: "hidden", name: "ValidationInvalidEmailMessage", value: labels.validationInvalidEmailMessage })] })] }), _jsxs("div", { "data-sf-role": "success-registration-message-container", className: successRegistrationContainerClass, style: successRegistrationContainerStyle, children: [_jsx("h3", { children: labels.successHeader }), _jsx("p", { children: labels.successLabel })] }), _jsxs("div", { "data-sf-role": "confirm-registration-message-container", className: confirmContainerClass, style: confirmContainerStyle, children: [_jsx("h3", { children: labels.activationLinkHeader }), _jsx("p", { "data-sf-role": "activation-link-message-container", children: activationLinkMessage }), _jsx("a", { "data-sf-role": "sendAgainLink", onClick: handleSendAgain, className: "btn btn-primary", children: labels.sendAgainLink }), _jsxs(_Fragment, { children: [_jsx("input", { type: "hidden", name: "ResendConfirmationEmailUrl", value: viewProps.resendConfirmationEmailHandlerPath }), _jsx("input", { type: "hidden", name: "ActivationLinkLabel", value: labels.activationLinkLabel }), _jsx("input", { type: "hidden", name: "SendAgainLink", value: labels.sendAgainLink }), _jsx("input", { type: "hidden", name: "SendAgainLabel", value: labels.sendAgainLabel })] })] })] })); } ;