diff --git a/client/css/icons/style.css b/client/css/icons/style.css index 90f70bd022f65b24335883a7fcdd899db7d42c7a..995a6b2a6d7272a2ba770be7f7a77f7e31dae74b 100644 --- a/client/css/icons/style.css +++ b/client/css/icons/style.css @@ -596,6 +596,9 @@ .icon-language1:before { content: "\e2a8"; } +.icon-vm4vmp:before { + content: "\e2a8"; +} .icon-layers:before { content: "\e1d3"; } diff --git a/client/javascript/app/directives/workspaceListDrtv.js b/client/javascript/app/directives/workspaceListDrtv.js index 6da6cf43c6439b60c045ff651c0bbfdd1ee3b9a2..f16ccb8e9b199c234322e0cf8aae1ad166428bf4 100755 --- a/client/javascript/app/directives/workspaceListDrtv.js +++ b/client/javascript/app/directives/workspaceListDrtv.js @@ -187,6 +187,9 @@ vitisApp.appWorkspaceListDrtv = function ($timeout, $rootScope, $templateRequest // Rafraîchit le formulaire. scope.$broadcast('$$rebind::refresh'); scope.$apply(); + // Rafraîchit les listes du formulaire. + var oFormScope = angular.element($('#' + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]).children()).scope(); + oFormScope['ctrl'].extractFormDefinitionInfos(); } } }); diff --git a/client/javascript/app/services/formSrvc.js b/client/javascript/app/services/formSrvc.js index ea6c95d42a8297b55bc48a2cf018081df3c214a1..0bae8fcd8b256b94e96e24373a1fe7581425f47c 100755 --- a/client/javascript/app/services/formSrvc.js +++ b/client/javascript/app/services/formSrvc.js @@ -51,44 +51,63 @@ vitisApp.formSrvc = function (envSrvc, propertiesSrvc, sessionSrvc, formReaderSe case "upload": case "file_wsdata": case "image_wsdata": - if (document.getElementById(aFormRowElementsList[ifieldIndex]["id"]) != null) { - var bContainFiles = true; - var oFiles = document.getElementById(aFormRowElementsList[ifieldIndex]["id"]).files; - if (goog.isDefAndNotNull(oFiles)) { - if (oFiles.length > 0) { - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"]] = oFiles[0]; - if (oFiles.length > 1) { - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"]] = oFiles; - } - if (goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]["width"]) && goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]["height"])) { - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"] + "_width"] = aFormRowElementsList[ifieldIndex]["width"]; - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"] + "_height"] = aFormRowElementsList[ifieldIndex]["height"]; + + var bContainFiles = false; + var oFiles = null; + if (document.getElementById(aFormRowElementsList[ifieldIndex]['id']) != null) { + bContainFiles = true; + oFiles = document.getElementById(aFormRowElementsList[ifieldIndex]['id']).files; + } else { + var oElemValue = aFormValues[aFormRowElementsList[ifieldIndex]['name']]; + if (goog.isArray(oElemValue)) { + if (goog.isDefAndNotNull(oElemValue[0])) { + if (goog.isDefAndNotNull(oElemValue[0]['name'])) { + oFiles = []; + for (var i = 0; i < oElemValue.length; i++) { + if (goog.isDefAndNotNull(oElemValue[i]['name'])) { + oFiles.push(oElemValue[i]); + } + } } - } else { - bContainFiles = false; + } + } + } + + if (goog.isDefAndNotNull(oFiles)) { + if (oFiles.length > 0) { + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name']] = oFiles[0]; + if (oFiles.length > 1) { + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name']] = oFiles; + } + if (goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]['width']) && goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]['height'])) { + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name'] + '_width'] = aFormRowElementsList[ifieldIndex]['width']; + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name'] + '_height'] = aFormRowElementsList[ifieldIndex]['height']; } } else { bContainFiles = false; } + } else { + bContainFiles = false; + } - if (!bContainFiles) { - var oElemValue = aFormValues[aFormRowElementsList[ifieldIndex]["name"]]; - if (goog.isDefAndNotNull(oElemValue)) { - if (goog.isDefAndNotNull(oElemValue['aFiles'])) { - if (goog.isDefAndNotNull(oElemValue['aFiles'][0])) { - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"]] = oElemValue['aFiles'][0]; - if (oElemValue['aFiles'].length > 1) { - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"]] = oElemValue['aFiles']; - } - if (goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]["width"]) && goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]["height"])) { - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"] + "_width"] = aFormRowElementsList[ifieldIndex]["width"]; - oFormKeysValues[aFormRowElementsList[ifieldIndex]["name"] + "_height"] = aFormRowElementsList[ifieldIndex]["height"]; - } + if (!bContainFiles) { + var oElemValue = aFormValues[aFormRowElementsList[ifieldIndex]['name']]; + if (goog.isDefAndNotNull(oElemValue)) { + if (goog.isDefAndNotNull(oElemValue['aFiles'])) { + if (goog.isDefAndNotNull(oElemValue['aFiles'][0])) { + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name']] = oElemValue['aFiles'][0]; + if (oElemValue['aFiles'].length > 1) { + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name']] = oElemValue['aFiles']; + } + if (goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]['width']) && goog.isDefAndNotNull(aFormRowElementsList[ifieldIndex]['height'])) { + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name'] + '_width'] = aFormRowElementsList[ifieldIndex]['width']; + oFormKeysValues[aFormRowElementsList[ifieldIndex]['name'] + '_height'] = aFormRowElementsList[ifieldIndex]['height']; } } } } } + break; // Si double liste : valeurs séparé par un champ. case "double_select": @@ -149,6 +168,15 @@ vitisApp.formSrvc = function (envSrvc, propertiesSrvc, sessionSrvc, formReaderSe iRowIndex++; } + // vitis_deleted_files + if (goog.isDefAndNotNull(aFormValues['vitis_deleted_files'])) { + oFormKeysValues['vitis_deleted_files'] = JSON.stringify(aFormValues['vitis_deleted_files']); + } + // vitis_unchanged_files + if (goog.isDefAndNotNull(aFormValues['vitis_unchanged_files'])) { + oFormKeysValues['vitis_unchanged_files'] = JSON.stringify(aFormValues['vitis_unchanged_files']); + } + // Retourne un objet json ou un objet "FormData". if (bReturnJson === true) { oFormData = oFormKeysValues; @@ -161,14 +189,45 @@ vitisApp.formSrvc = function (envSrvc, propertiesSrvc, sessionSrvc, formReaderSe } } else { // Sauve les clés et valeurs dans un objet "FormData". - oFormData = new FormData(); - var aFormKeys = Object.keys(oFormKeysValues); - var i = 0; - while (i < aFormKeys.length) { - oFormData.append(aFormKeys[i], oFormKeysValues[aFormKeys[i]]); - i++; + oFormData = this['getFormDataFromValues'](oFormKeysValues); + } + + return oFormData; + }, + "getFormDataFromValues": function (oValues) { + + var oFormData = new FormData(); + + for (var key in oValues) { + + var bIsMultipleFiles = false; + if (goog.isObject(oValues[key])) { + if (goog.isDefAndNotNull(oValues[key].length)) { + bIsMultipleFiles = true + } + } + + // Fichiers multiples + if (bIsMultipleFiles) { + for (var i = 0; i < oValues[key].length; i++) { + if (oValues[key][i]._modified !== false) { + // Ajoute les fichiers + if (goog.isDefAndNotNull(oValues[key][i]['name'])) { + oFormData.append(key + '[]', oValues[key][i], oValues[key][i]['name']); + } else { + oFormData.append(key + '[]', oValues[key][i]); + } + } + } + } + // Fichier simple + else { + if (oValues[key]._modified !== false) { + oFormData.append(key, oValues[key]); + } } } + return oFormData; }, /** diff --git a/client/javascript/externs/formReader/component/file_picker/file_picker.css b/client/javascript/externs/formReader/component/file_picker/file_picker.css new file mode 100644 index 0000000000000000000000000000000000000000..14bac1a02f071760a18454cc26398d549791570d --- /dev/null +++ b/client/javascript/externs/formReader/component/file_picker/file_picker.css @@ -0,0 +1,128 @@ +.file_picker .preview-images-zone { + width: 100%; + border: 1px solid #ddd; + min-height: 90px; + padding: 5px 5px 0px 5px; + position: relative; + overflow:auto; +} +.file_picker .preview-images-zone > .preview-image-small { + height: 90px !important; + width: 90px !important; +} +.file_picker .preview-images-zone > .preview-image { + height: 185px; + width: 185px; + position: relative; + margin-right: 5px; + float: left; + margin-bottom: 5px; +} +.file_picker .preview-images-zone > .preview-image > .image-zone { + width: 100%; + height: 100%; +} +.file_picker .preview-images-zone > .preview-image > .image-add { + text-align: center; + font-size: 30px; + padding-top: calc(50% - 20px); +} +.file_picker .preview-images-zone > .preview-image > .image-zone > img { + width: 100%; + height: 100%; +} +.file_picker .preview-images-zone > .preview-image > .tools-edit-image { + position: absolute; + z-index: 100; + color: #fff; + bottom: 0; + width: 100%; + text-align: center; + margin-bottom: calc(50% - 20px); + display: none; +} +.file_picker .preview-images-zone > .preview-image > .tools-edit-image > a > .icon-zoom-in{ + font-size: 22px; +} +.file_picker .preview-images-zone > .preview-image > .image-cancel { + font-size: 18px; + position: absolute; + top: 0; + right: 0; + font-weight: bold; + margin-right: 10px; + cursor: pointer; + display: none; + z-index: 100; +} +.file_picker .preview-documents-zone > .preview-document > .document-cancel { + font-weight: bold; + margin-left: 15px; + cursor: pointer; + display: none; +} +.file_picker .preview-image:hover > .image-add, +.file_picker .preview-image:hover > .image-zone { + cursor: pointer; + opacity: .5; +} +.preview-image:hover > .tools-edit-image, +.file_picker .preview-image:hover > .image-cancel { + display: block !important; +} +.file_picker .preview-document:hover > .document-cancel { + display: inline !important; +} +.file_picker .preview-document:hover > .document-link { + text-decoration: underline; +} +.file_picker .ui-sortable-helper { + width: 90px !important; + height: 90px !important; +} +.modal-image-zone { + text-align: center; + max-height: 600px; + overflow-y: auto; +} +.modal-image-zone > img { + height: auto; + width: 100%; + max-width: 350px; + max-height: 350px; +} + +.file_picker .container { + padding-top: 50px; +} + +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-button-container { + padding-top: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container { + position: absolute; + top: 0px; + width: calc(100% - 30px); + height: calc(100% - 64px); +} +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container > .filepicker-image-zoom-modal-tools-prev, +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container > .filepicker-image-zoom-modal-tools-next { + position: absolute; + top: calc(50% - 35px); + font-size: 70px; + cursor: pointer; + -webkit-text-stroke: 1px white; + display: none; +} +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container:hover > .filepicker-image-zoom-modal-tools-prev, +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container:hover > .filepicker-image-zoom-modal-tools-next { + display: block; +} +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container > .filepicker-image-zoom-modal-tools-prev { + left: 0px; +} +.filepicker-image-zoom-modal .filepicker-image-zoom-modal-tools-container > .filepicker-image-zoom-modal-tools-next { + right: 0px; +} diff --git a/client/javascript/externs/formReader/component/file_picker/file_picker.html b/client/javascript/externs/formReader/component/file_picker/file_picker.html new file mode 100644 index 0000000000000000000000000000000000000000..4a3243d8b3ef881c2a5b1e69cd1309c8f4dec536 --- /dev/null +++ b/client/javascript/externs/formReader/component/file_picker/file_picker.html @@ -0,0 +1,73 @@ + +<link rel="stylesheet" ng-href="{{ folderUrl }}/file_picker.css"> + +<div class="file_picker"> + + <label for="{{:refresh:field.id}}" id="{{:refresh:field.id}}_label" class="control-label" data-translate="{{:refresh:field.label}}"></label> + + <!-- Visioneuse Images --> + <div ng-if="field.type === 'image_wsdata'" + ng-show="aPreviewImages.length > 0" + class="preview-images-zone"> + <div ng-repeat="image in aPreviewImages" + ng-class="{'preview-image-small' : aPreviewImages.length !== 1}" + class="preview-image preview-show-{{$index}}"> + <div class="image-cancel" data-no="{{$index}}" ng-if="!field.displayOnly" ng-click="removeFile(image)"> + <span class="icon-trash"></span> + </div> + <div class="image-zone"><img ng-src="{{image.src}}"></div> + <div class="tools-edit-image"> + <a href="javascript:void(0)" + data-no="{{$index}}" + class="btn btn-light btn-edit-image" + ng-click="showImageModal(image)"> + <span class="icon-zoom-in"></span> + </a> + </div> + </div> + </div> + + <!-- Visioneuse documents --> + <div ng-if="field.type === 'file_wsdata'" class="preview-documents-zone"> + <div ng-repeat="document in aPreviewDocuments" + class="preview-document preview-show-{{$index}}"> + <a class="document-link" href="javascript:void(0)" ng-click="downloadDocument(document)">{{document.name}}</a> + <span class="document-cancel" data-no="{{$index}}" ng-click="removeFile(document)"><span class="icon-trash"></span></span> + </div> + </div> + + <!-- Fichiers à envoyer --> + <div class="input-group input-file-xxs" ng-if="!field.displayOnly" ng-click="searchNewFile()"> + <div tabindex="500" class="form-control file-caption kv-fileinput-caption"> + <div ng-show="aFiles.length > 0" class="file-caption-name" title="7 fichiers sélectionné(s)"><span class="glyphicon glyphicon-file kv-caption-icon"></span> {{aFiles.length}} fichier(s)</div> + <div ng-show="aFiles.length == 0" class="file-caption-name" title="7 fichiers sélectionné(s)"><span class="glyphicon glyphicon-file kv-caption-icon"></span> Aucun fichier disponible</div> + </div> + <div class="input-group-btn"> + <div tabindex="500" class="btn btn-primary btn-file"><i class="glyphicon glyphicon-folder-open"></i> Ajouter…</div> + </div> + </div> + + <!-- Bouton caché input --> + <div class="hide" + ng-if="!field.displayOnly"> + <!-- Simple --> + <input ng-if="!field.multiple" + type="file" + id="{{:refresh:field.id}}_hidden" + class="file" + name="{{:refresh:field.name}}" + class="form-control" + ng-attr-accept="{{ field.type === 'image_wsdata' ? 'image/*' : (field.formats.length > 0 ? getFormatsRestrict() : '*') }}" + ng-required="field.required"> + <!-- Multiple --> + <input ng-if="field.multiple" + type="file" + id="{{:refresh:field.id}}_hidden" + class="file" + name="{{:refresh:field.name}}" + class="form-control" + ng-attr-accept="{{ field.type === 'image_wsdata' ? 'image/*' : (field.formats.length > 0 ? getFormatsRestrict() : '*') }}" + ng-required="field.required" multiple> + </div> + +</div> diff --git a/client/javascript/externs/formReader/component/file_picker/file_picker.js b/client/javascript/externs/formReader/component/file_picker/file_picker.js new file mode 100644 index 0000000000000000000000000000000000000000..6ae3324962dfceca6e2d9012e0c5959ed05771af --- /dev/null +++ b/client/javascript/externs/formReader/component/file_picker/file_picker.js @@ -0,0 +1,723 @@ +/* global goog, ol, nsVitisComponent, vitisApp, formReader, bootbox */ + +/** + * @author: Anthony Borghi, Armand Bahi + * @Description: Fichier contenant la classe nsVitisComponent.Map + * Permet d'instancier un composant OpenLayers3 + */ + +'use strict'; + +goog.provide('nsVitisComponent.FilePicker'); + +goog.require('formReader'); +goog.require('nsVitisComponent.Map'); + +/** + * FilePicker Directive + * @param {type} $timeout + * @returns {nsVitisComponent.FilePickerDirective} + * @ngInject + */ +nsVitisComponent.FilePickerDirective = function ($timeout, $translate, propertiesSrvc, formReaderService, $log, $q) { + return { + restrict: 'A', + scope: { + 'field': '=appField', + 'oFormDefinition': '=appFormDef', + 'sFormDefinitionName': '=appFormDefName', + 'oFormValues': '=appFormVal' + }, + controllerAs: 'ctrl', + templateUrl: window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '') + "/" + sessionStorage["appEnv"] + '/javascript/externs/formReader/component/file_picker/file_picker.html', + link: function (scope, element, attributes, controller, transcludeFn) { + $log.log("formReader.FilePickerDirective.link"); + + var fileInputLoaded = false; + + /** + * URL vers le dossier fliepicker + */ + scope['folderUrl'] = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '') + "/" + sessionStorage["appEnv"] + '/javascript/externs/formReader/component/file_picker'; + + /** + * Fichiers à envoyer + */ + scope['aFiles'] = []; + + /** + * Fichiers à supprimer + */ + scope['aDeletedFiles'] = []; + + /** + * Liste des URL des images à afficher + */ + scope['aPreviewImages'] = []; + + /** + * Liste des URL des documents à afficher + */ + scope['aPreviewDocuments'] = []; + + /** + * Initialise le composant + */ + scope['initComponent'] = function() { + $log.log("formReader.FilePickerDirective.initComponent"); + + // Réinitialise les variables + scope['resetFileInput'](); + + // Initialise l'élément bootstrap fileInput + scope['initBootstrapFileInputs']().then(function(oInput) { + + // Écoute les changements pour afficher les images dans la liste + if (!fileInputLoaded) { + $(oInput).change(function(e){ + + // Vide la liste quand on est pas en mode multiple + if (scope['field']['multiple'] !== true) { + scope['aFiles'] = []; + } + + // Ajoute les fichiers + scope['addFiles'](e); + + // Affichage des images/documents dans l'espace de prévisualisation + scope['initPreview'](); + + // Set la nouvelle valeur de l'attibut + setTimeout(function () { + oInput[0]['files_vitis'] = scope['aFiles']; + + // Sauvegarde les fichiers sur oFormValues + scope['saveFiles'](); + }); + }); + } + + // Affiche les images présentes sur le serveur + var aAvaliableFiles = scope["oFormValues"][scope["sFormDefinitionName"]][scope['field'].name]; + + // Rétrocompatibilité API + if (goog.isString(aAvaliableFiles)) { + aAvaliableFiles = [aAvaliableFiles]; + } + + if (goog.isDefAndNotNull(aAvaliableFiles)) { + scope['addFilesFromURL'](aAvaliableFiles).then(function(){ + + // Initialise l'affichage des images + scope['initPreview'](); + + // Sauvegarde les fichiers sur oFormValues + scope['saveFiles'](); + }); + } + + fileInputLoaded = true; + }); + } + + /** + * Réinitialise les variables du composant + * + * @return {type} description + */ + scope['resetFileInput'] = function() { + $log.log("formReader.FilePickerDirective.resetFileInput"); + + scope.$applyAsync(function(){ + scope['aFiles'] = []; + scope['aPreviewImages'] = []; + scope['aPreviewDocuments'] = []; + scope['aDeletedFiles'] = []; + scope['initPreview'](); + }); + } + + /** + * Add the added files to scope.aFiles + * @param {type} event + */ + scope['addFiles'] = function(event) { + $log.log("formReader.FilePickerDirective.addFiles"); + + var files = event['target']['files']; + for (var i = 0; i < files.length; i++) { + if (scope['isFilePresent'](files[i])) { + console.error('file already present'); + } else { + scope['aFiles'].push(files[i]); + } + } + } + + /** + * Lit les images à partir de leur URL + * @param {array} aAvaliableFiles tableau d'URL + * @return {promise} + */ + scope['addFilesFromURL'] = function(aAvaliableFiles) { + $log.log("formReader.FilePickerDirective.addFilesFromURL"); + + var deferred = $q.defer(); + var iCounter = 0; + + if (goog.isArray(aAvaliableFiles)) { + + // Assure que le ajaxLoader soit activé pendant le chargement + for (var i = 0; i < 100; i++) { + setTimeout(function () { + if (iCounter < aAvaliableFiles.length) { + showAjaxLoader(); + } + }, i * 100); + } + + for (var i = 0; i < aAvaliableFiles.length; i++) { + + scope['downloadFileBlob'](aAvaliableFiles[i], true, 3).then( + function success(oBlob){ + scope['aFiles'].push(oBlob); + iCounter++; + if (iCounter === aAvaliableFiles.length) { + deferred.resolve(); + } + }, + function error(){ + iCounter++; + if (iCounter === aAvaliableFiles.length) { + deferred.resolve(); + } + }); + } + } + + return deferred.promise; + } + + /** + * Télécharge le blob d'un fichier depuis son URL + * + * @param {string} sFileUrl URL du fichier + * @param {number|undefined} iRetry Nombre de fois à retenter en cas de problème + * @param {boolean|undefined} bThumbnail True pour télécharger la thumbnail en priorité + * @return {promise} fonction prenant le blob en paramètre + */ + scope['downloadFileBlob'] = function(sFileUrl, bThumbnail, iRetry) { + $log.log("formReader.FilePickerDirective.downloadFileBlob " + iRetry); + + var deferred = $q.defer(); + var bThumbnail = goog.isDefAndNotNull(bThumbnail) ? bThumbnail : false; + var oParams = { + 'type': scope['field']['type'] === 'image_wsdata' ? 'image' : 'document', + 'thumbnail' : bThumbnail === true ? true : false + }; + + if (goog.isString(sFileUrl)) { + ajaxRequest({ + 'method': 'GET', + 'url': sFileUrl, + 'headers': { + 'Accept': 'application/x-vm-json' + }, + 'params': oParams, + 'ajaxLoader': true, + 'responseType': 'blob', + 'success': function(response) { + if (goog.isDefAndNotNull(response['data'])) { + + var oBlob = response['data']; + + // Trouve le nom du fichier + var sFileName = scope['findFileNameInHeaders'](response['headers']); + + if (scope['field']['type'] === 'image_wsdata') { + // Vérification du type + if(response['headers']['content-type'] === 'application/x-vm-json; charset=UTF-8'){ + if (bThumbnail === true) { + bThumbnail = false; + sFileName = null; + } + } + } + + if (goog.isDefAndNotNull(sFileName)) { + oBlob['name'] = sFileName; + oBlob._url = sFileUrl; + oBlob._modified = false; + oBlob._thumbnail = bThumbnail; + deferred.resolve(oBlob); + } else { + console.error('cannot get name from headers : ', response['headers']); + + // Retry + if (goog.isDefAndNotNull(iRetry)) { + if (iRetry > 0) { + iRetry--; + scope['downloadFileBlob'](sFileUrl, bThumbnail, iRetry).then( + function success(oBlob){ + deferred.resolve(oBlob); + }, + function error(){ + deferred.reject(); + } + ); + } else { + oBlob['name'] = sFileUrl.split('/')[sFileUrl.split('/').length - 1]; + oBlob._url = sFileUrl; + oBlob._modified = false; + oBlob._thumbnail = bThumbnail; + deferred.resolve(oBlob); + } + } + } + + } else { + deferred.reject(); + } + }, + 'error': function(response) { + deferred.reject(); + } + }); + } else { + setTimeout(function () { + deferred.reject(); + }); + } + + return deferred.promise; + } + + /** + * Récupère le nom du fichier depuis les headers + * + * @param {object} oHeaders Headers + * @return {string} Nom du fichier + */ + scope['findFileNameInHeaders'] = function(oHeaders) { + var sName; + + if (goog.isDefAndNotNull(oHeaders)) { + + var sContentDisp = oHeaders['content-disposition']; + + // IE + if (!goog.isDefAndNotNull(sContentDisp) && + goog.isDefAndNotNull(oHeaders['Content-disposition'])) { + sContentDisp = oHeaders['Content-disposition']; + } + + if (goog.isString(sContentDisp)) { + var aContentDisp = sContentDisp.split(';'); + for (var i = 0; i < aContentDisp.length; i++) { + if(aContentDisp[i].indexOf('filename=') !== -1){ + sName = aContentDisp[i].split('"')[1]; + } + } + } + } + + if (goog.isDefAndNotNull(sName)) { + sName = decodeURI(sName); + } + + return sName; + } + + /** + * Fonction pour télécharger les documents de type non image + * + * @param {object} oFile + */ + scope['downloadDocument'] = function(oFile) { + $log.log("formReader.FilePickerDirective.downloadDocument"); + + if (goog.isDefAndNotNull(oFile._url)) { + scope['downloadFileBlob'](oFile._url).then(function(oBlob){ + scope['downloadFile'](oFile, oBlob); + }); + } else { + scope['downloadFile'](oFile); + } + } + + /** + * Download the given file + * @param {object} oFile + * @param {object|undefined} oBlob + */ + scope['downloadFile'] = function(oFile, oBlob) { + $log.log("formReader.FilePickerDirective.downloadFile"); + + var sFileName = oFile['name']; + + if (!goog.isDefAndNotNull(oBlob)) { + // Trouve le fichier correspondant + for (var i = 0; i < scope['aFiles'].length; i++) { + if(scope['aFiles'][i]['name'] === oFile['name']){ + oBlob = scope['aFiles'][i]; + } + } + } + + // Télécharge le fichier + if (goog.isDefAndNotNull(oBlob)) { + + // IE + if (window.navigator['msSaveOrOpenBlob']) { + window.navigator['msSaveOrOpenBlob'](oBlob, sFileName); + } + // Others + else { + var a = document.createElement("a"); + var url = window.URL.createObjectURL(oBlob); + document.body.appendChild(a); + a.style = "display: none"; + a.href = url; + a.download = sFileName; + a.click(); + window.URL.revokeObjectURL(url); + } + } + } + + /** + * Initialise l'élément bootstrap fileInput + */ + scope['initBootstrapFileInputs'] = function() { + $log.log("formReader.FilePickerDirective.initBootstrapFileInputs"); + + var deferred = $q.defer(); + setTimeout(function () { + var oInput = $(element).find('#' + scope['field']['id'] + '_hidden'); + deferred.resolve(oInput); + }); + + return deferred.promise; + } + + /** + * Init the preview in scope.aPreviewImages or scope.aPreviewDocuments + */ + scope['initPreview'] = function() { + $log.log("formReader.FilePickerDirective.initPreview"); + + var sPreviewContainer = 'aPreviewDocuments'; + if (scope['field']['type'] === 'image_wsdata') { + sPreviewContainer = 'aPreviewImages'; + } + + // Vide les images qui ont étés supprimées de aFiles + var bIsPresent; + for (var i = scope[sPreviewContainer].length - 1; i >= 0; i--) { + bIsPresent = false; + for (var ii = 0; ii < scope['aFiles'].length; ii++) { + if (!bIsPresent) { + if(scope[sPreviewContainer][i]['name'] === scope['aFiles'][ii]['name']){ + bIsPresent = true; + } + } + } + if (!bIsPresent) { + scope[sPreviewContainer].splice(i, 1); + } + } + + // Ajoute les nouvelles images + var oFile; + for (var i = 0; i < scope['aFiles'].length; i++) { + bIsPresent = false; + oFile = scope['aFiles'][i]; + + if (scope['field']['type'] === 'image_wsdata') { + if (!oFile.type.match('image')) continue; + } + + // Vérifie que l'image ne soit pas déjà ajoutée + for (var ii = 0; ii < scope[sPreviewContainer].length; ii++) { + if(scope['aFiles'][i]['name'] === scope[sPreviewContainer][ii]['name']){ + bIsPresent = true; + } + } + + // Ajoute les nouvelles images + if (!bIsPresent) { + var picReader = new FileReader(); + picReader.addEventListener('load', angular.bind(this, function (oFile, event) { + var picFile = event.target; + scope.$applyAsync(function(){ + scope[sPreviewContainer].push({ + 'name': oFile['name'], + 'src': picFile['result'], + _url: oFile._url, + _thumbnail: oFile._thumbnail + }); + }); + }, oFile)); + picReader.readAsDataURL(oFile); + } + } + + // Rafraichit la vue + scope.$applyAsync(function(){ + scope[sPreviewContainer] = scope[sPreviewContainer]; + }); + } + + /** + * Test if a file is already present + * @param {object} oFile file to test + * @return {boolean} true if the file is already present + */ + scope['isFilePresent'] = function(oFile) { + $log.log("formReader.FilePickerDirective.isFilePresent"); + + var bIsFilePresent = false; + for (var i = 0; i < scope['aFiles'].length; i++) { + if (scope['aFiles'][i]['name'] === oFile['name']) { + bIsFilePresent = true; + } + } + return bIsFilePresent; + } + + /** + * Remove the given file + * @param {object} oImage + */ + scope['removeFile'] = function(oFile) { + $log.log("formReader.FilePickerDirective.removeFile"); + + bootbox['confirm']({ + 'message': "Supprimer <b>" + oFile['name'] + "</b> ?", + 'buttons': { + 'confirm': { + 'label': 'Oui', + 'className': 'btn-danger' + }, + 'cancel': { + 'label': 'Non', + 'className': 'btn-default' + } + }, + 'callback': function (result) { + if (result) { + + scope['aDeletedFiles'].push(oFile['name']); + + for (var i = 0; i < scope['aFiles'].length; i++) { + if(scope['aFiles'][i]['name'] === oFile['name']){ + scope['aFiles'].splice(i, 1); + } + } + + // Affichage des images + setTimeout(function () { + + // Initialise l'affichage des images + scope['initPreview'](); + + // Sauvegarde les fichiers sur oFormValues + scope['saveFiles'](); + }); + } + } + }); + } + + /** + * Show the finder to search no files to add + */ + scope['searchNewFile'] = function() { + $log.log("formReader.FilePickerDirective.searchNewFile"); + + var oInput = $(element).find('#' + scope['field']['id'] + '_hidden'); + $(oInput).click(); + } + + /** + * Show the given image on a modal + * @param {object} oImage + * @param {object|undefined} oBlob + */ + scope['showImageModal'] = function(oImage, oBlob) { + $log.log("formReader.FilePickerDirective.showImageModal"); + + var iImageIndex; + for (var i = 0; i < scope['aPreviewImages'].length; i++) { + if(scope['aPreviewImages'][i]['name'] === oImage['name']){ + iImageIndex = angular.copy(i); + } + } + + var domModalcontent = $('<div class="modal-image-zone"></div>'); + var domImage = $('<img src="' + oImage['src'] + '">'); + + // Boutons suivant/précédent + var domImageToolsContainer = $('<div class="filepicker-image-zoom-modal-tools-container"></div>'); + var domImageToolsPrev = $('<div class="filepicker-image-zoom-modal-tools-prev"><span class="icon-keyboard_arrow_left"></span></div>'); + var domImageToolsNext = $('<div class="filepicker-image-zoom-modal-tools-next"><span class="icon-keyboard_arrow_right"></span></div>'); + + // Bouton télécharger + var domDownloadButtonContainer = $('<div class="filepicker-image-zoom-modal-button-container"></div>'); + var domDownloadButton = $('<button type="button" class="btn btn-primary"><span class="glyphicon glyphicon-download-alt"></span></button>'); + + /** + * Téléchargement de l'image + */ + $(domDownloadButton).click(function(){ + scope['downloadDocument'](oImage); + }); + + /** + * Image suivante + */ + $(domImageToolsNext).click(function(){ + scope['showNextImageModal'](oImage, dialog); + }); + + /** + * Image précédente + */ + $(domImageToolsPrev).click(function(){ + scope['showNextImageModal'](oImage, dialog, true); + }); + + // Image + $(domModalcontent).append(domImage); + + // Boutons suivant/précédent + if (goog.isDefAndNotNull(iImageIndex)) { + if (iImageIndex > 0) { + $(domImageToolsContainer).append(domImageToolsPrev); + } + if (iImageIndex < scope['aPreviewImages'].length - 1) { + $(domImageToolsContainer).append(domImageToolsNext); + } + } + + // Bouton téléchargement + $(domDownloadButtonContainer).append(domDownloadButton); + + // Containers + $(domModalcontent).append(domDownloadButtonContainer); + $(domModalcontent).append(domImageToolsContainer); + + + var dialog = bootbox['dialog']({ + 'title': oImage['name'], + 'className': 'filepicker-image-zoom-modal', + 'animate': false, + 'message': domModalcontent + }); + } + + /** + * Affiche l'image suivante + * + * @param {object} oImage + * @param {object} oBootbox + * @param {boolean} bPrev true pour affiche l'ímage suivante + */ + scope['showNextImageModal'] = function(oImage, oBootbox, bPrev) { + $log.log("formReader.FilePickerDirective.showNextImageModal"); + + if (!goog.isDefAndNotNull(oImage)) { + console.error('oImage not defined or null'); + return 0; + } + + if (goog.isDefAndNotNull(oImage['name'])) { + + var iImageIndex; + for (var i = 0; i < scope['aPreviewImages'].length; i++) { + if(scope['aPreviewImages'][i]['name'] === oImage['name']){ + iImageIndex = angular.copy(i); + } + } + + if (goog.isDefAndNotNull(iImageIndex)) { + + var oNextImage; + if (bPrev === true) { + oNextImage = scope['aPreviewImages'][iImageIndex - 1]; + } else { + oNextImage = scope['aPreviewImages'][iImageIndex + 1]; + } + + if (goog.isDefAndNotNull(oNextImage)) { + if (goog.isDefAndNotNull(oNextImage['name']) && + goog.isDefAndNotNull(oNextImage['src'])) { + oBootbox['modal']('hide'); + scope['showImageModal'](oNextImage); + } + } + + } else { + console.error('iImageIndex not founded'); + } + } + + } + + /** + * Sauvegarde les fichiers sur oFormValues + */ + scope['saveFiles'] = function() { + $log.log("formReader.FilePickerDirective.saveFiles"); + + // Fichiers inchangés à ne pas re-envoyer + var aUnchangedFiles = []; + for (var i = 0; i < scope['aFiles'].length; i++) { + if (scope['aFiles'][i]._modified === false) { + aUnchangedFiles.push(scope['aFiles'][i]['name']); + } + } + if (!goog.isDefAndNotNull(scope['oFormValues'][scope['sFormDefinitionName']]['vitis_unchanged_files'])) { + scope['oFormValues'][scope['sFormDefinitionName']]['vitis_unchanged_files'] = {} + } + scope['oFormValues'][scope['sFormDefinitionName']]['vitis_unchanged_files'][scope['field'].name] = aUnchangedFiles; + + // Fichiers à supprimer + if (!goog.isDefAndNotNull(scope['oFormValues'][scope['sFormDefinitionName']]['vitis_deleted_files'])) { + scope['oFormValues'][scope['sFormDefinitionName']]['vitis_deleted_files'] = {} + } + scope['oFormValues'][scope['sFormDefinitionName']]['vitis_deleted_files'][scope['field'].name] = scope['aDeletedFiles']; + + // Fichiers à envoyer + scope['oFormValues'][scope['sFormDefinitionName']][scope['field'].name] = scope['aFiles']; + } + + /** + * Retourne les restrictions de type input=file + */ + scope['getFormatsRestrict'] = function() { + + var sRestrictedFormats; + var aImgExtencions = ['']; + + if (goog.isString(scope.field.formats)) { + + var aRestrictedFormats = []; + var aFormats = scope.field.formats.split('|'); + + for (var i = 0; i < aFormats.length; i++) { + aRestrictedFormats.push('.' + aFormats[i]); + } + + sRestrictedFormats = aRestrictedFormats.join(', '); + + } else { + sRestrictedFormats = scope.field.formats; + } + + return sRestrictedFormats; + } + } + }; +}; +formReader.module.directive('appFilePicker', nsVitisComponent.FilePickerDirective); diff --git a/client/javascript/externs/formReader/component/map.js b/client/javascript/externs/formReader/component/map.js index 0482db946269fcaebace4fb649834a3e949861c0..84e8ba3cc709ec0c973afeee8a915f6be0de8a41 100755 --- a/client/javascript/externs/formReader/component/map.js +++ b/client/javascript/externs/formReader/component/map.js @@ -117,6 +117,10 @@ nsVitisComponent.Map = function (opt_option) { * @private */ this.$log_ = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["$log"]); + /** + * @private + */ + this.$q_ = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["$q"]); var this_ = this; @@ -355,7 +359,31 @@ nsVitisComponent.Map = function (opt_option) { } } - /****************************************************Map*******************************/ + var hiddenFeatures = angular.copy($("#" + this.hiddenFieldId).val()); + + // Initialise la carte + this.initMap(options).then(function(){ + // Initialise l'étendue de la carte + this_.initExtent(options); + // Initialise le CSS de la carte + this_.initCSS(options); + // Initialise les features de la carte + this_.initFeatureOverlay(options, hiddenFeatures); + }); + + return this; +}; + +/** + * Initialise la carte + * + * @param {object} options + */ +nsVitisComponent.Map.prototype.initMap = function (options) { + this.$log_.info('nsVitisComponent.Map.initMap'); + + var deferred = this.$q_.defer(); + var this_ = this; this.MapObject = new ol.Map({ target: this_.Target, @@ -372,16 +400,54 @@ nsVitisComponent.Map = function (opt_option) { this.setExtent(options["center"]["extent"]); } - if (options["type"] === "vmap" && options["tree"]) { - this['aTree'] = this.loadTree(options["tree"]); + if (options["type"] === "vmap") { + if (options["tree"]) { + this['aTree'] = this.loadTree(options["tree"]); + } else if (options["map_id"]) { + this.getAjaxVmapMap(options["map_id"]).then(function(oMap){ + + // Set map + this_['aTree'] = this_.loadTree(oMap); + + // Set proj_ + this_.proj_ = this_.MapObject.getView().getProjection().getCode(); + + deferred.resolve(this_['aTree']); + }, + // Cas où carte non trouvée + function(){ + this_.MapObject.addLayer(new ol.layer.Tile({ + source: new ol.source.OSM() + })); + this_['aTree'] = [{ + 'service': options["type"], + 'layers': this_.Layers + }]; + setTimeout(function () { + deferred.resolve(this_['aTree']); + }); + }); + } } else { this['aTree'] = [{ - 'service': options["type"], - 'layers': this.Layers - }]; + 'service': options["type"], + 'layers': this.Layers + }]; + setTimeout(function () { + deferred.resolve(this_['aTree']); + }); } - /****************************************Extent***************************************/ + return deferred.promise; +} + +/** + * Initialise l'étendue de la carte + * + * @param {object} options + */ +nsVitisComponent.Map.prototype.initExtent = function (options) { + this.$log_.info('nsVitisComponent.Map.initExtent'); // Vérifie que l'étendue soit valable var projExtent = ol.proj.get(options["proj"]).getExtent(); @@ -393,20 +459,34 @@ nsVitisComponent.Map = function (opt_option) { console.error('map extent oversized'); this.MapObject.getView().fit(projExtent); } +} +/** + * Initialise lle CSS de la carte + * + * @param {object} options + */ +nsVitisComponent.Map.prototype.initCSS = function (options) { + this.$log_.info('nsVitisComponent.Map.initCSS'); - //****************************************CSS******************************************/ $(".ol-mouse-position").css("bottom", "8px"); $(".ol-mouse-position").css("top", "auto"); $(".ol-mouse-position").css("background", this.appColor); $(".ol-mouse-position").css("color", "#ffffff"); $(".ol-mouse-position").css("border-radius", "4px"); - $(".ol-scale-line").css("background", this.appColor); - $(".ol-current-projection-studio").css("background", this.appColor); +} + +/** + * Initialise les features de la carte + * + * @param {object} options + */ +nsVitisComponent.Map.prototype.initFeatureOverlay = function (options, hiddenFeatures) { + this.$log_.info('nsVitisComponent.Map.initFeatureOverlay'); - /****************************************Feature Overlay********************************/ + var this_ = this; options["draw_color"] = goog.isDef(options["draw_color"]) ? options["draw_color"] : "rgba(54,184,255,0.6)"; options["contour_color"] = goog.isDef(options["contour_color"]) ? options["contour_color"] : "rgba(0,0,0,0.4)"; @@ -464,40 +544,72 @@ nsVitisComponent.Map = function (opt_option) { source: this_.FeatureOverlay.getSource() }) - var hiddenFeatures = $("#" + this.hiddenFieldId).val(); + // Met en place les Features + this.setFeatures(hiddenFeatures); + + // Écrit les features dans le champ hidden + this.Features.on("change", function () { + setTimeout(function () { + this_.saveFeatures(); + this_.MapObject.dispatchEvent('moveend'); + }); + }); +} + +/** + * Set the map features + * + * @param {string} hiddenFeatures GeoJSON features + */ +nsVitisComponent.Map.prototype.setFeatures = function (hiddenFeatures) { + this.$log_.info('nsVitisComponent.Map.setFeatures'); + + // Vide les précédentes features + this.FeatureOverlay.getSource().forEachFeature(function(oFeature){ + this.FeatureOverlay.getSource().removeFeature(oFeature); + }, this); // Lit les features écrites dans le champ hidden if (goog.isDef(hiddenFeatures)) { if (!goog.string.isEmpty(hiddenFeatures) && hiddenFeatures !== "[object Object]") { - var aFeatures = this_.getFeaturesByString(hiddenFeatures); + var aFeatures = this.getFeaturesByString(hiddenFeatures); // Ajoute les features for (var i = 0; i < aFeatures.length; i++) { this.FeatureOverlay.getSource().addFeature(aFeatures[i]); } - var featuresExtent = this.FeatureOverlay.getSource().getExtent(); - this.MapObject.getView().fit(featuresExtent); - // En cas de simple point - if (aFeatures.length === 1) { - if (aFeatures[0].getGeometry().getType() === 'Point') { - this.MapObject.getView().setZoom(12); - } - } + // Zoom sur les features + this.zoomOnFeatures(); + + // Sauvegarde les features + this.saveFeatures(); } } +} - // Écrit les features dans le champ hidden - this.Features.on("change", function () { - setTimeout(function () { - this_.saveFeatures(); - this_.MapObject.dispatchEvent('moveend'); - }); - }); +/** + * Zoom sur les features de this.FeatureOverlay + */ +nsVitisComponent.Map.prototype.zoomOnFeatures = function () { + this.$log_.info('nsVitisComponent.Map.zoomOnFeatures'); - return this; -}; + var aFeatures = this.FeatureOverlay.getSource().getFeatures(); + var featuresExtent = this.FeatureOverlay.getSource().getExtent(); + + if (aFeatures.length > 0) { + + this.MapObject.getView().fit(featuresExtent); + + // En cas de simple point + if (aFeatures.length === 1) { + if (aFeatures[0].getGeometry().getType() === 'Point') { + this.MapObject.getView().setZoom(15); + } + } + } +} /** * Save the current features @@ -526,14 +638,20 @@ nsVitisComponent.Map.prototype.saveFeatures = function () { /** * Parse the string (GeoJSON, WKT) and return the features * @param {string} sFeatures + * @param {string} sFormat * @returns {Array} + * @export */ -nsVitisComponent.Map.prototype.getFeaturesByString = function (sFeatures) { +nsVitisComponent.Map.prototype.getFeaturesByString = function (sFeatures, sFormat) { this.$log_.info('nsVitisComponent.Map.getFeaturesByString'); var aFeatures = []; - if (this.outputFormat_ === 'wkt' || this.outputFormat_ === 'ewkt') { + if (!goog.isDefAndNotNull(sFormat)) { + sFormat = this.outputFormat_; + } + + if (sFormat === 'wkt' || sFormat === 'ewkt') { if (ol.isEWKTGeom(sFeatures)) { aFeatures = ol.getFeaturesFromEWKT(sFeatures, this.proj_); } else { @@ -547,7 +665,7 @@ nsVitisComponent.Map.prototype.getFeaturesByString = function (sFeatures) { console.error('cannot read the geometry on format wkt'); } } - } else if (this.outputFormat_ === 'geojson') { + } else if (sFormat === 'geojson') { try { aFeatures = this.geoJSONFormat.readFeatures(sFeatures, { dataProjection: this.baseProj_, @@ -1318,10 +1436,19 @@ nsVitisComponent.Map.prototype.activeInteraction = function (sInteraction, bForc this_.MapObject.addInteraction(this.snapInteraction_); }; +/** + * Get the formReaderScope + * @return {object} scope + */ nsVitisComponent.Map.prototype.getFormReaderScope_ = function (){ return angular.element(this.Target).scope(); } +/** + * Show the divide segment form + * @param {string} sFeature1 + * @param {string} sFeature2 + */ nsVitisComponent.Map.prototype.showDividedSegmentForm_ = function (sFeature1, sFeature2){ var this_ = this; @@ -1674,6 +1801,62 @@ nsVitisComponent.Map.prototype.removeFeature = function (oFeature) { this.Features.changed(); }; +/** + * Requête Ajax pour répupérer la définition d'une carte + * @param {string} sMapId map_id + * @return {object} map json + */ +nsVitisComponent.Map.prototype.getAjaxVmapMap = function (sMapId) { + + var deferred = this.$q_.defer(); + + if (!angular.isDefined(sMapId) || sMapId == '') { + console.error('map_id non valide'); + deferred.reject(); + } else { + + // Récupère la liste des rapports disponibles + ajaxRequest({ + 'method': 'GET', + 'url': this.$propertiesSrvc_["web_server_name"] + "/" + this.$propertiesSrvc_["services_alias"] + '/vmap/mapjsons/' + sMapId, + 'headers': { + 'Accept': 'application/x-vm-json' + }, + 'success': function (response) { + if (!goog.isDefAndNotNull(response['data'])) { + console.error('response.data undefined: ', response); + deferred.reject(); + return 0; + } + if (!goog.isDefAndNotNull(response['data']['data'])) { + console.error('Aucune carte disponible pour ' + sMapId); + deferred.reject(); + return 0; + } + if (!goog.isDefAndNotNull(response['data']['data'][0])) { + console.error('Aucune carte disponible pour ' + sMapId); + deferred.reject(); + return 0; + } + if (!goog.isDefAndNotNull(response['data']['data'][0]['children'])) { + console.error('Aucune carte disponible pour ' + sMapId); + deferred.reject(); + return 0; + } + if (!goog.isDefAndNotNull(response['data']['data'][0]['children'][1])) { + console.error('Aucune carte disponible pour ' + sMapId); + deferred.reject(); + return 0; + } + var oMap = response['data']['data'][0]; + deferred.resolve(oMap); + } + }); + } + + return deferred.promise; +} + /** * Load a Map.json to set layers and view of the map * @param {Object} tree Json tree to set the map (he's generated by Vmap) diff --git a/client/javascript/externs/formReader/component/map_workbench/map_workbench.js b/client/javascript/externs/formReader/component/map_workbench/map_workbench.js index 32ed53d696a53063fe3dd4020ed207461e8f235a..76b09c686bef4b3411631f3042d7f1c92ef4929c 100755 --- a/client/javascript/externs/formReader/component/map_workbench/map_workbench.js +++ b/client/javascript/externs/formReader/component/map_workbench/map_workbench.js @@ -365,7 +365,7 @@ nsVitisComponent.MapWorkbenchDirective = function ($timeout) { break; } }); - }); + }, 500); // Intancie le subform setTimeout(function () { @@ -745,7 +745,7 @@ nsVitisComponent.MapWorkbenchController.prototype.addFeature = function () { }); }); - // Désactive la possibilité d'ajouter des features + // Désactive la possibilité d'ajouter des features this.unactiveDrawInteractions_(); // Ajoute la/les nouvelle interaction @@ -811,7 +811,7 @@ nsVitisComponent.MapWorkbenchController.prototype.setStyleFromType_ = function ( // La chaine commence et se finit par {{ et }} ? if (oStyle[key1][key2].substr(0, 2) === '{{' && oStyle[key1][key2].substr(-2, 2) === '}}') { - // Le contenu des balises est un des champs du formulaire ? + // Le contenu des balises est un des champs du formulaire ? var sTag = oStyle[key1][key2].substr(2, oStyle[key1][key2].length - 4); if (goog.isDefAndNotNull(oAttributes[sTag])) { oStyle[key1][key2] = oAttributes[sTag]; @@ -887,4 +887,4 @@ nsVitisComponent.MapWorkbenchController.prototype.unactiveDrawInteractions_ = fu // this.$scope_['oMap']['setInteractions'](this.$scope_['field']['map_options']['interactions']); // } // } -}; \ No newline at end of file +}; diff --git a/client/javascript/externs/formReader/formReader.html b/client/javascript/externs/formReader/formReader.html index bec175d509bb7cc60b97fc19e66fa200af6d4c44..1640c7e5ca712e67e7df0335ddbfb45d697c7cea 100755 --- a/client/javascript/externs/formReader/formReader.html +++ b/client/javascript/externs/formReader/formReader.html @@ -368,25 +368,12 @@ </div> <!-- image ws_data --> <div ng-switch-when="image_wsdata"> - <label for="{{:refresh:field.id}}" id="{{:refresh:field.id}}_label" class="control-label" data-translate="{{:refresh:field.label}}"></label> - <!--Si l'image n'existe pas--> - <div ng-if="!field.displayOnly" ng-show="!oFormValues[sFormDefinitionName][field.name].length > 0"> - <input ng-if="!field.multiple" data-app-form-field-specific-params="" type="file" id="{{:refresh:field.id}}" class="file" name="{{:refresh:field.name}}" class="form-control" ng-required="field.required"> - <input ng-if="field.multiple" data-app-form-field-specific-params="" type="file" id="{{:refresh:field.id}}" class="file" name="{{:refresh:field.name}}" class="form-control" ng-required="field.required" multiple> - </div> - <!--Si l'image existe--> - <div ng-show="oFormValues[sFormDefinitionName][field.name].length > 0"> - <img id="{{:refresh:field.id}}_img" ng-src="{{oFormValues[sFormDefinitionName][field.name]}}" alt="image" class="img-responsive" width="{{field.display_width}}"/> - <div ng-if="!field.displayOnly"> - <div style="float: left; width:95%"> - <input ng-if="!field.multiple" data-app-form-field-specific-params="" type="file" id="{{:refresh:field.id}}" class="file" name="{{:refresh:field.name}}" class="form-control" ng-required="field.required"> - <input ng-if="field.multiple" data-app-form-field-specific-params="" type="file" id="{{:refresh:field.id}}" class="file" name="{{:refresh:field.name}}" class="form-control" ng-required="field.required" multiple> - </div> - <div style="float: right; width:5%"> - <a ng-href="{{oFormValues[sFormDefinitionName][field.name]}}" download class="btn btn-xs btn-success"><span class="glyphicon glyphicon-download"></span></a> - </div> - </div> - </div> + <div id="{{:refresh:field.id}}_image_picker" + data-app-file-picker="" + data-app-field="field" + data-app-form-def="oFormDefinition" + data-app-form-def-name="sFormDefinitionName" + data-app-form-val="oFormValues"></div> </div> <!-- Boutons --> <div ng-switch-when="button"> @@ -474,14 +461,12 @@ </div> <!-- File WS_Data --> <div ng-switch-when="file_wsdata"> - <label for="{{:refresh:field.id}}" id="{{:refresh:field.id}}_label" class="control-label" data-translate="{{:refresh:field.label}}"></label> - <div> - <a ng-href="{{oFormValues[sFormDefinitionName][field.name]}}" download>{{getLinkFileName(oFormValues[sFormDefinitionName][field.name])}}</a> - </div> - <div ng-if="!field.displayOnly && !field.disabled"> - <input ng-if="!field.multiple" data-app-form-field-specific-params="" type="file" id="{{:refresh:field.id}}" class="file" name="{{:refresh:field.name}}" class="form-control" ng-required="field.required"> - <input ng-if="field.multiple" data-app-form-field-specific-params="" type="file" id="{{:refresh:field.id}}" class="file" name="{{:refresh:field.name}}" class="form-control" ng-required="field.required" multiple> - </div> + <div id="{{:refresh:field.id}}_image_picker" + data-app-file-picker="" + data-app-field="field" + data-app-form-def="oFormDefinition" + data-app-form-def-name="sFormDefinitionName" + data-app-form-val="oFormValues"></div> </div> <!-- UI Grid --> <div ng-switch-when="ui_grid"> diff --git a/client/javascript/externs/formReader/formReaderDrtv.js b/client/javascript/externs/formReader/formReaderDrtv.js index d49d434d947387edf9a9a3012541f8a1ff759652..7764774d42b8e94d95a855d92806dc03b85b10bd 100644 --- a/client/javascript/externs/formReader/formReaderDrtv.js +++ b/client/javascript/externs/formReader/formReaderDrtv.js @@ -7,6 +7,7 @@ */ goog.provide('formReader.directive.formReaderDirective'); goog.require('nsVitisComponent.MapWorkbench'); +goog.require('nsVitisComponent.FilePicker'); goog.require('formReader'); /** @@ -717,6 +718,13 @@ formReader.formReaderDirective = function ($q, formReaderService, propertiesSrvc $(element).find(".file").each(function () { $(this)['fileinput']('clear'); }); + + setTimeout(function () { + $(element).find('[data-app-file-picker=""]').each(function(index, elem){ + var oFilePickerScope = angular.element($(elem).children()).scope(); + oFilePickerScope['initComponent'](); + }) + }, 500); }; /** @@ -899,88 +907,88 @@ formReader.appFormFieldSpecificParamsDrtv = function ($timeout, $translate, prop // Intégration du plugin "bootstrap-fileinput" dans tous les champ d'upload de fichiers. $(element)["fileinput"](oOptions); break; - case 'file_wsdata': - - // Évite la multiplication des champs depuis le studio - // quand on coche/décoche "Multiple documents" - if ($(element).parent().find('.file-input').length > 0) { - $(element).remove(); - break; - } - - // Si sélection d'un fichier à uploader : sauve ses paramètres. - element[0].addEventListener("change", function () { - var oFileList = { - "aFiles": this.files - }; - scope["oFormValues"][scope["sFormDefinitionName"]][element[0].name] = oFileList; - }, false); - // Extensions de fichiers autorisées. - if (typeof(scope["field"]["formats"]) != "undefined" && typeof(scope["field"]["extensions"]) == "undefined") - scope["field"]["extensions"] = scope["field"]["formats"]; - if (goog.isDefAndNotNull(scope["field"]["extensions"])) { - var aFilesExtensions = scope["field"]["extensions"].split('|'); - for (var iFileExtensionIndex in aFilesExtensions) - aFilesExtensions[iFileExtensionIndex] = "." + aFilesExtensions[iFileExtensionIndex]; - element[0].setAttribute("accept", aFilesExtensions.join(",")); - } - // Options - var oOptions = { - "showPreview": false, - "showRemove": false, - "showUpload": false, - }; - - if (typeof (scope["field"]["options"]) !== "undefined") - goog.object.extend(oOptions, scope["field"]["options"]); - - oOptions["mainClass"] = "input-file-" + scope["oFormDefinition"][scope["sFormDefinitionName"]]["input_size"]; - // Langue. - if (propertiesSrvc["language"] != "en") - oOptions["language"] = propertiesSrvc["language"]; - // Intégration du plugin "bootstrap-fileinput" dans tous les champ d'upload de fichiers. - $(element)["fileinput"](oOptions); - break; - case 'image_wsdata': - - // Évite la multiplication des champs depuis le studio - // quand on coche/décoche "Multiple documents" - if ($(element).parent().find('.file-input').length > 0) { - $(element).remove(); - break; - } - - if (!goog.isDefAndNotNull(scope["field"]["display_width"])) { - scope["field"]["display_width"] = "100%"; - } - // Si sélection d'un fichier à uploader : sauve ses paramètres. - element[0].addEventListener("change", function () { - var oFileList = { - "aFiles": this.files - }; - if (goog.isDefAndNotNull(scope["field"]["width"]) && goog.isDefAndNotNull(scope["field"]["height"])) { - oFileList["width"] = scope["field"]["width"]; - oFileList["height"] = scope["field"]["height"]; - } - - scope["oFormValues"][scope["sFormDefinitionName"]][element[0].name] = oFileList; - }, false); - // Passage de paramètres de définition du champ d'upload ? - var oOptions = { - "showPreview": false, - "showRemove": false, - "showUpload": false, - "allowedFileTypes": ['image'] - }; - oOptions["mainClass"] = "input-file-" + scope["oFormDefinition"][scope["sFormDefinitionName"]]["input_size"]; - - // Langue. - if (propertiesSrvc["language"] != "en") - oOptions["language"] = propertiesSrvc["language"]; - - // Intégration du plugin "bootstrap-fileinput" dans tous les champ d'upload de fichiers. - $(element)["fileinput"](oOptions); - break; + // case 'file_wsdata': + // + // // Évite la multiplication des champs depuis le studio + // // quand on coche/décoche "Multiple documents" + // if ($(element).parent().find('.file-input').length > 0) { + // $(element).remove(); + // break; + // } + // + // // Si sélection d'un fichier à uploader : sauve ses paramètres. + // element[0].addEventListener("change", function () { + // var oFileList = { + // "aFiles": this.files + // }; + // scope["oFormValues"][scope["sFormDefinitionName"]][element[0].name] = oFileList; + // }, false); + // // Extensions de fichiers autorisées. + // if (typeof(scope["field"]["formats"]) != "undefined" && typeof(scope["field"]["extensions"]) == "undefined") + // scope["field"]["extensions"] = scope["field"]["formats"]; + // if (goog.isDefAndNotNull(scope["field"]["extensions"])) { + // var aFilesExtensions = scope["field"]["extensions"].split('|'); + // for (var iFileExtensionIndex in aFilesExtensions) + // aFilesExtensions[iFileExtensionIndex] = "." + aFilesExtensions[iFileExtensionIndex]; + // element[0].setAttribute("accept", aFilesExtensions.join(",")); + // } + // // Options + // var oOptions = { + // "showPreview": false, + // "showRemove": false, + // "showUpload": false, + // }; + // + // if (typeof (scope["field"]["options"]) !== "undefined") + // goog.object.extend(oOptions, scope["field"]["options"]); + // + // oOptions["mainClass"] = "input-file-" + scope["oFormDefinition"][scope["sFormDefinitionName"]]["input_size"]; + // // Langue. + // if (propertiesSrvc["language"] != "en") + // oOptions["language"] = propertiesSrvc["language"]; + // // Intégration du plugin "bootstrap-fileinput" dans tous les champ d'upload de fichiers. + // $(element)["fileinput"](oOptions); + // break; + // case 'image_wsdata': + // + // // Évite la multiplication des champs depuis le studio + // // quand on coche/décoche "Multiple documents" + // if ($(element).parent().find('.file-input').length > 0) { + // $(element).remove(); + // break; + // } + // + // if (!goog.isDefAndNotNull(scope["field"]["display_width"])) { + // scope["field"]["display_width"] = "100%"; + // } + // // Si sélection d'un fichier à uploader : sauve ses paramètres. + // element[0].addEventListener("change", function () { + // var oFileList = { + // "aFiles": this.files + // }; + // if (goog.isDefAndNotNull(scope["field"]["width"]) && goog.isDefAndNotNull(scope["field"]["height"])) { + // oFileList["width"] = scope["field"]["width"]; + // oFileList["height"] = scope["field"]["height"]; + // } + // + // scope["oFormValues"][scope["sFormDefinitionName"]][element[0].name] = oFileList; + // }, false); + // // Passage de paramètres de définition du champ d'upload ? + // var oOptions = { + // "showPreview": false, + // "showRemove": false, + // "showUpload": false, + // "allowedFileTypes": ['image'] + // }; + // oOptions["mainClass"] = "input-file-" + scope["oFormDefinition"][scope["sFormDefinitionName"]]["input_size"]; + // + // // Langue. + // if (propertiesSrvc["language"] != "en") + // oOptions["language"] = propertiesSrvc["language"]; + // + // // Intégration du plugin "bootstrap-fileinput" dans tous les champ d'upload de fichiers. + // $(element)["fileinput"](oOptions); + // break; case 'email': scope["field"]["pattern"] = "^(([a-zA-Z]|[0-9])|([-]|[_]|[.]))+[@](([a-zA-Z]|[0-9])|([-]|[_]|[.])){2,63}[.](([a-zA-Z0-9]){2,63})+$"; // Utile dans le studio pour mémoriser la patern @@ -1375,7 +1383,9 @@ formReader.appFormFieldSpecificParamsDrtv = function ($timeout, $translate, prop scope['oFormValues'][scope['sFormDefinitionName']][scope['field']['name']] = 0; // Quand le slider change par l'action de l'utilisateur $(element).on('slide', function () { - scope['oFormValues'][scope['sFormDefinitionName']][scope['field']['name']] = $(element)['slider']('getValue'); + scope.$applyAsync(function(){ + scope['oFormValues'][scope['sFormDefinitionName']][scope['field']['name']] = $(element)['slider']('getValue'); + }); }); // Quand la valeur dans oFormValues du slider change scope.$watch('oFormValues.' + scope['sFormDefinitionName'] + '["' + scope['field']['name'] + '"]', function () { diff --git a/client/javascript/externs/mapJSON/MapJSON.js b/client/javascript/externs/mapJSON/MapJSON.js index 0d98c0487f4de44920d87be6070a95f0702f16da..1f631eb3536f9f76a3bd0b8a29c2a790df270b98 100755 --- a/client/javascript/externs/mapJSON/MapJSON.js +++ b/client/javascript/externs/mapJSON/MapJSON.js @@ -597,8 +597,11 @@ MapJSON.prototype.getLayerFromLayerDef_ = function (oMapDefinition, oLayerDef, o } if (goog.isDefAndNotNull(oLayerDef['is_filtered'])) { if (goog.isDefAndNotNull(oLayerDef['filter_form'])) { - if (goog.isString(oLayerDef['filter_form']) && oLayerDef['filter_form'].length !== 0) { - oLayerDef['filter_form'] = JSON.parse(oLayerDef['filter_form']); + if ((goog.isString(oLayerDef['filter_form']) && oLayerDef['filter_form'].length !== 0) || + goog.isObject(oLayerDef['filter_form'])) { + if (goog.isString(oLayerDef['filter_form'])) { + oLayerDef['filter_form'] = JSON.parse(oLayerDef['filter_form']); + } oLayerDef['filter_values'] = this.getFilterFormValues_(oLayerDef['filter_form']); layer.set('filter_form', oLayerDef['filter_form']); layer.set('filter_form_embedjs', oLayerDef['filter_form_embedjs']); diff --git a/client/modules/vitis/forms/user/user_vitis_user.json b/client/modules/vitis/forms/user/user_vitis_user.json index a5dacd7e5ccd46a776a8381a46c298adce8ab53f..6042656ced48e36bbf7436f68eb19e85f3acec83 100644 --- a/client/modules/vitis/forms/user/user_vitis_user.json +++ b/client/modules/vitis/forms/user/user_vitis_user.json @@ -139,7 +139,7 @@ "type": "radio", "name": "dataencrypt", "label": "FORM_DATAENCRYPT_USER_USER", - "nb_cols": 5, + "nb_cols": 3, "options": { "choices": [ { @@ -152,22 +152,31 @@ } ] }, - "default_value": false + "default_value": false, + "visible": "oProperties.enableEncryptionForUsers == true ? true : false" }, { "type": "hidden", "name": "encrypted_secretkey", "label": "", "required": false, - "nb_cols": 1 + "nb_cols": 1, + "visible": "oProperties.enableEncryptionForUsers == true ? true : false" }, { - "type": "text", + "type": "password", "name": "secretkey", "label": "FORM_SECRETKEY_USER_USER", "required": false, "pattern": "^[^\t\r\n]+$", - "nb_cols": 6 + "visible": "= {{dataencrypt}} === true && oProperties.enableEncryptionForUsers", + "tooltip": { + "title":"FORM_DATAENCRYPT_TOOLTIP_USER_TITLE", + "content":"FORM_DATAENCRYPT_TOOLTIP_USER_USER", + "container": "body", + "html": true + }, + "nb_cols": 8 } ] }, diff --git a/client/modules/vitis/forms/users/users_vitis_users.json b/client/modules/vitis/forms/users/users_vitis_users.json index 6e19d03d238b88849bb454975ecb262f80d9e886..39aa385fab9aadd53d3a3194c903da6c631e32e8 100644 --- a/client/modules/vitis/forms/users/users_vitis_users.json +++ b/client/modules/vitis/forms/users/users_vitis_users.json @@ -646,8 +646,7 @@ "parameters":{ "order_by":"billinggroup" } - }, - "default_value": -1 + } } ] }, diff --git a/client/modules/vitis/javascript/script_module.js b/client/modules/vitis/javascript/script_module.js index 716b8de908bc4dfb057afe25e838d92aa2463531..b15867c294f4eb7a6c96f0103c68d1c1af9c2b04 100644 --- a/client/modules/vitis/javascript/script_module.js +++ b/client/modules/vitis/javascript/script_module.js @@ -34,13 +34,11 @@ vitisApp.on('appMainDrtvLoaded', function () { // Cryptage de la clé secrète. var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]; oFormValues['encrypted_secretkey'] = ""; - if (oFormValues['dataencrypt'] === true && (goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) !== "0x")) { + if ((goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) !== "0x")) { var key = oFormValues['login']; var ciphertext = des(key, oFormValues['secretkey'], 1, 0); oFormValues['encrypted_secretkey'] = stringToHex(ciphertext); } - else if (oFormValues['dataencrypt'] === false) - oFormValues['secretkey'] = ""; // Changement de mot de passe ? var oPasswordInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password']"); var oPasswordConfirmInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password_confirm']"); @@ -101,7 +99,7 @@ vitisApp.on('appMainDrtvLoaded', function () { } } // Décryptage de la clé secrète. - if (oFormValues['dataencrypt'] === true && (goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) === "0x")) { + if ((goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) === "0x")) { var key = oFormValues['login']; // Décrypte et Suprimme les caractères "NULL". oFormValues['secretkey'] = des(key, hexToString(oFormValues['secretkey']), 0, 0).replace(/\x00/g, ""); @@ -284,7 +282,7 @@ vitisApp.on('appMainDrtvLoaded', function () { link: function (scope, element, attrs) { // 1er affichage ou tri de la liste : maj de la mise en forme. var clearObserver = attrs.$observe("appUserRoleColumn", function (value) { - // Si le champ est vide : supprime l'icône. + // Si le champ est vide : supprime l'icône. if (scope["row"]["entity"][scope["col"]["field"]] === null || scope["row"]["entity"][scope["col"]["field"]] === "") element[0].className = ""; else { @@ -700,35 +698,33 @@ vitisApp.on('appMainDrtvLoaded', function () { } } // Chargement de la clé secrète (le web service vitis/users ne doit pas la retourner). - if (oFormValues['dataencrypt'] === true) { - var oUrlParams = { - "schema": "s_vitis", - "table": "user", - "filter": { - "relation": "AND", - "operators": [{ - "column": "user_id", - "compare_operator": "=", - "value": oFormValues["user_id"] - }] - }, - "attributs": "secretkey" - }; - ajaxRequest({ - "method": "GET", - "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/genericquerys/user", - "params": oUrlParams, - "success": function (response) { - if (response["data"]["status"] != 0) { - // Décryptage de la clé secrète. - var oUserSecretKey = envSrvc["extractWebServiceData"]("genericquerys", response["data"])[0]; - if (goog.isDefAndNotNull(oUserSecretKey['secretkey']) && oUserSecretKey['secretkey'] != "" && oUserSecretKey['secretkey'].substr(0, 2) === "0x") { - oFormValues['secretkey'] = des (oFormValues['login'], hexToString(oUserSecretKey['secretkey']), 0, 0).replace(/\x00/g, ""); - } - } - } - }); - } + var oUrlParams = { + "schema": "s_vitis", + "table": "user", + "filter": { + "relation": "AND", + "operators": [{ + "column": "user_id", + "compare_operator": "=", + "value": oFormValues["user_id"] + }] + }, + "attributs": "secretkey" + }; + ajaxRequest({ + "method": "GET", + "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/genericquerys/user", + "params": oUrlParams, + "success": function (response) { + if (response["data"]["status"] != 0) { + // Décryptage de la clé secrète. + var oUserSecretKey = envSrvc["extractWebServiceData"]("genericquerys", response["data"])[0]; + if (goog.isDefAndNotNull(oUserSecretKey['secretkey']) && oUserSecretKey['secretkey'] != "" && oUserSecretKey['secretkey'].substr(0, 2) === "0x") { + oFormValues['secretkey'] = des (oFormValues['login'], hexToString(oUserSecretKey['secretkey']), 0, 0).replace(/\x00/g, ""); + } + } + } + }); }); }; @@ -1693,9 +1689,9 @@ vitisApp.on('appMainDrtvLoaded', function () { envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["rows"].push(aMethodFields); envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["tr_status_method"] = sMethod; - // l'event submit du formulaire sera appelé après cette fonction + // l'event submit du formulaire sera appelé après cette fonction }; - + /** * loadVitisExploitation function. * Chargement des sections du mode "exploitation". @@ -1709,7 +1705,7 @@ vitisApp.on('appMainDrtvLoaded', function () { // Passage en mode "Update" (pour afficher les sections). envSrvc["sMode"] = "update"; }; - + /** * initExploitationSharedDirectoryForm function. * Chargement de l'arborescence du répertoire partagé. @@ -1738,7 +1734,7 @@ vitisApp.on('appMainDrtvLoaded', function () { document.getElementById(oFormElementDefinition["id"] + "_treeview").style.height = document.getElementById("container_mode_exploitation").clientHeight - 221 + "px"; }); }; - + /** * refreshExploitationSharedDirectoryTreeview function. * Recharge les données du treeview du répertoire partagé. @@ -1761,7 +1757,7 @@ vitisApp.on('appMainDrtvLoaded', function () { document.getElementById(oFormElementDefinition["id"] + "_treeview").style.height = document.getElementById("container_mode_exploitation").parentElement.clientHeight - 221 + "px"; }); }; - + /** * loadExploitationSharedDirectoryTreeviewData function. * Charge les données du treeview du répertoire partagé. @@ -1788,7 +1784,7 @@ vitisApp.on('appMainDrtvLoaded', function () { }); return promise; }; - + /** * deleteSharedDirectoryFiles function. * Charge les données du treeview du répertoire partagé. @@ -1846,7 +1842,7 @@ vitisApp.on('appMainDrtvLoaded', function () { $rootScope["modalWindow"]("confirm", "", oOptions); } }; - + /** * createSharedDirectoryFolder function. * Création d'un répertoire dans le répertoire partagé. @@ -1897,7 +1893,7 @@ vitisApp.on('appMainDrtvLoaded', function () { $rootScope["modalWindow"]("dialog", "FORM_NO_DIRECTORY_EXPLOITATION_EXPLOITATION", {"className": "modal-danger"}); } }; - + /** * uploadSharedDirectoryFile function. * Upload d'un fichier dans le répertoire partagé. @@ -1952,4 +1948,4 @@ vitisApp.on('appMainDrtvLoaded', function () { $rootScope["modalWindow"]("dialog", "FORM_NO_FILE_EXPLOITATION_EXPLOITATION", {"className": "modal-danger"}); } }; -}); \ No newline at end of file +}); diff --git a/client/modules/vitis/lang/lang-en.json b/client/modules/vitis/lang/lang-en.json index dc98a487ebd474dde8d906521ce10687fd6b5a2f..b383a8afabdd1545ff87faa5fea21f8ec3df13d8 100644 --- a/client/modules/vitis/lang/lang-en.json +++ b/client/modules/vitis/lang/lang-en.json @@ -152,6 +152,8 @@ "FORM_PHONE_USER_USER" : "Telephone number (for SMS) in international E.164 format (+33 6 xx xx xx xx)", "FORM_TIMEZONE_ID_USER_USER" : "Time Zone", "FORM_FORMATDATE_ID_USER_USER" : "Date display format", + "FORM_DATAENCRYPT_TOOLTIP_USER_TITLE" : "Data encryption", + "FORM_DATAENCRYPT_TOOLTIP_USER_USER" : "The results produced by GTF will be encrypted using the \"AES 256\" algorithm, you will need a suitable tool to open these files. (ex: 7zip)", "": "", "USER_ROLE_TOOLTIP_TITLE_USERS_USER": "Description", "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER": "Administrator", diff --git a/client/modules/vitis/lang/lang-fr.json b/client/modules/vitis/lang/lang-fr.json index 9a882aa04bad00781d3d5434d5ee6f052a6bd3c3..7ed0e0437dbb44de208982f66b059dcdaf04ff1b 100644 --- a/client/modules/vitis/lang/lang-fr.json +++ b/client/modules/vitis/lang/lang-fr.json @@ -147,13 +147,15 @@ "FORM_INFORMATIONS_USER_USER": "Informations", "FORM_NEW_PASSWORD_USER_USER": "Nouveau mot de passe", "ACCOUNT_UNSUBSCRIBE" : "Désactiver votre compte", - "FORM_DATAENCRYPT_USER_USER" : "Cryptage des données", - "FORM_SECRETKEY_USER_USER" : "Clé secrète", + "FORM_DATAENCRYPT_USER_USER" : "Cryptage des documents générés", + "FORM_SECRETKEY_USER_USER" : "Clé de chiffrement", "FORM_BILLINGGROUP_ID_USERS_USER" : "Groupe de facturation", "FORM_ACCEPTNOTIFICATION_USER_USER" : "Acceptez-vous de recevoir des notifications par SMS ?", "FORM_PHONE_USER_USER" : "N° de téléphone (pour SMS) au format international E.164 (+33 6 xx xx xx xx)", "FORM_TIMEZONE_ID_USER_USER" : "Fuseau horaire", "FORM_FORMATDATE_ID_USER_USER" : "Format d'affichage des dates", + "FORM_DATAENCRYPT_TOOLTIP_USER_TITLE" : "Cryptage des données", + "FORM_DATAENCRYPT_TOOLTIP_USER_USER" : "Le cryptage des données entraîne le chiffrement avec l’algorithme AES-256 des jeux de données générés par GTF et téléchargeables. Si la clef de chiffrement personnelle n'est pas définie, une clé est générée aléatoirement à chaque traitement et envoyée à l'utilisateur avec le mail optionnel de notification. Cette clef ne peut pas être retrouvée et le message ne peut pas être renvoyé. Les utilisateurs doivent donc demander a être notifiés de la fin du traitement (fonctionnement par défaut) si leur clé de chiffrement n'est pas définie.", "": "", "USER_ROLE_TOOLTIP_TITLE_USERS_USER": "Description", "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER": "Administrateur", diff --git a/vas/rest/class/vmlib/files/Files_manager.class.inc b/vas/rest/class/vmlib/files/Files_manager.class.inc index a3f047854d7d7cf08b11267e193b2382b37f07e3..df8a89bcac44e25f15f3aa2dc9f91c906791b541 100644 --- a/vas/rest/class/vmlib/files/Files_manager.class.inc +++ b/vas/rest/class/vmlib/files/Files_manager.class.inc @@ -40,6 +40,7 @@ class Files_manager{ break; } } + /** *This method allow to upload a file on a server. *@file vmlib/phpUtil.inc @@ -48,7 +49,7 @@ class Files_manager{ *@param $sServerPath New path of the file. *@param $sMaxSize Maximal size of the file. *@param $aFileValues File structure generated by extractFileStruct. - *@return $sErrorMsg The error message or the final file path on success. + *@return $aReturn */ private function uploadFile($sNomObjet, $sFileType, $sServerPath, $sMaxSize, $aFileValues) { loadLang($this->sFolderLib, $this->oProperties["language"], $this->sFolderLib . "/"); @@ -63,10 +64,12 @@ class Files_manager{ ); $aForbiddenExtension = explode('|', str_replace("*.", "", $this->oProperties['forbidden_extension'])); $sTmpFile = ""; + $sFileName = ""; $sErrorMsg = ""; // si pas de aValues il y a eu une erreur pendant l'upload dans tmp du PUT if (!empty($aFileValues)){ $sTmpFile = $aFileValues['tmp_name']; + $sFileName = $aFileValues['name']; // Si l'utilisateur n'a indiqué aucun fichier à uploader, il ne se passe rien if ($sTmpFile == '') { @@ -133,12 +136,31 @@ class Files_manager{ } // si c'est une image avec les infos de taille final on resample - if($sFileType === "image" && (isset($aFileValues["width"]) && isset($aFileValues["height"]))){ - $sTmpFile = pictureResampler($sTmpFile, $aFileValues["width"], $aFileValues["height"], 0, 0, 0, 0, $sFileExtension); - if(!$sTmpFile){ - $bAllowUpload = false; - writeToErrorLog(ERROR_COPYING_FILE . $aFileValues['name'] . ON_SERVER_PHPUTIL . ', while resampling picture, ' . $sServerPath); - $sErrorMsg = ERROR_COPYING_FILE . $aFileValues['name'] . ON_SERVER_PHPUTIL . '.'; + if(isset($aFileValues["width"]) && isset($aFileValues["height"])){ + + // Si le fichier est une image + if(@is_array(getimagesize($sTmpFile))){ + + // Resample l'image + $sTmpFile = pictureResampler($sTmpFile, $aFileValues["width"], $aFileValues["height"], 0, 0, 0, 0, $sFileExtension); + + // Change l'extension de la destination + $sMinFileExtension = $this->extension($sTmpFile); + $aDestPathExt = explode('.', $sServerPath); + array_pop($aDestPathExt); + array_push($aDestPathExt, 'jpg'); + $sServerPath = implode('.', $aDestPathExt); + + $aFileExt = explode('.', $sFileName); + array_pop($aFileExt); + array_push($aFileExt, 'jpg'); + $sFileName = implode('.', $aFileExt); + + if(!$sTmpFile){ + $bAllowUpload = false; + writeToErrorLog(ERROR_COPYING_FILE . $aFileValues['name'] . ON_SERVER_PHPUTIL . ', while resampling picture, ' . $sServerPath); + $sErrorMsg = ERROR_COPYING_FILE . $aFileValues['name'] . ON_SERVER_PHPUTIL . '.'; + } } } @@ -158,7 +180,11 @@ class Files_manager{ $sErrorMsg = FILE_LABEL_PHPUTIL . "File" . ERROR_DOWNLOAD_SERVER . '.'; } - return $sErrorMsg; + return array( + 'message' => $sMessage, + 'file_name' => $sFileName, + 'file_path' => $sServerPath + ); } /** @@ -172,23 +198,37 @@ class Files_manager{ $aFileStruc = array(); if (!isset($aValues[$sField . "_name"])){ // Extract From Post $File Struct - $aFileStruc = array( - "name" => $_FILES[$sField]['name'], - "tmp_name" => $_FILES[$sField]['tmp_name'], - "error" => $_FILES[$sField]['error'], - "size" => $_FILES[$sField]['size'] - ); + if (!empty($_FILES[$sField]['name'])) { + $aFileStruc = array( + "name" => $_FILES[$sField]['name'], + "tmp_name" => $_FILES[$sField]['tmp_name'], + "error" => $_FILES[$sField]['error'], + "size" => $_FILES[$sField]['size'] + ); + if (!empty($_FILES[$sField]['width'])) { + $aFileStruc['width'] = $_FILES[$sField]['width']; + } + if (!empty($_FILES[$sField]['height'])) { + $aFileStruc['height'] = $_FILES[$sField]['height']; + } + } // Fichiers multiples - if (!empty($_FILES[$sField][0])) { - $aFileStruc = []; + if (!empty($_FILES[$sField][0]['name'])) { for ($i=0; $i < count($_FILES[$sField]); $i++) { - $aFileStruc[] = array( + $aTmpFileStruc = array( "name" => $_FILES[$sField][$i]['name'], "tmp_name" => $_FILES[$sField][$i]['tmp_name'], "error" => $_FILES[$sField][$i]['error'], "size" => $_FILES[$sField][$i]['size'] ); + if (!empty($_FILES[$sField][$i]['width'])) { + $aTmpFileStruc['width'] = $_FILES[$sField][$i]['width']; + } + if (!empty($_FILES[$sField]['height'])) { + $aTmpFileStruc['height'] = $_FILES[$sField][$i]['height']; + } + array_push($aFileStruc, $aTmpFileStruc); } } @@ -219,6 +259,70 @@ class Files_manager{ return $aFileStruc; } + /** + * Upload la miniature du fichier si il s'agit l'image ou retourne false + * + * @param {array} $aFileStruct Structure du fichier + * @param {string} $sDestPath Répertoire de destination + * @param {string} $sField Champ en base de données + * @param {string} $sMinDestPath Répertoire de destination du fichier min + * @param {integer} $iMaxSize Taille maximale du fichier + * @return {boolean} true en cas de succes + */ + private function uploadImageThumbnail($aFileStruct, $sDestPath, $sField, $sMinDestPath, $iMaxSize = -1) { + + $aImgSize = getimagesize($aFileStruct['tmp_name']); + + // Si image + if(@is_array($aImgSize)){ + + $aThumbnailFileStruct = $aFileStruct; + $aThumbnailFileStruct["width"] = 200; + $aThumbnailFileStruct["height"] = 200; + + if (is_int($this->oProperties['filesystem_thumbnails_max_width']) && + is_int($this->oProperties['filesystem_thumbnails_max_height'])) { + + $imgWidth = $aImgSize[0]; + $imgHeight = $aImgSize[1]; + + // Redimentionne la largeur en conservant le ratio + if ($imgWidth > $this->oProperties['filesystem_thumbnails_max_width']) { + $imgHeight = round($imgHeight * $this->oProperties['filesystem_thumbnails_max_width'] / $imgWidth); + $imgWidth = $this->oProperties['filesystem_thumbnails_max_width']; + } + + // Redimentionne la hauteur en conservant le ratio + if ($imgHeight > $this->oProperties['filesystem_thumbnails_max_height']) { + $imgWidth = round($imgWidth * $this->oProperties['filesystem_thumbnails_max_height'] / $imgHeight); + $imgHeight = $this->oProperties['filesystem_thumbnails_max_height']; + } + + $aThumbnailFileStruct["height"] = $imgHeight; + $aThumbnailFileStruct["width"] = $imgWidth; + } + + $aThumbnailFileStruct['tmp_name'] = $aThumbnailFileStruct['tmp_name'] . '.min'; + $aDestPathExt = explode('.', $sDestPath); + + $aDestPathExt = explode('.', $sDestPath); + + // Ajoute .min sur la destination + array_splice($aDestPathExt, -1, 0, 'min'); + $sMinDestPath = implode('.', $aDestPathExt); + + // Copie le fichier dans tmp + copy($aFileStruct['tmp_name'], $aThumbnailFileStruct['tmp_name']); + + // Upload le fichier .min.jpg + $this->uploadFile($sField, "image", $sMinDestPath, $iMaxSize, $aThumbnailFileStruct); + + return true; + } else { + return false; + } + } + /** *This method upload a file in ws_data. *@param $sModule Name of the module. @@ -230,11 +334,12 @@ class Files_manager{ *@param $iMaxSize Maximum size to upload on server. (set to -1 to disable this control) *@param $sFileTypeCtrl Type of the document. (set to all to disable this control) *@param $aFileStruct File structure to upload - *@return $sErrorMsg The error message. + *@param $bCreateThumbnailImage true to create automatically a thumnail image + *@return $aReturn */ - public function uploadInWsDataDir($sModule, $sObject, $mId, $sField, $sContainer = "", $iMaxSize = -1, $sFileTypeCtrl = "all", $aFileStruct = null){ + public function uploadInWsDataDir($sModule, $sObject, $mId, $sField, $sContainer = "", $iMaxSize = -1, $sFileTypeCtrl = "all", $aFileStruct = null, $bCreateThumbnail = false){ - // on controle les attributs pour éviter les mauvais placements + // controle les attributs pour éviter les mauvais placements if (strpos($sModule, '/') > -1){ writeToErrorLog("Module can't contain path : " . $sModule); return "Module can't contain path : " . $sModule; @@ -268,9 +373,9 @@ class Files_manager{ // Fichiers multiples if (!empty($aFileStruct[0]['name'])) { $aReturn = array(); + // Appel récursif for ($i=0; $i < count($aFileStruct); $i++) { - // Appel récursif - $aResult = $this->uploadInWsDataDir($sModule, $sObject, $mId, $sField, $sContainer, $iMaxSize, $sFileTypeCtrl, $aFileStruct[$i]); + $aResult = $this->uploadInWsDataDir($sModule, $sObject, $mId, $sField, $sContainer, $iMaxSize, $sFileTypeCtrl, $aFileStruct[$i], $bCreateThumbnail); $aReturn['message'][] = $aResult['message']; $aReturn['file_name'][] = $aResult['file_name']; $aReturn['file_path'][] = $aResult['file_path']; @@ -298,10 +403,12 @@ class Files_manager{ writeToErrorLog("This function doesn't accept relative reference : " . $sDestPath); return "This function doesn't accept relative reference : " . $sDestPath; } + // si taille max vaut -1 alors taille max = taille fichier + 1 if ($iMaxSize == -1){ $iMaxSize = $aFileStruct["size"] + 1; } + // création du fichier si besoin if (!is_dir($sDestDir)){ if(!mkdir($sDestDir, 0777, true)){ @@ -309,16 +416,25 @@ class Files_manager{ return 'ERROR_CREATING_DIRECTORY ' . $sDestDir; } } + + // Image miniature + $sMinDestPath = null; + if ($bCreateThumbnail === true && file_exists($aFileStruct['tmp_name'])) { + $this->uploadImageThumbnail($aFileStruct, $sDestPath, $sField, $sMinDestPath, $iMaxSize); + } + // Upload du fichier - $sMessage = $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + $aUploadReturn = $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); return array( - 'message' => $sMessage, - 'field_value' => $aFileStruct["name"], - 'file_name' => $aFileStruct["name"], - 'file_path' => $sDestPath + 'message' => $aUploadReturn['message'], + 'field_value' => $aUploadReturn["file_name"], + 'file_name' => $aUploadReturn["file_name"], + 'file_path' => $sDestPath, + 'file_min_path' => $sMinDestPath ); } + /** *This method upload a file in Public. *@file vmlib/phpUtil.inc @@ -368,8 +484,10 @@ class Files_manager{ } } // Upload du fichier - return $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + $aUploadReturn = $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + return $aUploadReturn['message']; } + /** *This method upload a file in Upload. *@file vmlib/phpUtil.inc @@ -419,8 +537,126 @@ class Files_manager{ } } // Upload du fichier - return $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + $aUploadReturn = $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + return $aUploadReturn['message']; } + + /** + *This method clean the objects ws_data dir . + *@param $sModule Name of the module. + *@param $sObject Name of the object. + *@param $mId Id of the current object. + *@param $sField field name (generally DB column name). + *@param $sContainer folder between $sObject and $mId + *@param $aFilesToDelete array of files names to delete, false to delete all the files + *@param $aExceptions array of files names to preserve, false to delete all the files + *@return true if the disrectory has benn cleaned + */ + public function cleanWsDataDir($sModule, $sObject, $mId, $sField, $sContainer = "", $aFilesToDelete = false, $aExceptions = false){ + + // controle les attributs pour éviter les mauvais placements + if (strpos($sModule, '/') > -1){ + writeToErrorLog("Module can't contain path : " . $sModule); + return "Module can't contain path : " . $sModule; + } + + if (strpos($sObject, "/") > -1){ + writeToErrorLog("Object can't contain path : " . $sObject); + return "Object can't contain path : " . $sObject; + } + + if (strpos($mId, "/") > -1){ + writeToErrorLog("Id can't contain path : " . $mId); + return "Id can't contain path : " . $mId; + } + + if (strpos($sField, "/") > -1){ + writeToErrorLog("Field can't contain path : " . $sField); + return "Field can't contain path : " . $sField; + } + + if (strpos($sContainer, "/") > -1){ + writeToErrorLog("Container can't contain path : " . $sContainer); + return "Container can't contain path : " . $sContainer; + } + + // Fichiers à supprimer et exceptions + $bIsFilesToDelete = false; + if ($aFilesToDelete !== false) { + $bIsFilesToDelete = true; + } else { + $bIsFilesToDelete = false; + $aFilesToDelete = []; + } + $bIsExceptions = false; + if ($aExceptions !== false) { + $bIsExceptions = true; + } else { + $bIsExceptions = false; + $aExceptions = []; + } + + // Génère la destination + $sDestDir = $this->oProperties['ws_data_dir'] . "/" . $sModule . "/" . $sObject; + + if(!empty($sContainer)){ + $sDestDir .= "/" . $sContainer; + } + if(!empty($mId)){ + $sDestDir .= "/" . $mId; + } + if(!empty($sField)){ + $sDestDir .= "/" . $sField; + } + + // Ajoute les miniatures aux exceptions + $aMinExceptions = []; + if ($bIsExceptions !== false) { + for ($i=0; $i < count($aExceptions); $i++) { + $aMinException = explode('.', $aExceptions[$i]); + array_pop($aMinException); + array_push($aMinException, 'min'); + array_push($aMinException, 'jpg'); + array_push($aMinExceptions, implode('.', $aMinException)); + } + for ($i=0; $i < count($aMinExceptions); $i++) { + array_push($aExceptions, $aMinExceptions[$i]); + } + } + + // Ajoute les miniatures aux fichiers à supprimer + $aMinFilesToDelete = []; + if ($bIsFilesToDelete !== false) { + for ($i=0; $i < count($aFilesToDelete); $i++) { + $aMinFileToDelete = explode('.', $aFilesToDelete[$i]); + array_pop($aMinFileToDelete); + array_push($aMinFileToDelete, 'min'); + array_push($aMinFileToDelete, 'jpg'); + array_push($aMinFilesToDelete, implode('.', $aMinFileToDelete)); + } + for ($i=0; $i < count($aMinFilesToDelete); $i++) { + array_push($aFilesToDelete, $aMinFilesToDelete[$i]); + } + } + + // création du fichier si besoin + if (is_dir($sDestDir)){ + $files = glob($sDestDir . '/*'); // get all file names + foreach($files as $file){ // iterate files + if(is_file($file)){ + if (in_array(basename($file), $aFilesToDelete) || $bIsFilesToDelete == false) { + if (!in_array(basename($file), $aExceptions) || $bIsExceptions == false) { + unlink($file); + } + } + } + } + return true; + } else { + return false; + } + } + /** *This method return the extension of a file. *@file vmlib/phpUtil.inc diff --git a/vas/rest/class/vmlib/files/Local_files.class.inc b/vas/rest/class/vmlib/files/Local_files.class.inc index d4543cab5de7f17fc297d92c932b57160b2beb45..ed9febd5c0bb42d10bbbdc78d70a241e8ce0af71 100644 --- a/vas/rest/class/vmlib/files/Local_files.class.inc +++ b/vas/rest/class/vmlib/files/Local_files.class.inc @@ -195,12 +195,12 @@ class Local_files extends Files_common implements Files{ */ public function getProxyPassUrl ($sFilePath){ $date = new DateTime(); - $sDataUrl = $this->oProperties['web_server_name'] . "/" . $this->oProperties['services_alias'] . "/vitis/file_downloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); + $sDataUrl = $this->oProperties['web_server_name'] . "/" . $this->oProperties['services_alias'] . "/vitis/FileDownloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); $sKey = str_replace($this->oProperties['ws_data_dir'], "ws_data" , $sFilePath); $sKey = str_replace($this->oProperties['dir_export'], "public" , $sKey); $sKey = str_replace($this->oProperties['upload_dir'], "upload" , $sKey); - $sKey = str_replace($properties['vas_home'] . '/shared', "shared" , $sKey); + $sKey = str_replace($this->oProperties['vas_home'] . '/shared', "shared" , $sKey); $sFileUrl = str_replace("[KEY]", urlencode($sKey), $sDataUrl); $sFileUrl = str_replace("[ETAG]", sha1(file_get_contents($sFilePath), false), $sFileUrl); diff --git a/vas/rest/class/vmlib/files/S3_files.class.inc b/vas/rest/class/vmlib/files/S3_files.class.inc index 47299130714a74817ba59aad8c112b6a2a93f444..fd16f7559686e386b894494771237494fc7a6c6f 100644 --- a/vas/rest/class/vmlib/files/S3_files.class.inc +++ b/vas/rest/class/vmlib/files/S3_files.class.inc @@ -445,7 +445,7 @@ class S3_files extends Files_common implements Files{ $sEtag = $this->getFileEtag($sFilePath); $date = new DateTime(); - $sDataUrl = $this->oProperties['web_server_name'] . "/" . $this->oProperties['services_alias'] . "/vitis/file_downloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); + $sDataUrl = $this->oProperties['web_server_name'] . "/" . $this->oProperties['services_alias'] . "/vitis/FileDownloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); $sKey = str_replace($this->oProperties['ws_data_dir'], "ws_data" , $sFilePath); $sKey = str_replace($this->oProperties['dir_export'], "public" , $sKey); diff --git a/vas/rest/class/vmlib/phpUtil.inc b/vas/rest/class/vmlib/phpUtil.inc index bac8eeaa4c6aa6df98f4dbe63d60bc5e1272b968..79b6523549cae25246eec3639a6e45b9a1b06194 100755 --- a/vas/rest/class/vmlib/phpUtil.inc +++ b/vas/rest/class/vmlib/phpUtil.inc @@ -552,7 +552,7 @@ function stripslashes_deep($aString) { $aFileName = explode("/", $sFilePath); $date = new DateTime(); - $sDataUrl = $properties['web_server_name'] . "/rest/vitis/file_downloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); + $sDataUrl = $properties['web_server_name'] . "/rest/vitis/FileDownloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); $sFileUrl = str_replace("[KEY]", str_replace($properties['ws_data_dir'], "ws_data" , $sFilePath), $sDataUrl); $sFileUrl = str_replace("[ETAG]", sha1(file_get_contents($sFilePath), false), $sFileUrl); @@ -602,7 +602,7 @@ function stripslashes_deep($aString) { )); $date = new DateTime(); - $sDataUrl = $properties['web_server_name'] . "/rest/vitis/file_downloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); + $sDataUrl = $properties['web_server_name'] . "/rest/vitis/FileDownloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); $aPath = explode("/", $sDirectoryPath); $aTree = array( "filename"=> end($aPath), diff --git a/vas/rest/conf/properties_server.inc b/vas/rest/conf/properties_server.inc index 494c13e697f984b236ba8e59c84bd894572e9cf1..9b34fdadd7ae222fac65ec5f264f1377555cd898 100644 --- a/vas/rest/conf/properties_server.inc +++ b/vas/rest/conf/properties_server.inc @@ -49,6 +49,8 @@ $properties["notifierAccessKeyAccount"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX $properties["notifierSecretKeyAccount"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // utilisation de s3 pour remplacer le système de Fichier $properties['filesystem'] = 'fs'; // s3 +$properties['filesystem_thumbnails_max_width'] = 350; // taille maximale des images .min.jpg +$properties['filesystem_thumbnails_max_height'] = 350; // taille maximale des images .min.jpg $properties['AWSCredentialsFilePath'] = ""; // .../.aws/credentials $properties["fileS3UploaderProfil"] = ""; $properties["fileS3UploaderBucket"] = ""; diff --git a/vas/rest/index.vhtml b/vas/rest/index.vhtml index 4e0e614d1bd2d65f7ec472036138c5efa867865a..44fcbfafc04970d93a27ba07d5f48bf0eae08435 100755 --- a/vas/rest/index.vhtml +++ b/vas/rest/index.vhtml @@ -1,4 +1,8 @@ <?php - header('Content-type: '.$aValues['output'].'; charset='.$properties["page_encoding"]); + ob_end_flush(); + $aCurrentHeaders = apache_response_headers(); + if(!array_key_exists('Content-Type-Set-By', $aCurrentHeaders)){ + header('Content-type: '.$aValues['output'].'; charset='.$properties["page_encoding"]); + } echo $sMessage; -?> \ No newline at end of file +?> diff --git a/vas/rest/ws/vitis/File_downloader.class.inc b/vas/rest/ws/vitis/FileDownloader.class.inc similarity index 69% rename from vas/rest/ws/vitis/File_downloader.class.inc rename to vas/rest/ws/vitis/FileDownloader.class.inc index fcc86a89c7145276ab0bf659a3a63bda15404e95..c2f2e825c66a8686562611730132344501797afa 100755 --- a/vas/rest/ws/vitis/File_downloader.class.inc +++ b/vas/rest/ws/vitis/FileDownloader.class.inc @@ -1,8 +1,8 @@ <?php /** - * \file File_downloader.class.inc - * \class File_downloader + * \file FileDownloader.class.inc + * \class FileDownloader * * \author Anthony Borghi <anthony.borghi@veremes.com>. * @@ -14,17 +14,18 @@ require_once 'Vitis.class.inc'; require_once ("aws_sdk/aws-autoloader.php"); require_once ("vmlib/phpUtil.inc"); +require_once "vmlib/files/Files_manager.class.inc"; -class File_downloader extends Vitis { +class FileDownloader extends Vitis { /** * @SWG\Definition( - * definition="/file_downloader", + * definition="/FileDownloader", * allOf={ - * @SWG\Schema(ref="#/definitions/file_downloader") + * @SWG\Schema(ref="#/definitions/FileDownloader") * } * ) * * @SWG\Tag( - * name="File_downloader", + * name="FileDownloader", * description="Download a file" * ) */ @@ -38,14 +39,14 @@ class File_downloader extends Vitis { * @param type $oConnection connection object */ function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) { - $this->aValues = $aValues; - $this->aProperties = $properties; - $this->oFilesManager = new Files_manager($properties); + $this->aValues = $aValues; + $this->aProperties = $properties; + $this->oFilesManager = new Files_manager($this->aProperties); } /** - * @SWG\Get(path="/file_downloader", - * tags={"File_downloader"}, + * @SWG\Get(path="/FileDownloader", + * tags={"FileDownloader"}, * summary="Get File Content", * description="Request to get File", * operationId="GET", @@ -74,7 +75,7 @@ class File_downloader extends Vitis { * @SWG\Response( * response=200, * description="Blob of the file", - * @SWG\Schema(ref="#/definitions/file_downloader") + * @SWG\Schema(ref="#/definitions/FileDownloader") * ) * ) */ @@ -103,15 +104,36 @@ class File_downloader extends Vitis { $sMessage = array("status" => 0, "sMessage" => "This directory can't be replaced by our replacer"); return json_encode($sMessage); } + if($this->oFilesManager->oFileInterface->file_exists($sPath)){ if($this->oFilesManager->oFileInterface->getFileEtag($sPath) === $this->aValues["eTag"]){ $sFileName = $this->oFilesManager->getFileName($sPath); $sContentType = $this->oFilesManager->oFileInterface->mime_content_type($sPath); - header("Content-Type: " . $sContentType); - if (in_array($sContentType, array("text/plain", 'application/pdf'))){ - header("Content-disposition: inline; filename=\"" . $sFileName . "\""); + + // Utilisation thumnail + if ($this->aValues["thumbnail"] === 'true') { + $sMinFilePath = $sPath; + $aMinFilePath = explode('.', $sMinFilePath); + array_pop($aMinFilePath); + array_push($aMinFilePath, 'min'); + array_push($aMinFilePath, 'jpg'); + $sMinFilePath = implode('.', $aMinFilePath); + if ($this->oFilesManager->oFileInterface->file_exists($sMinFilePath)) { + $sPath = $sMinFilePath; + } + } + + if ($this->aValues["thumbnail"] === 'true' && $this->aValues["type"] === 'document') { + header("Content-disposition: attachment; filename=\"" . rawurlencode($sFileName) . "\""); + return array("status" => 1, "fileName" => $sFileName); + } + + header("Content-Type: " . $sContentType .'; charset='. $this->aProperties["page_encoding"]); + header("Content-Type-Set-By: vitis/filedownloader"); + if (in_array($sContentType, array("text/plain", 'application/pdf', 'text/html', 'application/xml', 'application/json'))){ + header("Content-disposition: inline; filename=\"" . rawurlencode($sFileName) . "\""); } else { - header("Content-disposition: attachment; filename=\"" . $sFileName . "\""); + header("Content-disposition: attachment; filename=\"" . rawurlencode($sFileName) . "\""); } header('Content-Length: ' . $this->oFilesManager->oFileInterface->filesize($sPath)); if ($sContentType === "application/octet-stream") { diff --git a/vas/rest/ws/vitis/GenericQuerys.class.inc b/vas/rest/ws/vitis/GenericQuerys.class.inc index ae3ade89fea7b65a19aed0869f12b0357b914be6..7394491a162f775ffb0d7ec7731e124bbb5621c9 100644 --- a/vas/rest/ws/vitis/GenericQuerys.class.inc +++ b/vas/rest/ws/vitis/GenericQuerys.class.inc @@ -457,7 +457,6 @@ class GenericQuerys extends Vitis { $this->aValues['password'] = ''; } } - $this->oBd = new BD($this->aValues['login'], $this->aValues['password'], $this->aValues['database'], $this->aValues['server'], $this->aValues['port'], $this->aValues['sgbd'], $this->aValues['encoding']); if ($this->oBd->erreurRencontree) { writeToErrorLog(ERROR_CONNECTION_PROBLEM); @@ -525,6 +524,28 @@ class GenericQuerys extends Vitis { $this->oBd = new BD($this->aValues['login'], $this->aValues['password'], $sDatabase, $this->aValues['server'], $this->aValues['port'], $this->aValues['sgbd'], $this->aValues['encoding']); $sSql = $this->aSql[$this->aValues['sgbd']]['getSchemas']; $aSQLParams = array(); + //order by + if (!empty($this->aValues['order_by'])) { + $aOrder = explode("|", $this->aValues['order_by']); + foreach ($aOrder as $value) { + $sColumnKey = 'column_' . vitisUniqId(); + if (strpos($sSql, "ORDER BY") == FALSE) + $sSql .= " ORDER BY " . str_replace("=", " ", "[" . $sColumnKey . "]"); + else + $sSql .= ", " . str_replace("=", " ", "[" . $sColumnKey . "]"); + $aSQLParams[$sColumnKey] = array('value' => $value, 'type' => 'column_name'); + } + } + // sort_order + if (!empty($this->aValues['sort_order'])) { + switch (strtoupper($this->aValues['sort_order'])) { + case 'DESC': + $sSql .= " DESC"; + break; + default: + $sSql .= " ASC"; + } + } $oPDOresult = $this->oBd->executeWithParams($sSql, $aSQLParams); if ($this->oBd->enErreur()) { $oError = new VitisError(1, $this->oBd->getBDMessage()); diff --git a/vas/rest/ws/vitis/Users.class.inc b/vas/rest/ws/vitis/Users.class.inc index 56ec511d7a516ff8aba5dce2358a5c15e95c5444..dbd30e03ec789141d57883e48ff65d690be7ac3e 100755 --- a/vas/rest/ws/vitis/Users.class.inc +++ b/vas/rest/ws/vitis/Users.class.inc @@ -271,6 +271,10 @@ class Users extends Vitis { $aXmlRacineAttribute['status'] = 0; $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']); } else { + // suppression des valeur permettant d'activer l'encryption lors du post pour que l'administrateur ne puisse pas l'activer à travers l'API + unset($this->aValues['secretkey']); + unset($this->aValues['dataencrypt']); + unset($this->aValues['encrypted_secretkey']); // insert user in table $iId = $this->oConnection->oBd->insert($this->aProperties['schema_framework'], 'v_user', $this->aValues, $this->aProperties['schema_framework'] . '.seq_common', 'user_id'); if ($this->oConnection->oBd->enErreur()) { @@ -416,10 +420,12 @@ class Users extends Vitis { $sLogin = mb_strtolower($this->aValues["login"], 'UTF-8'); $sLogin = str_replace(array('à', 'â', 'ä', 'á', 'ã', 'å', 'î', 'ï', 'ì', 'í', 'ô', 'ö', 'ò', 'ó', 'õ', 'ø', 'ù', 'û', 'ü', 'ú', 'é', 'è', 'ê', 'ë', 'ç', 'ÿ', 'ñ'), array('a', 'a', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'e', 'e', 'e', 'e', 'c', 'y', 'n',), $sLogin); unset($this->aValues['login']); - if (!empty($this->aValues['encrypted_secretkey'])) - $this->aValues['secretkey'] = $this->aValues['encrypted_secretkey']; - else - $this->aValues['secretkey'] = null; + $this->aValues['secretkey'] = $this->aValues['encrypted_secretkey']; + if($this->aProperties['enableEncryptionForUsers'] !== true){ + unset($this->aValues['secretkey']); + unset($this->aValues['dataencrypt']); + unset($this->aValues['encrypted_secretkey']); + } $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'v_user', 'user_id'); $aXmlRacineAttribute['status'] = $aReturn['sStatus']; $sMessage = $aReturn['sMessage']; diff --git a/vas/rest/ws/vitis/Vitis.class.inc b/vas/rest/ws/vitis/Vitis.class.inc index 8a5c4da59651c0c09d1dd64ad8a91f9d2926a22a..0cfa33e45373d8146d7043148a37136fbb11ba1b 100644 --- a/vas/rest/ws/vitis/Vitis.class.inc +++ b/vas/rest/ws/vitis/Vitis.class.inc @@ -82,12 +82,14 @@ class Vitis extends DbClass { /** * Generic function which get fields of the object stored in the database - * @param type $sSchema - * @param type $sTable - * @param type $sIdField - * + * @param $sSchema + * @param $sTable + * @param $sIdField + * @param $sVitisObjectName Name of the vitis object, if provide and the object contains files stored in ws_data/vitis/$sVitisObjectName the values will be url formed + * @param $sVitisModuleName for upload files : module name + * @param $sVitisPathComplement for upload files : complement folder on put files (ws_data/vitis/.../documents/...) */ - function getFields($sSchema, $sTable, $sIdField) { + function getFields($sSchema, $sTable, $sIdField, $sVitisObjectName = "", $sVitisModuleName = "vitis", $sVitisPathComplement = "documents") { $this->aSqlParams = array(); @@ -139,12 +141,48 @@ class Vitis extends DbClass { $aData = array(); while ($aObject = $this->oConnection->oBd->ligneSuivante($oResult)) { foreach ($aObject as $sParamKey => $sParamValue) { - $aData[$sParamKey] = $sParamValue; } } + + // Vérifie si il y a des fichiers à renvoyer + if ($sVitisObjectName != "") { + + // check dans ws_data + $sDataDir = $this->aProperties['ws_data_dir'] . '/'.$sVitisModuleName.'/' . $sVitisObjectName; + if(!empty($sVitisPathComplement)){ + $sDataDir .= '/' . $sVitisPathComplement; + } + $sDataDir .= '/' . $aData[$sIdField]; + + if ($this->oFilesManager->oFileInterface->is_dir($sDataDir)) { + // Remplace le nom du fichier par son url + foreach ($aData as $key => $value) { + if ($this->oFilesManager->oFileInterface->is_dir($sDataDir . "/" . $key)) { + $aFiles = explode('|', $value); + if (count($aFiles) > 1) { + $aData[$key] = []; + for ($i=0; $i < count($aFiles); $i++) { + if (!empty($aFiles[$i])) { + if (file_exists($sDataDir . "/" . $key . "/" . $aFiles[$i])) { + array_push($aData[$key], $this->oFilesManager->oFileInterface->getProxyPassUrl($sDataDir . "/" . $key . "/" . $aFiles[$i])); + } + } + } + } else { + if (!empty($value)) { + if (file_exists($sDataDir . "/" . $key . "/" . $value)) { + $aData[$key] = $this->oFilesManager->oFileInterface->getProxyPassUrl($sDataDir . "/" . $key . "/" . $value); + } + } + } + } + } + } + } } } + return $aData; } @@ -206,7 +244,6 @@ class Vitis extends DbClass { return $aColumn; } - // fonction get générique à tous les objets /** * Generic function which get data of the objects in tables * @param $sSchema schema of the table @@ -214,6 +251,8 @@ class Vitis extends DbClass { * @param $sIdField name of the id field * @param $bOnlyReturnStatus * @param $sVitisObjectName Name of the vitis object, if provide and the object contains files stored in ws_data/vitis/$sVitisObjectName the values will be url formed + * @param $sVitisModuleName for upload files : module name + * @param $sVitisPathComplement for upload files : complement folder on put files (ws_data/vitis/.../documents/...) * @return the array of objects */ function genericGet($sSchema, $sTable, $sIdField, $bOnlyReturnStatus = false, $sVitisObjectName = "", $sVitisModuleName = "vitis", $sVitisPathComplement = "documents") { @@ -268,7 +307,23 @@ class Vitis extends DbClass { // Remplace le nom du fichier par son url foreach ($oObject->aFields as $key => $value) { if ($this->oFilesManager->oFileInterface->is_dir($sDataDir . "/" . $key)) { - $oObject->aFields[$key] = $this->oFilesManager->oFileInterface->getProxyPassUrl($sDataDir . "/" . $key . "/" . $value); + $aFiles = explode('|', $value); + if (count($aFiles) > 1) { + $oObject->aFields[$key] = []; + for ($i=0; $i < count($aFiles); $i++) { + if (!empty($aFiles[$i])) { + if (file_exists($sDataDir . "/" . $key . "/" . $aFiles[$i])) { + array_push($oObject->aFields[$key], $this->oFilesManager->oFileInterface->getProxyPassUrl($sDataDir . "/" . $key . "/" . $aFiles[$i])); + } + } + } + } else { + if (!empty($value)) { + if (file_exists($sDataDir . "/" . $key . "/" . $value)) { + $oObject->aFields[$key] = $this->oFilesManager->oFileInterface->getProxyPassUrl($sDataDir . "/" . $key . "/" . $value); + } + } + } } } } @@ -527,15 +582,18 @@ class Vitis extends DbClass { } /** - * - * @param type $sSchema schema containing the table - * @param type $sTable table to update - * @param type $sSequence used sequence to get the id - * @param type $sIdField id field name - * @param type $sPrivilegeParent privilege to do the insertion + * Generic function to insert data using $this->aValues + * @param $sSchema schema containing the table + * @param $sTable table to update + * @param $sSequence used sequence to get the id + * @param $sIdField id field name + * @param $aUploadFiles : uploaded files array (more info on function genericPutFiles) + * @param $sVitisObjectName for upload files : object name + * @param $sVitisModuleName for upload files : module name + * @param $sVitisPathComplement for upload files : complement folder on put files (ws_data/vitis/.../documents/...) * @return array containing the status and the message */ - function genericPost($sSchema, $sTable, $sSequence, $sIdField) { + function genericPost($sSchema, $sTable, $sSequence, $sIdField, $aUploadFiles = false, $sVitisObjectName = "", $sVitisModuleName = "vitis", $sVitisPathComplement = "documents") { if (isset($this->aValues['sEncoding'])) $sEncoding = $this->aValues['sEncoding']; else @@ -550,10 +608,10 @@ class Vitis extends DbClass { $aXmlRacineAttribute['status'] = 0; $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']); } else { - // verify if the user is framework_admin + // verify if the user privileges $this->getTablePrivileges($sSchema, $sTable); - //$aPrivileges = array_intersect($this->oConnection->aPrivileges, $this->aTablePrivileges) ; if (in_array('INSERT', $this->aTablePrivileges)) { + // insert user in table $iId = $this->oConnection->oBd->insert($sSchema, $sTable, $this->aValues, $sSequence, $sIdField); if ($this->oConnection->oBd->enErreur()) { @@ -564,6 +622,13 @@ class Vitis extends DbClass { $this->aFields[$sIdField] = $iId; $this->aValues['my_vitis_id'] = $iId; + // Upload de fichiers + if (($aUploadFiles !== false) && ($sVitisObjectName != "")) { + // Upload the files in $_FILES and $aUploadFiles + // Updade $this->aValues + $this->genericPut($sSchema, $sTable, $sIdField, $aUploadFiles, $sVitisObjectName, $sVitisModuleName, $sVitisPathComplement); + } + $aXmlRacineAttribute['status'] = 1; $sMessage = $this->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']); } @@ -578,14 +643,17 @@ class Vitis extends DbClass { } /** - * - * @param type $sSchema schema containing the table - * @param type $sTable table to update - * @param type $sIdField id field name - * @param type $sPrivilegeParent privilege to do the insertion + * Generic function to update data using $this->aValues + * @param $sSchema schema containing the table + * @param $sTable table to update + * @param $sIdField id field name + * @param $aUploadFiles : uploaded files array (more info on function genericPutFiles) + * @param $sVitisObjectName Name of the vitis object, if provide and the object contains files stored in ws_data/vitis/$sVitisObjectName the values will be url formed + * @param $sVitisModuleName for upload files : module name + * @param $sVitisPathComplement for upload files : complement folder on put files (ws_data/vitis/.../documents/...) * @return array containing the status and the message */ - function genericPut($sSchema, $sTable, $sIdField) { + function genericPut($sSchema, $sTable, $sIdField, $aUploadFiles = false, $sVitisObjectName = "", $sVitisModuleName = "vitis", $sVitisPathComplement = "documents") { if (isset($this->aValues['sEncoding'])) $sEncoding = $this->aValues['sEncoding']; else @@ -594,14 +662,26 @@ class Vitis extends DbClass { $sSourceEncoding = $this->aValues['sSourceEncoding']; else $sSourceEncoding = null; + + // Test connection if ($this->oConnection->oError != null) { $oError = $this->oConnection->oError; $aXmlRacineAttribute['status'] = 0; $sMessage = $oError->asDocument('', 'vitis', $sEncoding, True, $aXmlRacineAttribute, $sSourceEncoding, $this->aValues['output']); } else { + + // Test privilèges $this->getTablePrivileges($sSchema, $sTable); - //$aPrivileges = array_intersect($this->oConnection->aPrivileges, $this->aTablePrivileges) ; if (in_array('UPDATE', $this->aTablePrivileges)) { + + // Upload de fichiers + if (($aUploadFiles !== false) && ($sVitisObjectName != "")) { + // Upload the files in $_FILES and $aUploadFiles + // Updade $this->aValues + $this->genericPutFiles($aUploadFiles, $sVitisObjectName, $sVitisModuleName, $sVitisPathComplement); + } + + // Upload DBB $iId = $this->oConnection->oBd->update($sSchema, $sTable, $this->aValues, $sIdField, $this->aValues['my_vitis_id'], "text"); if ($this->oConnection->oBd->enErreur()) { $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage()); @@ -1431,5 +1511,109 @@ class Vitis extends DbClass { else return $sField; } + + /** + * Put the files present on $_FILES and aValues on the specified dir (ws_data, S3 ...) + * @param $aUploadFiles for upload files : two dimensional array of uploaded files columns or * to allow everyting + * ex : $aUploadFiles = [ + * 'image_col' => [ + * 'width' => 800 + * 'height' => 600 + * ], + * 'doc_col' => [] + * ] + * @param $sVitisObjectName for upload files : object name (ex : user) + * @param $sVitisModuleName for upload files : module name (ex : vitis) + * @param $sVitisPathComplement for upload files : complement folder on put files (ws_data/vitis/.../documents/...) + */ + function genericPutFiles($aUploadFiles, $sVitisObjectName, $sVitisModuleName = 'vitis', $sVitisPathComplement = 'documents') { + + if (empty($aUploadFiles) || + empty($sVitisObjectName) || + empty($sVitisModuleName) || + empty($sVitisPathComplement)) { + return false; + } + + // Noms des colonnes à uploader + $aUploadFilesCols = []; + if (is_array($aUploadFiles)) { + $aUploadFilesCols = array_keys($aUploadFiles); + } + + // Fichiers inchangés à ne pas supprimer + if (!empty($this->aValues['vitis_unchanged_files'])) { + $aUnchangedFiles = json_decode($this->aValues['vitis_unchanged_files'], true); + } + + // Fichiers à supprimer ? + if (!empty($this->aValues['vitis_deleted_files'])) { + $aDeletedFiles = json_decode($this->aValues['vitis_deleted_files'], true); + foreach ($aDeletedFiles as $sFieldName => $aFile) { + + // Vérifie la présence du champ + if (in_array($sFieldName, $aUploadFilesCols) || $aUploadFiles === '*') { + + // Supprime les fichiers + $this->oFilesManager->cleanWsDataDir($sVitisModuleName, $sVitisObjectName, $this->aValues['my_vitis_id'], $sFieldName, $sVitisPathComplement, $aDeletedFiles[$sFieldName], false); + + // Set aValues avec les fichiers restants + $this->aValues[$sFieldName] = null; + if (!empty($aUnchangedFiles[$sFieldName])) { + $this->aValues[$sFieldName] = implode('|', $aUnchangedFiles[$sFieldName]); + } + } + } + } + + // Fichiers à uploader ? + if (!empty($_FILES) && !empty($this->aValues['my_vitis_id'])) { + foreach ($_FILES as $sFieldName => $aFile) { + + // Vérifie la présence du champ + if (in_array($sFieldName, $aUploadFilesCols) || $aUploadFiles === '*') { + + // width / height + if (!empty($aUploadFiles[$sFieldName]['width']) && + !empty($aUploadFiles[$sFieldName]['height'])) { + + // Fichier unique + if (!empty($_FILES[$sFieldName]['name'])) { + $_FILES[$sFieldName]['width'] = $aUploadFiles[$sFieldName]['width']; + $_FILES[$sFieldName]['height'] = $aUploadFiles[$sFieldName]['height']; + } + + // Fichiers multiples + if (!empty($_FILES[$sFieldName][0]['name'])) { + for ($i=0; $i < count($_FILES[$sFieldName]); $i++) { + $_FILES[$sFieldName][$i]['width'] = $aUploadFiles[$sFieldName]['width']; + $_FILES[$sFieldName][$i]['height'] = $aUploadFiles[$sFieldName]['height']; + } + } + } + + // Fichiers à ne pas supprimer + $aExceptions = []; + if (!empty($aUnchangedFiles[$sFieldName])) { + $aExceptions = $aUnchangedFiles[$sFieldName]; + } + + // Nettoyage de l'espace ws_data + $this->oFilesManager->cleanWsDataDir($sVitisModuleName, $sVitisObjectName, $this->aValues['my_vitis_id'], $sFieldName, $sVitisPathComplement, false, $aExceptions); + + // Écriture des fichiers + $aUploadReturn = $this->oFilesManager->uploadInWsDataDir($sVitisModuleName, $sVitisObjectName, $this->aValues['my_vitis_id'], $sFieldName, $sVitisPathComplement, -1, "all", null, true); + $this->aValues[$sFieldName] = $aUploadReturn['field_value']; + + // Re-inscrit en base les fichiers à ne pas supprimer + $aFiles = explode('|', $this->aValues[$sFieldName]); + for ($i=0; $i < count($aExceptions); $i++) { + array_unshift($aFiles, $aExceptions[$i]); + } + $this->aValues[$sFieldName] = implode('|', $aFiles); + } + } + } + } } ?> diff --git a/vas/sql/sqlQueries.xml b/vas/sql/sqlQueries.xml index 131ae69f427361a1b80dc1a59aa57106e0385884..ad70051512d7ab830bb6e8b9a007d4e3ea0f6a35 100644 --- a/vas/sql/sqlQueries.xml +++ b/vas/sql/sqlQueries.xml @@ -955,5 +955,15 @@ ]]> </code> </query> + <query> + <type>update</type> + <version>2019.01.01</version> + <code> + <![CDATA[ + -- Frédéric le 14/02/2019 à 15:53 + ALTER TABLE s_vitis."user" ALTER COLUMN billinggroup_id drop default; + ]]> + </code> + </query> </queriesCollection> </sqlQueries>