From a32ee20a40d55855543e2972f98663c36201b6bf Mon Sep 17 00:00:00 2001 From: Tim Worrall Date: Mon, 6 Apr 2015 14:48:05 -0400 Subject: [PATCH] VIVO-921: some additional validation work as well as dislaying an indicator when a data property has been ingested in an invalid format. --- .../languages/es_GO/i18n/all_es_GO.properties | 12 +- .../individual/DataPropertyTemplateModel.java | 7 + webapp/web/css/individual/individual.css | 4 + webapp/web/i18n/all.properties | 12 +- .../individual/propStatement-dataDefault.ftl | 68 +++++++++- .../edit/forms/defaultDataPropertyForm.ftl | 11 ++ .../edit/forms/js/defaultDataPropertyUtils.js | 128 +++++++++++++----- 7 files changed, 199 insertions(+), 43 deletions(-) diff --git a/webapp/languages/es_GO/i18n/all_es_GO.properties b/webapp/languages/es_GO/i18n/all_es_GO.properties index b9c22edf6..a62a3a29d 100644 --- a/webapp/languages/es_GO/i18n/all_es_GO.properties +++ b/webapp/languages/es_GO/i18n/all_es_GO.properties @@ -886,4 +886,14 @@ faux_property_listing = Lista de faux propiedades faux_property_by_base = Faux propiedades por base propriedad faux_property_alpha = Faux propiedades en orden alfabético -no_class_restrictions=No hay clases con una restricción de esta propiedad. \ No newline at end of file +no_class_restrictions=No hay clases con una restricción de esta propiedad. + +invalid_format=Formato inválido +four_digit_year=Entrada invalida. Por favor, introduzca un año de 4 dígitos. +year_numeric=Entrada invalida. El Año debe ser numérico. +year_month_day=Entrada invalida. Por favor, introduzca un año, mes y día. +minimum_ymd=Entrada invalida. Introduzca por lo menos un año, mes y día. +minimum_hour=Entrada invalida. Especifique por lo menos una hora. +year_month=Entrada invalida. Por favor ingrese un Año y Mes. +decimal_only=Entrada invalida. Se permite un punto decimal, pero miles separadores no son. +whole_number=Entrada invalida. Por favor, introduzca un número entero sin punto decimal o miles separadores. diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java index dbe99ce60..bf22a5dac 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java @@ -64,6 +64,7 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel { private DataPropertyListConfig config; private String objectKey; private String queryString; + private String rangeDatatypeURI; private Set constructQueries; private int displayLimit; @@ -84,6 +85,7 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel { statements = new ArrayList(); displayLimit = dp.getDisplayLimit(); + rangeDatatypeURI = dp.getRangeDatatypeURI(); // If the property is populated, get the data property statements via a sparql query if (populatedDataPropertyList.contains(dp)) { log.debug("Getting data for populated data property " + getUri()); @@ -161,6 +163,11 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel { return displayLimit; } +// @Override + public String getRangeDatatypeURI() { + return rangeDatatypeURI; + } + public ConfigError checkQuery(String queryString) { if (StringUtils.isBlank(queryString)) { return ConfigError.NO_SELECT_QUERY; diff --git a/webapp/web/css/individual/individual.css b/webapp/web/css/individual/individual.css index 39e91f2c1..2eafc11d3 100644 --- a/webapp/web/css/individual/individual.css +++ b/webapp/web/css/individual/individual.css @@ -295,4 +295,8 @@ ul.tinyMCEDisc li, ol.tinyMCENumeric li { padding: 0 !important; margin-left: 30px; +} +img.invalidFormat { + padding-left:8px; + vertical-align:middle; } \ No newline at end of file diff --git a/webapp/web/i18n/all.properties b/webapp/web/i18n/all.properties index 2ad69da30..4c0ead6af 100644 --- a/webapp/web/i18n/all.properties +++ b/webapp/web/i18n/all.properties @@ -899,4 +899,14 @@ faux_property_listing = Faux Property Listing faux_property_by_base = faux properties by base property faux_property_alpha = faux properties alphabetically -no_class_restrictions=There are no classes with a restriction on this property. \ No newline at end of file +no_class_restrictions=There are no classes with a restriction on this property. + +invalid_format=Invalid format +four_digit_year=Invalid entry. Please enter a 4-digit Year. +year_numeric=Invalid entry. The Year must be numeric. +year_month_day=Invalid entry. Please enter a Year, Month and Day. +minimum_ymd=Invalid entry. Please enter at least a Year, Month and Day. +minimum_hour=Invalid entry. Please specify at least an Hour. +year_month=Invalid entry. Please enter a Year and Month. +decimal_only=Invalid entry. A decimal point is allowed, but thousands-separators are not. +whole_number=Invalid entry. Enter a whole number with no decimal point or thousands-separators. diff --git a/webapp/web/templates/freemarker/body/partials/individual/propStatement-dataDefault.ftl b/webapp/web/templates/freemarker/body/partials/individual/propStatement-dataDefault.ftl index 9b66c5bc6..e9ba1eead 100644 --- a/webapp/web/templates/freemarker/body/partials/individual/propStatement-dataDefault.ftl +++ b/webapp/web/templates/freemarker/body/partials/individual/propStatement-dataDefault.ftl @@ -6,10 +6,14 @@ is also used to generate the property statement during a deletion. --> <#import "lib-datetime.ftl" as dt> -<@showStatement statement /> +<#if property.rangeDatatypeURI?? && property.rangeDatatypeURI?contains("#")> + <#assign datatype = property.rangeDatatypeURI?substring(property.rangeDatatypeURI?last_index_of("#")+1) /> + +<@showStatement statement datatype /> -<#macro showStatement statement> +<#macro showStatement statement datatype> <#assign theValue = statement.value /> + <#if theValue?contains("
    ") > <#assign theValue = theValue?replace("
      ","
        ") /> @@ -23,7 +27,11 @@ <#assign theValue = theValue + "T00:00:00" /> ${dt.formatXsdDateTimeLong(theValue, "yearMonthDayPrecision")} <#elseif theValue?matches("^([0-9]{4})-((0[1-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1]))(T|\\s)(([0-1][0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])")> - ${dt.formatXsdDateTimeLong(theValue, "yearMonthDayTimePrecision")} + <#if theValue?contains("T00:00:00") > + ${dt.formatXsdDateTimeLong(theValue, "yearMonthDayPrecision")} + <#else> + ${dt.formatXsdDateTimeLong(theValue, "yearMonthDayTimePrecision")} + <#elseif theValue?matches("^([0-9]{4})-(0[1-9]|1[012])")> <#assign theValue = theValue + "-01T00:00:00" /> ${dt.formatXsdDateTimeLong(theValue, "yearMonthPrecision")} @@ -31,6 +39,56 @@ <#assign theValue = "2000" + theValue?substring(1) + "-01T00:00:00" /> ${dt.formatXsdDateTimeLong(theValue, "monthPrecision")} <#else> - ${theValue} + ${theValue} <@validateFormat theValue datatype/> - \ No newline at end of file + +<#macro validateFormat value datatype > + <#if datatype?? > + <#switch datatype> + <#case "date"> + ${i18n().invalid_format} <#-- validated above --> + <#break> + <#case "dateTime"> +  ${i18n().invalid_format} <#-- validated above --> + <#break> + <#case "time"> + <#if !value?matches("(([0-1][0-9])|(2[0-3])):([0-5][0-9]):([0-5][0-9])") > +  ${i18n().invalid_format} + + <#break> + <#case "gYear"> + <#if !value?matches("^\\d{4}") > +  ${i18n().invalid_format} + + <#break> + <#case "gMonth"> +  ${i18n().invalid_format} <#-- validated above --> + <#break> + <#case "gYearMonth"> +  ${i18n().invalid_format} <#-- validated above --> + <#break> + <#case "float"> + <#if !value?matches("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?.") > +  ${i18n().invalid_format} + + <#break> + <#case "integer"> + <#if !value?matches("^-?\\d+$") > +  ${i18n().invalid_format} + + <#break> + <#case "int"> + <#if !value?matches("^-?\\d+$") > +  ${i18n().invalid_format} + + <#break> + <#case "boolean"> + <#if !value?matches("false") && !value?matches("true") > +  ${i18n().invalid_format} + + <#break> + <#default> + + + + diff --git a/webapp/web/templates/freemarker/edit/forms/defaultDataPropertyForm.ftl b/webapp/web/templates/freemarker/edit/forms/defaultDataPropertyForm.ftl index 64b7e2dde..04fe85670 100644 --- a/webapp/web/templates/freemarker/edit/forms/defaultDataPropertyForm.ftl +++ b/webapp/web/templates/freemarker/edit/forms/defaultDataPropertyForm.ftl @@ -87,6 +87,17 @@ <#include "defaultFormScripts.ftl"> diff --git a/webapp/web/templates/freemarker/edit/forms/js/defaultDataPropertyUtils.js b/webapp/web/templates/freemarker/edit/forms/js/defaultDataPropertyUtils.js index 15eac97cb..ab552fec2 100644 --- a/webapp/web/templates/freemarker/edit/forms/js/defaultDataPropertyUtils.js +++ b/webapp/web/templates/freemarker/edit/forms/js/defaultDataPropertyUtils.js @@ -17,6 +17,7 @@ var defaultDataPropertyUtils = { this.textArea = $('textarea.useTinyMce'); $.extend(this, datatype); + $.extend(this, i18nStrings); }, @@ -42,49 +43,104 @@ var defaultDataPropertyUtils = { } } else { - defaultDataPropertyUtils.createLiteralValue(); + return defaultDataPropertyUtils.createAndValidateLiteralValue(); } + return true; }); }, - createLiteralValue: function() { + createAndValidateLiteralValue: function() { var theType = datatype.substring(datatype.lastIndexOf("#") + 1); var temp = ""; - - switch (theType) { - case 'date': - temp = $('#dateTimeField-year').val() + "-" - + $('#dateTimeField-month').val() + "-" - + $('#dateTimeField-day').val(); - $('#literal').val(temp); - break; - case 'dateTime': - temp = $('#dateTimeField-year').val() + "-" - + $('#dateTimeField-month').val() + "-" - + $('#dateTimeField-day').val() + "T" - + $('#dateTimeField-hour').val() + ":" - + $('#dateTimeField-minute').val() + ":" - + $('#dateTimeField-second').val(); - $('#literal').val(temp); - break; - case 'time': - temp = $('#dateTimeField-hour').val() + ":" - + $('#dateTimeField-minute').val() + ":" - + $('#dateTimeField-second').val(); - $('#literal').val(temp); - break; - case 'gYear': - $('#literal').val($('#dateTimeField-year').val()); - break; - case 'gYearMonth': - temp = $('#dateTimeField-year').val() + "-" + $('#dateTimeField-month').val(); - $('#literal').val(temp); - break; - case 'gMonth': - temp = "--" + $('#dateTimeField-month').val() - $('input#literal').val(temp); - break; + if ( $('#literal').attr("type") == "hidden" ) { + if ( $('#dateTimeField-year').length ) { + if ( $('#dateTimeField-year').val().length < 4 ) { + alert(defaultDataPropertyUtils.four_digit_year); + return false; + } + var reg = /^\d+$/; + if ( !reg.test($('#dateTimeField-year').val()) ) { + alert(defaultDataPropertyUtils.year_numeric); + return false; + } + } + switch (theType) { + case 'date': + temp = $('#dateTimeField-year').val() + "-" + + $('#dateTimeField-month').val() + "-" + + $('#dateTimeField-day').val(); + if ( temp.indexOf("-") == 0 || temp.lastIndexOf("-") == (temp.length - 1) || temp.indexOf("--") > 0 ) { + alert(defaultDataPropertyUtils.year_month_day); + return false; + } + $('#literal').val(temp); + break; + case 'dateTime': + temp = $('#dateTimeField-year').val() + "-" + + $('#dateTimeField-month').val() + "-" + + $('#dateTimeField-day').val() + "T" + + ($('#dateTimeField-hour').val().length == 0 ? "00" : $('#dateTimeField-hour').val()) + ":" + + ($('#dateTimeField-minute').val().length == 0 ? "00" : $('#dateTimeField-minute').val()) + ":" + + ($('#dateTimeField-second').val().length == 0 ? "00" : $('#dateTimeField-second').val()); + if ( temp.indexOf("-") == 0 || temp.indexOf("-T") > 0 || temp.indexOf("--") > 0 ) { + alert(defaultDataPropertyUtils.minimum_ymd); + return false; + } + $('#literal').val(temp); + break; + case 'time': + temp = $('#dateTimeField-hour').val() + ":" + + ($('#dateTimeField-minute').val().length == 0 ? "00" : $('#dateTimeField-minute').val()) + ":" + + ($('#dateTimeField-second').val().length == 0 ? "00" : $('#dateTimeField-second').val()); + if ( temp.indexOf(":") == 0 ) { + alert(defaultDataPropertyUtils.minimum_hour); + return false; + } + $('#literal').val(temp); + break; + case 'gYear': + $('#literal').val($('#dateTimeField-year').val()); + break; + case 'gYearMonth': + temp = $('#dateTimeField-year').val() + "-" + $('#dateTimeField-month').val(); + if ( temp.indexOf("-") == 0 || temp.lastIndexOf("-") == (temp.length - 1) ) { + alert(defaultDataPropertyUtils.year_month); + return false; + } + $('#literal').val(temp); + break; + case 'gMonth': + if ( $('#dateTimeField-month').val().length == 2 ) { + temp = "--" + $('#dateTimeField-month').val() + $('input#literal').val(temp); + } + break; + } } + else if ( $('#literal').attr("type") == "text" ) { + switch (theType) { + case 'float': + if ( $('#literal').val().indexOf(",") > -1 ) { + alert(defaultDataPropertyUtils.decimal_only); + return false; + } + $('#literal').val($('#literal').val().replace(",","")); + break; + case 'integer': + if ( $('#literal').val().indexOf(".") > -1 || $('#literal').val().indexOf(",") > 0 ) { + alert(defaultDataPropertyUtils.whole_number); + return false; + } + break; + case 'int': + if ( $('#literal').val().indexOf(".") > -1 || $('#literal').val().indexOf(",") > 0 ) { + alert(defaultDataPropertyUtils.whole_number); + return false; + } + break; + } + } + return true; }, parseLiteralValue: function() {