diff --git a/src/app/core/common.service.js b/src/app/core/common.service.js index 1cf9334c..8783c062 100644 --- a/src/app/core/common.service.js +++ b/src/app/core/common.service.js @@ -14,12 +14,13 @@ angular * define common Javascript methods * @function commonService * @param {Object} $translate translation service Angular object + * @param {object} $rootScope Angular Object * @param {Object} events Angular object * @param {Object} $timeout promise with timeout Angular object * @param {Object} constants modules that contain all the constants * @return {Object} service common service */ -function commonService($translate, events, $timeout, constants) { +function commonService($translate, $rootScope, events, $timeout, constants) { const service = { parseJSON, @@ -36,7 +37,8 @@ function commonService($translate, events, $timeout, constants) { clickTab, clickSubTab, scrollToElement, - validServiceUrl + validServiceUrl, + validateForm }; let languages; @@ -106,6 +108,15 @@ function commonService($translate, events, $timeout, constants) { return Array.from(new Set(arr)); } + /** + * Validate form after the current language is set to the supplied value. + * @function validateForm + */ + function validateForm() { + // validate form + $rootScope.$broadcast('schemaFormValidate'); + } + /** * Sets the current language to the supplied value and broadcasts schema initialization event. * @function setLang diff --git a/src/app/ui/forms/form.service.js b/src/app/ui/forms/form.service.js index 0e2e674e..a3a9ff24 100644 --- a/src/app/ui/forms/form.service.js +++ b/src/app/ui/forms/form.service.js @@ -413,20 +413,51 @@ function formService($timeout, $rootScope, events, $mdDialog, $translate, keyNam * @function setErrorMessage * @param {Object} form form object to get value from * @param {String} message message to get from translation.csv - * @param {Array} variables variables to replace + * @param {Array} variables variables to replace * @return {String} mess the updated message */ function setErrorMessage(form, message, variables) { let mess = $translate.instant(message); - for (let variable of variables) { + let errorcode = form.error; + // if value is not a valid number, called by opacity if invalid value + if (errorcode === 'number') { + mess = $translate.instant('form.map.wkidnuminvalid'); + } // value is greater than maximum,called by opacity value positive 2 digits + if (errorcode === 'max') { + mess = $translate.instant('form.map.layeropacitymaxerr'); + } // value is les than minimim, called by opacity, value negative 2 digits + if (errorcode === 'min') { + mess = $translate.instant('form.map.extentdefxminerr'); + } // value is required wkid, extents, id, name, description, alt text + else if (errorcode === '302') { + mess = $translate.instant('form.map.requirederr'); + } // number less than minimum, called by expand factor, opacity, tolerance + else if ((errorcode === '101') && (message === '')) { + mess = $translate.instant('form.map.extentdefxminerr'); + } // number greater than maximum called by opacity - single value + else if ((errorcode === '103') && (message === '')) { + mess = $translate.instant('form.map.layeropacitymaxerr'); + } + else if (message !=='') { + mess = $translate.instant(message); + } + if (typeof variables !== 'undefined') { + for (let variable of variables) { // get the replacing value from form object - let replace = form; - variable.split('.').map(item => { replace = replace[item] }); + let replace = form; + variable.split('.').map(item => { replace = replace[item] }); - // replace value in the message - mess = mess.replace(`{${variable}}`, replace); + // replace value in the message + mess = mess.replace(`{${variable}}`, replace); + } } + else if (typeof variables === 'undefined') { + // replace values in message string if no parameters passed to replace them with + mess = mess.replace(/{.+?}/, ' '); + mess = mess.replace(/{.+?}/, ' '); + mess = mess.replace("( )", ' '); + } return mess; } diff --git a/src/app/ui/forms/map/map.directive.js b/src/app/ui/forms/map/map.directive.js index 4d514e9a..5eb33934 100644 --- a/src/app/ui/forms/map/map.directive.js +++ b/src/app/ui/forms/map/map.directive.js @@ -621,9 +621,9 @@ function Controller($scope, $translate, $timeout, // hidden read only field { 'key': 'tileSchemas[].id', 'readonly': true }, { 'key': 'tileSchemas[].name', 'onChange': debounceService.registerDebounce((model, item) => { self.formService.updateId(model, $scope, 'tileSchemas'); - self.formService.updateLinkValues($scope, [['tileSchemas', 'id'], ['tileSchemas', 'name']], 'tileId'); }, constants.debInput, false) }, + self.formService.updateLinkValues($scope, [['tileSchemas', 'id'], ['tileSchemas', 'name']], 'tileId'); }, constants.debInput, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { - 'key': 'tileSchemas[].extentSetId', + 'key': 'tileSchemas[].extentSetId', 'validationMessage': form => self.formService.setErrorMessage(form, '', ), 'type': 'dynamic-select', 'optionData': 'extentId', 'model': 'extentSetId', @@ -656,7 +656,7 @@ function Controller($scope, $translate, $timeout, { 'type': 'template', 'template': addButton('extentdefault', 'setExtent', 'av-setdefaultext-button'), 'setExtent': () => self.formService.setExtent('default', $scope.model.extentSets) }, { 'type': 'template', 'template': addButton('extentfull', 'setExtent', 'av-setfullext-button'), 'setExtent': () => self.formService.setExtent('full', $scope.model.extentSets) }, { 'type': 'template', 'template': addButton('extentmax', 'setExtent', 'av-setmaxext-button'), 'setExtent': () => self.formService.setExtent('maximum', $scope.model.extentSets) }, - { 'key': 'extentSets[].id', 'htmlClass': 'av-extentset-id', 'onChange': () => debounceService.registerDebounce(self.formService.updateLinkValues(scope, [['extentSets', 'id']], 'extentId'), constants.debInput, false) }, + { 'key': 'extentSets[].id', 'htmlClass': 'av-extentset-id', 'onChange': () => debounceService.registerDebounce(self.formService.updateLinkValues(scope, [['extentSets', 'id']], 'extentId'), constants.debInput, false), 'validationMessage': form => self.formService.setErrorMessage(form, 'form.map.requirederr', ) }, { 'type': 'section', 'htmlClass': 'row', 'items': [ { 'type': 'section', 'htmlClass': 'col-xs-2', 'items': [ { 'key': 'extentSets[].spatialReference.wkid', 'htmlClass': 'av-extentset-wkid', 'onChange': debounceService.registerDebounce(model => { @@ -667,7 +667,7 @@ function Controller($scope, $translate, $timeout, for (let btn of buttons) { btn[apply]('disabled', ''); } - }, constants.debInput, false) } + }, constants.debInput, false) , 'validationMessage': form => self.formService.setErrorMessage(form, '', ['viewValue', 'schema.minimum'] ) } ] } // Not use, // { 'type': 'section', 'htmlClass': 'col-xs-2', 'items': [ @@ -686,48 +686,48 @@ function Controller($scope, $translate, $timeout, { 'type': 'section', 'htmlClass': 'row', 'items': [ { 'key': 'extentSets[].default', 'items': [ { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].default.xmin' } + { 'key': 'extentSets[].default.xmin', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].default.ymin' } + { 'key': 'extentSets[].default.ymin', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].default.xmax' } + { 'key': 'extentSets[].default.xmax', 'validationMessage': form => self.formService.setErrorMessage(form, '', )} ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].default.ymax' } + { 'key': 'extentSets[].default.ymax', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] } ] } ] }, { 'type': 'section', 'htmlClass': 'row', 'items': [ { 'key': 'extentSets[].full', 'items': [ { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].full.xmin' } + { 'key': 'extentSets[].full.xmin' , 'validationMessage': form => self.formService.setErrorMessage(form, '', )} ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].full.ymin' } + { 'key': 'extentSets[].full.ymin', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].full.xmax' } + { 'key': 'extentSets[].full.xmax', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].full.ymax' } + { 'key': 'extentSets[].full.ymax' , 'validationMessage': form => self.formService.setErrorMessage(form, '', )} ] } ] } ] }, { 'type': 'section', 'htmlClass': 'row', 'items': [ { 'key': 'extentSets[].maximum', 'items': [ { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].maximum.xmin' } + { 'key': 'extentSets[].maximum.xmin', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].maximum.ymin' } + { 'key': 'extentSets[].maximum.ymin', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].maximum.xmax' } + { 'key': 'extentSets[].maximum.xmax', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] }, { 'type': 'section', 'htmlClass': 'col-xs-3', 'items': [ - { 'key': 'extentSets[].maximum.ymax' } + { 'key': 'extentSets[].maximum.ymax', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) } ] } ] } ] } @@ -743,7 +743,7 @@ function Controller($scope, $translate, $timeout, self.lodSets = lods.length; }, 'notitle': true, 'add': $translate.instant('button.add'), 'items': [ { 'key': 'lodSets[]', 'htmlClass': `av-lods-array`, 'items': [ - { 'key': 'lodSets[].id', 'onChange': () => debounceService.registerDebounce(self.formService.updateLinkValues($scope, [['lodSets', 'id']], 'lodId'), constants.debInput, false) }, + { 'key': 'lodSets[].id', 'onChange': () => debounceService.registerDebounce(self.formService.updateLinkValues($scope, [['lodSets', 'id']], 'lodId'), constants.debInput, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'type': 'template', 'template': addButton('setlods', 'setLods', 'av-setloads-button'), 'setLods': () => self.formService.setLods($scope.model.lodSets, self.formService.getActiveElemIndex('av-lods-array')) }, { 'type': 'fieldset', 'htmlClass': 'row', 'items': [ { 'key': 'lodSets[].lods', 'add': null, 'items': [ @@ -789,10 +789,10 @@ function Controller($scope, $translate, $timeout, { 'key': 'baseMaps[].name', 'targetLink': 'legend.0', 'targetParent': 'av-accordion-toggle', 'default': $translate.instant('form.map.basemap'), 'onChange': debounceService.registerDebounce((model, item) => { self.formService.copyValueToFormIndex(model, item); self.formService.updateId(model, $scope, 'baseMaps'); - self.formService.updateLinkValues($scope, [['baseMaps', 'id'], ['baseMaps', 'name']], 'initBaseId'); }, constants.debInput, false) }, - { 'key': 'baseMaps[].description' }, + self.formService.updateLinkValues($scope, [['baseMaps', 'id'], ['baseMaps', 'name']], 'initBaseId'); }, constants.debInput, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, + { 'key': 'baseMaps[].description', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'baseMaps[].typeSummary', 'htmlClass': 'av-form-advance hidden' }, - { 'key': 'baseMaps[].altText' }, + { 'key': 'baseMaps[].altText', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'baseMaps[].thumbnailUrl', 'htmlClass': 'av-form-advance hidden' }, { 'key': 'baseMaps[].tileSchemaId', @@ -807,10 +807,10 @@ function Controller($scope, $translate, $timeout, // remove with version 2.5 $timeout(() => { events.$broadcast(events.avVersionSet); }, 1000); }, 'items': [ - { 'key': 'baseMaps[].layers[].id', 'htmlClass': 'av-form-advance hidden' }, - { 'key': 'baseMaps[].layers[].layerType', 'htmlClass': 'av-form-advance hidden' }, - { 'key': 'baseMaps[].layers[].url' }, - { 'key': 'baseMaps[].layers[].opacity', 'htmlClass': 'av-opacity-input av-form-advance hidden av-version-dev av-version-dev-hide' } + { 'key': 'baseMaps[].layers[].id', 'htmlClass': 'av-form-advance hidden', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, + { 'key': 'baseMaps[].layers[].layerType', 'htmlClass': 'av-form-advance hidden' , 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, + { 'key': 'baseMaps[].layers[].url', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, + { 'key': 'baseMaps[].layers[].opacity', 'htmlClass': 'av-opacity-input av-form-advance hidden av-version-dev av-version-dev-hide', 'validationMessage': form => self.formService.setErrorMessage(form, '',['viewValue', 'schema.minimum', 'schema.maximum'] ) } ] }, { 'type': 'fieldset', 'htmlClass': 'av-form-advance hidden av-accordion-toggle av-collapse', 'title': $translate.instant('form.map.basemapattrib'), 'items': [ { 'key': 'baseMaps[].attribution', 'htmlClass': 'av-accordion-content', 'notitle': true, 'items': [ @@ -818,7 +818,7 @@ function Controller($scope, $translate, $timeout, // { 'key': 'baseMaps[].attribution.logo' } // To be brought back with version 2.5 since we want the new element altext (v2.4) to be hide with prod version (2.3) { 'key': 'baseMaps[].attribution.logo', 'items': [ - { 'key': 'baseMaps[].attribution.logo.enabled' }, + { 'key': 'baseMaps[].attribution.logo.enabled', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'baseMaps[].attribution.logo.value' }, { 'key': 'baseMaps[].attribution.logo.altText', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide' }, { 'key': 'baseMaps[].attribution.logo.link' } @@ -845,7 +845,7 @@ function Controller($scope, $translate, $timeout, { 'key': 'layers[].name', 'targetLink': 'legend.0', 'targetParent': 'av-accordion-toggle', 'default': $translate.instant('form.map.layer'), 'onChange': debounceService.registerDebounce((model, item) => { self.formService.copyValueToFormIndex(model, item); self.formService.updateId(model, $scope, 'layers', true); - self.formService.updateLinkValues($scope, [['layers', 'id']], 'initLayerId', 'avLayersIdUpdate'); }, constants.debInput, false) }, + self.formService.updateLinkValues($scope, [['layers', 'id']], 'initLayerId', 'avLayersIdUpdate'); }, constants.debInput, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'layers[].url', 'onChange': debounceService.registerDebounce(model => { // check if it is a feature layer. If so, set fields. For dynamic we set when index change if (!isNaN(parseInt(model.substring(model.lastIndexOf('/') + 1, model.length)))) { @@ -853,9 +853,9 @@ function Controller($scope, $translate, $timeout, const btn = $(document.activeElement).closest('.av-layer').find('.av-form-setfields button')[0]; $timeout(() => { angular.element(btn).triggerHandler('click'); }, 0); } - }, constants.delayUpdateColumns, false) }, - { 'key': 'layers[].refreshInterval', 'htmlClass': 'av-form-advance hidden' }, - { 'key': 'layers[].expectedResponseTime', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide' }, + }, constants.delayUpdateColumns, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, + { 'key': 'layers[].refreshInterval', 'htmlClass': 'av-form-advance hidden', 'validationMessage': form => self.formService.setErrorMessage(form, '', ['viewValue', 'schema.minimum', 'schema.maximum'] ) }, + { 'key': 'layers[].expectedResponseTime', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide', 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'layers[].metadataUrl', 'htmlClass': 'av-form-advance hidden' }, { 'key': 'layers[].catalogueUrl', 'htmlClass': 'av-form-advance hidden' }, // hidden read only field { 'key': 'layers[].layerType', 'readonly': true }, @@ -863,7 +863,7 @@ function Controller($scope, $translate, $timeout, { 'key': 'layers[].nameField', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide', 'condition': 'model.layers[arrayIndex].layerChoice === \'esriFeature\'' }, { 'key': 'layers[].tooltipField', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide', 'condition': 'model.layers[arrayIndex].layerChoice === \'esriFeature\'' }, { 'key': 'layers[].customRenderer', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide', 'condition': 'model.layers[arrayIndex].layerChoice === \'esriFeature\'' }, - { 'key': 'layers[].tolerance', 'htmlClass': 'av-form-advance hidden', 'condition': 'model.layers[arrayIndex].layerChoice === \'esriFeature\' || model.layers[arrayIndex].layerChoice === \'esriDynamic\'' }, + { 'key': 'layers[].tolerance', 'htmlClass': 'av-form-advance hidden', 'condition': 'model.layers[arrayIndex].layerChoice === \'esriFeature\' || model.layers[arrayIndex].layerChoice === \'esriDynamic\'', 'validationMessage': form => self.formService.setErrorMessage(form, '', ['viewValue', 'schema.minimum', 'schema.maximum'] ) }, { 'key': 'layers[].imageFormat', 'htmlClass': 'av-form-advance hidden', 'condition': `model.layers[arrayIndex].layerChoice === \'esriDynamic\'` }, { 'type': 'fieldset', 'htmlClass': 'av-form-advance hidden av-accordion-toggle av-collapse', 'title': $translate.instant('form.map.layerdetail'), 'items': [ { 'type': 'section', 'htmlClass': 'av-accordion-content', 'items': [ @@ -881,7 +881,7 @@ function Controller($scope, $translate, $timeout, // simulate click event to set fields const btn = $(document.activeElement).closest('.av-layerEntry').find('.av-form-setfields button')[0]; $timeout(() => { angular.element(btn).triggerHandler('click'); }, 0); - }, constants.delayUpdateColumns, false) }, + }, constants.delayUpdateColumns, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'layers[].layerEntries[].name' }, { 'key': 'layers[].layerEntries[].outfields', 'htmlClass': 'av-form-advance hidden' }, { 'key': 'layers[].layerEntries[].nameField', 'htmlClass': 'av-form-advance hidden av-version-dev av-version-dev-hide' }, @@ -898,7 +898,7 @@ function Controller($scope, $translate, $timeout, // fields with condition doesn't work inside nested array, it appears only in the first element. We will use condition on group and duplicate them { 'type': 'fieldset', 'htmlClass': 'av-accordion-toggle av-layerEntry', 'title': $translate.instant('form.map.layerentry'), 'items': [ { 'type': 'fieldset', 'htmlClass': 'av-accordion-content', 'items': [ - { 'key': 'layers[].layerEntries[].id', 'targetLink': 'legend.0', 'targetParent': 'av-accordion-toggle', 'default': $translate.instant('form.map.layerentry'), 'onChange': debounceService.registerDebounce(self.formService.copyValueToFormIndex, constants.debInput, false) }, + { 'key': 'layers[].layerEntries[].id', 'targetLink': 'legend.0', 'targetParent': 'av-accordion-toggle', 'default': $translate.instant('form.map.layerentry'), 'onChange': debounceService.registerDebounce(self.formService.copyValueToFormIndex, constants.debInput, false), 'validationMessage': form => self.formService.setErrorMessage(form, '', ) }, { 'key': 'layers[].layerEntries[].name' }, { 'key': 'layers[].layerEntries[].allStyles' }, { 'key': 'layers[].layerEntries[].currentStyle' }, @@ -992,7 +992,7 @@ function Controller($scope, $translate, $timeout, { 'type': 'help', 'helpvalue': '