mattermost-redux
Version:
Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client
129 lines (128 loc) • 4.87 kB
JavaScript
;
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkDialogElementForError = checkDialogElementForError;
exports.checkIfErrorsMatchElements = checkIfErrorsMatchElements;
const date_fns_1 = require("date-fns");
const react_intl_1 = require("react-intl");
// Validation patterns for exact storage format matching
const DATE_FORMAT_PATTERN = /^\d{4}-\d{2}-\d{2}$/; // YYYY-MM-DD
const DATETIME_FORMAT_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/; // YYYY-MM-DDTHH:mm:ssZ
/**
* Validates date/datetime field values for format and range constraints
*/
function validateDateTimeValue(value, elem) {
const parsedDate = (0, date_fns_1.parseISO)(value);
if (!(0, date_fns_1.isValid)(parsedDate)) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.bad_format',
defaultMessage: 'Invalid date format',
});
}
const isDateField = elem.type === 'date';
if (isDateField) {
if (!DATE_FORMAT_PATTERN.test(value)) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.bad_date_format',
defaultMessage: 'Date field must be in YYYY-MM-DD format',
});
}
}
else if (!DATETIME_FORMAT_PATTERN.test(value)) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.bad_datetime_format',
defaultMessage: 'DateTime field must be in YYYY-MM-DDTHH:mm:ssZ format',
});
}
return null;
}
function checkDialogElementForError(elem, value) {
// Check if value is empty (handles arrays for multiselect)
let isEmpty;
if (value === 0) {
isEmpty = false;
}
else if (Array.isArray(value)) {
isEmpty = value.length === 0;
}
else {
isEmpty = !value;
}
if (isEmpty && !elem.optional) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.required',
defaultMessage: 'This field is required.',
});
}
const type = elem.type;
if (type === 'text' || type === 'textarea') {
if (value && value.length < elem.min_length) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.too_short',
// minLength provided by InteractiveDialog
// eslint-disable-next-line formatjs/enforce-placeholders
defaultMessage: 'Minimum input length is {minLength}.',
});
}
if (elem.subtype === 'email') {
if (value && !value.includes('@')) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.bad_email',
defaultMessage: 'Must be a valid email address.',
});
}
}
if (elem.subtype === 'number') {
if (value && isNaN(value)) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.bad_number',
defaultMessage: 'Must be a number.',
});
}
}
if (elem.subtype === 'url') {
if (value && !value.includes('http://') && !value.includes('https://')) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.bad_url',
defaultMessage: 'URL must include http:// or https://.',
});
}
}
}
else if (type === 'radio') {
const options = elem.options;
if (typeof value !== 'undefined' && Array.isArray(options) && !options.some((e) => e.value === value)) {
return (0, react_intl_1.defineMessage)({
id: 'interactive_dialog.error.invalid_option',
defaultMessage: 'Must be a valid option',
});
}
}
else if (type === 'date' || type === 'datetime') {
// Validate date/datetime format and range constraints
if (value && typeof value === 'string') {
const validationError = validateDateTimeValue(value, elem);
if (validationError) {
return validationError;
}
}
return null;
}
return null;
}
// If we're returned errors that don't match any of the elements we have,
// ignore them and complete the dialog
function checkIfErrorsMatchElements(errors = {}, elements = []) {
for (const name in errors) {
if (!Object.hasOwn(errors, name)) {
continue;
}
for (const elem of elements) {
if (elem.name === name) {
return true;
}
}
}
return false;
}