diff --git a/app/javascript/components/ComplexDatationInput/components/ComplexDatationInput.jsx b/app/javascript/components/ComplexDatationInput/components/ComplexDatationInput.jsx
index b5a94d6bc..686ab0774 100644
--- a/app/javascript/components/ComplexDatationInput/components/ComplexDatationInput.jsx
+++ b/app/javascript/components/ComplexDatationInput/components/ComplexDatationInput.jsx
@@ -16,7 +16,8 @@ const ComplexDatationInput = (props) => {
choiceSets: choiceSetsProps,
selectedFormat: selectedFormatProps,
fieldUuid,
- componentPolicies
+ componentPolicies,
+ errors
} = props
const [choiceSets, setChoiceSets] = useState(choiceSetsProps)
@@ -110,9 +111,12 @@ const ComplexDatationInput = (props) => {
setToState(to);
}, [granularity])
- let dateValid = isCurrentFormatValid();
- let errorStl = dateValid ? {} : {border: "2px solid #f00"};
- let errorMsg = dateValid ? "" : "Invalid value";
+ let fromDateValid = isCurrentFormatValid('from');
+ let toDateValid = isCurrentFormatValid('to');
+ let errorStl = {
+ "from": fromDateValid ? {} : {border: "2px solid #f00"},
+ "to": toDateValid ? {} : {border: "2px solid #f00"}
+ };
let fmt = getFieldOptions().format;
function _handleChangeBC(input) {
@@ -240,17 +244,18 @@ const ComplexDatationInput = (props) => {
});
}
- function getCurrentFormat() {
+ function getCurrentFormat(input) {
let d = getData();
let f = getFieldOptions().format;
return f.split('').map(function (k) {
- return d['from'][k] ? k : d['to'][k] ? k : '';
+ return d[input][k] ? k : '';
}).join('')
}
- function isCurrentFormatValid() {
- let current = getCurrentFormat();
+ function isCurrentFormatValid(input) {
+ let current = getCurrentFormat(input);
if (current === '' && !isRequired) return true; // allow empty value if field is not required
+ if (current === '' && isRequired && getCurrentFormat(input === "from" ? "to" : "from") !== '') return true;
let allowed = getAllowedFormats();
return allowed.indexOf(current) > -1;
}
@@ -274,13 +279,13 @@ const ComplexDatationInput = (props) => {
) : null}
{fmt.includes('D') ? (
-
) : null
}
{fmt.includes('M') ? (
- ) : null
}
{fmt.includes('Y') ? (
-
) : null
}
{fmt.includes('h') ? (
-
) : null
}
{fmt.includes('m') ? (
-
) : null
}
{fmt.includes('s') ? (
-
) : null
@@ -353,21 +358,21 @@ const ComplexDatationInput = (props) => {
)
}
- if (!fromState || !toState) return ""
+ if (!fromState || !toState) return ""
return (
{renderAllowedFormatsSelector()}
{selectedFormat === 'date_time' && (
-
-
{renderDateTimeInput('from')}
-
{renderDateTimeInput('to')}
-
{errorMsg}
-
+
+
{renderDateTimeInput('from', input)}
+
{renderDateTimeInput('to', input)}
+
{errors?.filter(e => e.field === input.split("#item_")[1].split("_json")[0])?.map(e => e.message)?.join(',')}
+
)}
- {selectedFormat === 'datation_choice' && (
-
{
{errorMsg}
-
diff --git a/app/javascript/components/DateTimeInput/components/DateTimeInput.jsx b/app/javascript/components/DateTimeInput/components/DateTimeInput.jsx
index e273c268d..e122d1e3c 100644
--- a/app/javascript/components/DateTimeInput/components/DateTimeInput.jsx
+++ b/app/javascript/components/DateTimeInput/components/DateTimeInput.jsx
@@ -10,7 +10,8 @@ const DateTimeInput = (props) => {
const {
input,
allowBC,
- preventNegativeInput
+ preventNegativeInput,
+ errors
} = props
const [state, setState] = useState(false)
@@ -39,7 +40,6 @@ const DateTimeInput = (props) => {
let dateValid = isCurrentFormatValid();
let errorStl = dateValid ? {} : {border: "2px solid #f00"};
- let errorMsg = dateValid ? "" : "Invalid value";
let fmt = getFieldOptions().format;
function _handleChangeDay(e) {
@@ -218,7 +218,8 @@ const DateTimeInput = (props) => {
) : null
}
{fmt.includes('Y') ? (
-
) : null
}
@@ -238,7 +239,7 @@ const DateTimeInput = (props) => {
) : null
}
- {errorMsg}
+ {errors?.filter(e => e.field === input.split("#item_")[1].split("_json")[0])?.map(e => e.message)?.join(',')}
);
};
diff --git a/app/models/field/complex_datation.rb b/app/models/field/complex_datation.rb
index 495e1c98c..49ac12685 100644
--- a/app/models/field/complex_datation.rb
+++ b/app/models/field/complex_datation.rb
@@ -170,7 +170,13 @@ def edit_props(item)
componentPolicies:
{
modal: "super-editor"
+ },
+ errors: item[:item].errors.map do |error|
+ {
+ message: error.message,
+ field: error.attribute
}
+ end
}
end
@@ -276,18 +282,29 @@ class ComplexDatationValidator < ActiveModel::Validator
def validate(record)
attrib = Array.wrap(options[:attributes]).first
value = record.public_send(attrib)
+ field = Field.find_by(uuid: attrib)
return if value.blank?
-
return if value['selected_format'] != "date_time"
+ to_value_empty = value['to'].keys.reject{|k| k=="BC"}.all? { |key| value['to'][key].blank? || value['to'][key].nil? }
+ from_value_empty = value['from'].keys.reject{|k| k=="BC"}.all? { |key| value['from'][key].blank? || value['from'][key].nil? }
+ return if to_value_empty && from_value_empty && !field.required
- from_date_is_positive = value['from'].compact.except("BC").all? { |_, v| v.to_i >= 0 }
+ if to_value_empty && from_value_empty && field.required
+ record.errors.add(attrib, I18n.t('activerecord.errors.models.item.attributes.base.cant_be_blank'))
+ return
+ end
+ from_date_is_positive = value['from'].compact.except("BC").all? { |_, v| v.to_i >= 0 }
to_date_is_positive = value['to'].compact.except("BC").all? { |_, v| v.to_i >= 0 }
- return if to_date_is_positive && from_date_is_positive
+ allowed_formats = Field::ComplexDatation::FORMATS.select{|f| field.format.include?(f) || field.format == f}
+
+ current_from_format = field.format.chars.map {|char| value['from'][char].blank? || value['from'][char].nil? ? nil : char}.compact.join
+ current_to_format = field.format.chars.map {|char| value['to'][char].blank? || value['to'][char].nil? ? nil : char}.compact.join
- record.errors.add(:base, :negative_dates)
+ record.errors.add(attrib, I18n.t('activerecord.errors.models.item.attributes.base.wrong_format', field_format: allowed_formats)) unless (allowed_formats.include?(current_from_format) || from_value_empty) && (allowed_formats.include?(current_to_format) || to_value_empty)
+ record.errors.add(attrib, :negative_dates) if !to_date_is_positive || !from_date_is_positive
end
end
end
diff --git a/app/models/field/date_time.rb b/app/models/field/date_time.rb
index 38f9541fa..072e50234 100644
--- a/app/models/field/date_time.rb
+++ b/app/models/field/date_time.rb
@@ -159,6 +159,17 @@ def sql_type
"JSON"
end
+ def edit_props(item)
+ {
+ errors: item[:item].errors.map do |error|
+ {
+ message: error.message,
+ field: error.attribute
+ }
+ end
+ }
+ end
+
private
def transform_value(v)
@@ -182,4 +193,31 @@ def coerce_to_array(values)
array << values[key]
end.compact
end
+
+ def build_validators
+ [DateTimeValidator]
+ end
+
+ class DateTimeValidator < ActiveModel::Validator
+ def validate(record)
+ attrib = Array.wrap(options[:attributes]).first
+ value = record.public_send(attrib)
+ field = Field.find_by(uuid: attrib)
+
+ return if value.blank?
+ return if value.is_a?(Hash) && value.has_key?("raw_value")
+ return if value.keys.all? { |key| value[key].blank? || value[key].nil? } && !field.required
+
+ if value.keys.all? { |key| value[key].blank? || value[key].nil? } && field.required
+ record.errors.add(attrib, I18n.t('activerecord.errors.models.item.attributes.base.cant_be_blank'))
+ return
+ end
+
+ allowed_formats = Field::DateTime::FORMATS.select{|f| field.format.include?(f) || field.format == f}
+ current_format = field.format.chars.map {|char| value[char].blank? || value[char].nil? ? nil : char}.compact.join
+
+ record.errors.add(attrib, I18n.t('activerecord.errors.models.item.attributes.base.wrong_format', field_format: allowed_formats)) unless allowed_formats.include?(current_format)
+ end
+ end
end
+
diff --git a/config/locales/app/en.yml b/config/locales/app/en.yml
index bcf631382..4f61dde8a 100644
--- a/config/locales/app/en.yml
+++ b/config/locales/app/en.yml
@@ -65,7 +65,9 @@ en:
item:
attributes:
base:
+ cant_be_blank: "Must be present"
negative_dates: "Negative dates must be entered with the option before Jesus Christ (if activated)"
+ wrong_format: "Do not respect the formats %{field_format}"
field/choice_set:
attributes:
choice_set_id:
diff --git a/config/locales/app/fr.yml b/config/locales/app/fr.yml
index c4fa10b07..124c66d8e 100644
--- a/config/locales/app/fr.yml
+++ b/config/locales/app/fr.yml
@@ -67,7 +67,9 @@ fr:
item:
attributes:
base:
+ cant_be_blank: "Doit être rempli(e)"
negative_dates: "Les dates négatives doivent être saisies avec l'option avant Jesus Christ (si activée)"
+ wrong_format: "Ne respecte pas les formats %{field_format}"
field/choice_set:
attributes:
choice_set_id: