Complete UserProfileFormFields
This commit is contained in:
parent
73a39bedf5
commit
be330886da
@ -125,14 +125,7 @@ export function UserProfileFormFields(props: UserProfileFormFieldsProps) {
|
|||||||
valueOrValues={valueOrValues}
|
valueOrValues={valueOrValues}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/*
|
{/* NOTE: Downloading of html5DataAnnotations scripts is done in the useUserProfileForm hook */}
|
||||||
TODO:
|
|
||||||
|
|
||||||
<#list profile.html5DataAnnotations?keys as key>
|
|
||||||
<script type="module" src="${url.resourcesPath}/js/${key}.js"></script>
|
|
||||||
</#list>
|
|
||||||
|
|
||||||
*/}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@ -279,32 +272,6 @@ type PropsOfInputFiledByType = {
|
|||||||
function InputFiledByType(props: PropsOfInputFiledByType) {
|
function InputFiledByType(props: PropsOfInputFiledByType) {
|
||||||
const { attribute, valueOrValues } = props;
|
const { attribute, valueOrValues } = props;
|
||||||
|
|
||||||
/*
|
|
||||||
<#macro inputFieldByType attribute>
|
|
||||||
<#switch attribute.annotations.inputType!''>
|
|
||||||
<#case 'textarea'>
|
|
||||||
<@textareaTag attribute=attribute/>
|
|
||||||
<#break>
|
|
||||||
<#case 'select'>
|
|
||||||
<#case 'multiselect'>
|
|
||||||
<@selectTag attribute=attribute/>
|
|
||||||
<#break>
|
|
||||||
<#case 'select-radiobuttons'>
|
|
||||||
<#case 'multiselect-checkboxes'>
|
|
||||||
<@inputTagSelects attribute=attribute/>
|
|
||||||
<#break>
|
|
||||||
<#default>
|
|
||||||
<#if attribute.multivalued && attribute.values?has_content>
|
|
||||||
<#list attribute.values as value>
|
|
||||||
<@inputTag attribute=attribute value=value!''/>
|
|
||||||
</#list>
|
|
||||||
<#else>
|
|
||||||
<@inputTag attribute=attribute value=attribute.value!''/>
|
|
||||||
</#if>
|
|
||||||
</#switch>
|
|
||||||
</#macro>
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (attribute.annotations.inputType) {
|
switch (attribute.annotations.inputType) {
|
||||||
case "textarea":
|
case "textarea":
|
||||||
return <TextareaTag {...props} />;
|
return <TextareaTag {...props} />;
|
||||||
@ -330,43 +297,6 @@ function InputFiledByType(props: PropsOfInputFiledByType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function InputTag(props: PropsOfInputFiledByType & { fieldIndex: number | undefined }) {
|
function InputTag(props: PropsOfInputFiledByType & { fieldIndex: number | undefined }) {
|
||||||
/*
|
|
||||||
<#macro inputTag attribute value>
|
|
||||||
<input type="<@inputTagType attribute=attribute/>" id="${attribute.name}" name="${attribute.name}" value="${(value!'')}" class="${properties.kcInputClass!}"
|
|
||||||
aria-invalid="<#if messagesPerField.existsError('${attribute.name}')>true</#if>"
|
|
||||||
<#if attribute.readOnly>disabled</#if>
|
|
||||||
<#if attribute.autocomplete??>autocomplete="${attribute.autocomplete}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypePlaceholder??>placeholder="${attribute.annotations.inputTypePlaceholder}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypePattern??>pattern="${attribute.annotations.inputTypePattern}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeSize??>size="${attribute.annotations.inputTypeSize}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeMaxlength??>maxlength="${attribute.annotations.inputTypeMaxlength}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeMinlength??>minlength="${attribute.annotations.inputTypeMinlength}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeMax??>max="${attribute.annotations.inputTypeMax}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeMin??>min="${attribute.annotations.inputTypeMin}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeStep??>step="${attribute.annotations.inputTypeStep}"</#if>
|
|
||||||
<#if attribute.annotations.inputTypeStep??>step="${attribute.annotations.inputTypeStep}"</#if>
|
|
||||||
<#list attribute.html5DataAnnotations as key, value>
|
|
||||||
data-${key}="${value}"
|
|
||||||
</#list>
|
|
||||||
/>
|
|
||||||
</#macro>
|
|
||||||
|
|
||||||
<#macro inputTagType attribute>
|
|
||||||
<#compress>
|
|
||||||
<#if attribute.annotations.inputType??>
|
|
||||||
<#if attribute.annotations.inputType?starts_with("html5-")>
|
|
||||||
${attribute.annotations.inputType[6..]}
|
|
||||||
<#else>
|
|
||||||
${attribute.annotations.inputType}
|
|
||||||
</#if>
|
|
||||||
<#else>
|
|
||||||
text
|
|
||||||
</#if>
|
|
||||||
</#compress>
|
|
||||||
</#macro>
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
const { attribute, fieldIndex, getClassName, formValidationDispatch, valueOrValues, i18n, displayableErrors } = props;
|
const { attribute, fieldIndex, getClassName, formValidationDispatch, valueOrValues, i18n, displayableErrors } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -582,41 +512,6 @@ function AddRemoveButtonsMultiValuedAttribute(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function InputTagSelects(props: PropsOfInputFiledByType) {
|
function InputTagSelects(props: PropsOfInputFiledByType) {
|
||||||
/*
|
|
||||||
<#macro inputTagSelects attribute>
|
|
||||||
<#if attribute.annotations.inputType=='select-radiobuttons'>
|
|
||||||
<#assign inputType='radio'>
|
|
||||||
<#assign classDiv=properties.kcInputClassRadio!>
|
|
||||||
<#assign classInput=properties.kcInputClassRadioInput!>
|
|
||||||
<#assign classLabel=properties.kcInputClassRadioLabel!>
|
|
||||||
<#else>
|
|
||||||
<#assign inputType='checkbox'>
|
|
||||||
<#assign classDiv=properties.kcInputClassCheckbox!>
|
|
||||||
<#assign classInput=properties.kcInputClassCheckboxInput!>
|
|
||||||
<#assign classLabel=properties.kcInputClassCheckboxLabel!>
|
|
||||||
</#if>
|
|
||||||
|
|
||||||
<#if attribute.annotations.inputOptionsFromValidation?? && attribute.validators[attribute.annotations.inputOptionsFromValidation]?? && attribute.validators[attribute.annotations.inputOptionsFromValidation].options??>
|
|
||||||
<#assign options=attribute.validators[attribute.annotations.inputOptionsFromValidation].options>
|
|
||||||
<#elseif attribute.validators.options?? && attribute.validators.options.options??>
|
|
||||||
<#assign options=attribute.validators.options.options>
|
|
||||||
<#else>
|
|
||||||
<#assign options=[]>
|
|
||||||
</#if>
|
|
||||||
|
|
||||||
<#list options as option>
|
|
||||||
<div class="${classDiv}">
|
|
||||||
<input type="${inputType}" id="${attribute.name}-${option}" name="${attribute.name}" value="${option}" class="${classInput}"
|
|
||||||
aria-invalid="<#if messagesPerField.existsError('${attribute.name}')>true</#if>"
|
|
||||||
<#if attribute.readOnly>disabled</#if>
|
|
||||||
<#if attribute.values?seq_contains(option)>checked</#if>
|
|
||||||
/>
|
|
||||||
<label for="${attribute.name}-${option}" class="${classLabel}<#if attribute.readOnly> ${properties.kcInputClassRadioCheckboxLabelDisabled!}</#if>"><@selectOptionLabelText attribute=attribute option=option/></label>
|
|
||||||
</div>
|
|
||||||
</#list>
|
|
||||||
</#macro>
|
|
||||||
*/
|
|
||||||
|
|
||||||
const { attribute, formValidationDispatch, getClassName, valueOrValues } = props;
|
const { attribute, formValidationDispatch, getClassName, valueOrValues } = props;
|
||||||
|
|
||||||
const { advancedMsg } = props.i18n;
|
const { advancedMsg } = props.i18n;
|
||||||
|
48
src/tools/formatNumber.ts
Normal file
48
src/tools/formatNumber.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
export const formatNumber = (input: string, format: string): string => {
|
||||||
|
if (!input) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// array holding the patterns for the number of expected digits in each part
|
||||||
|
const digitPattern = format.match(/{\d+}/g);
|
||||||
|
|
||||||
|
if (!digitPattern) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate the maximum size of the given pattern based on the sum of the expected digits
|
||||||
|
const maxSize = digitPattern.reduce((total, p) => total + parseInt(p.replace("{", "").replace("}", "")), 0);
|
||||||
|
|
||||||
|
// keep only digits
|
||||||
|
let rawValue = input.replace(/\D+/g, "");
|
||||||
|
|
||||||
|
// make sure the value is a number
|
||||||
|
if (`${parseInt(rawValue)}` !== rawValue) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the number of digits does not exceed the maximum size
|
||||||
|
if (rawValue.length > maxSize) {
|
||||||
|
rawValue = rawValue.substring(0, maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the regex based based on the expected digits in each part
|
||||||
|
const formatter = digitPattern.reduce((result, p) => result + `(\\d${p})`, "^");
|
||||||
|
|
||||||
|
// if the current digits match the pattern we have each group of digits in an array
|
||||||
|
let digits = new RegExp(formatter).exec(rawValue);
|
||||||
|
|
||||||
|
// no match, return the raw value without any format
|
||||||
|
if (!digits) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = format;
|
||||||
|
|
||||||
|
// finally format the current digits accordingly to the given format
|
||||||
|
for (let i = 0; i < digitPattern.length; i++) {
|
||||||
|
result = result.replace(digitPattern[i], digits[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user