Как фото передать в деталь в файлы и ссылки.

Как полученное фото передать в запись детали без костилей? 



Сейчас там происходит загрузка файла, я заменил кнопку и хочу сделать так: При нажатии открывается веб камера и снимается фото. 



Мне это фото нужно загрузить в деталь обратно как он делал при выборе файла. 

Нравится

5 комментариев
Лучший ответ

Здравствуйте Ислам!

После воспроизведения данного Вами кода, ошибка №1 не возникала (вероятно из-за разных версий продукта), но появлялась ошибка «Maximum call stack size exceeded error». Причина - обращение к AddRecordButton. Советую сделать замещение в diff на новую кнопку в FileDetailV2:

diff: /**SCHEMA_DIFF*/[
	{
		"operation": "insert",
		"name": "CustomButton",
		"parentName": "Detail",
		"propertyName": "tools",
		"values": {
			"caption": "Click me",
			"itemType": Terrasoft.ViewItemType.BUTTON,
			"click": {"bindTo": "getWebCamClick"},
			"visible": true
		}
	}
]/**SCHEMA_DIFF*/

Добавление фотографий в деталь не выполнялось. Я внесла несколько изменений в ваш код, теперь функционал работает. При открытии модального окна вы можете несколько раз нажать на кнопку «Сделать фото» и после каждого клика будет добавлено новое фото. Прикрепляю обновленные методы CameraPageMixin:

takePhoto: function() {
	var videoElement = document.querySelector("video");
	if (videoElement.srcObject) {
		var desiredWidth = 1000; 
		var desiredHeight = 1000;
		var canvas = document.createElement("canvas");
		canvas.width = desiredWidth;
		canvas.height = desiredHeight;
		var context = canvas.getContext("2d");
		context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
 
		var photoData = canvas.toDataURL("image/jpeg");
		var base64Part = photoData.split(",")[1];
		var buffer = this.base64ToArrayBuffer(base64Part);
		var mimeString = photoData.split(",")[0].split(":")[1].split(";")[0];
		var blob = new Blob([buffer], {type: mimeString});
		var files = new File([blob], "photo.jpeg", {type: "image/jpeg"});
		return files;
	}
	  return null;
},
 
base64ToArrayBuffer: function (base64) {
	var binaryString = atob(base64);
	var bytes = new Uint8Array(binaryString.length);
	for (var i = 0; i < binaryString.length; i++) {
		bytes[i] = binaryString.charCodeAt(i);
	}
	return bytes.buffer;
},

Ошибка №2 возникает из-за потери контекста. В FileDetailV2 метод onFileSelect вызывает getIsNewRecord, а getIsNewRecord отправляет сокетное сообщение GetCardState на DetailModuleV2, хотя должен его отправлять в BasePageV2. Воспроизводится, если хотя бы раз открыть контейнер до перезахода на страницу. Поймать точный момент возникновения проблемы у меня не получилось, к сожалению.

Здравствуйте, Ислам!

 

Вы можете реализовать поставленную задачу с помощью пользовательского модуля:

https://academy.creatio.com/docs/developer/front_end_development/sandbox/overview

По нажатию на кнопку будет открываться модальное окно с необходимым функционалом. Пример загрузки модуля описан ниже: https://academy.creatio.com/docs/developer/front_end_development/sandbox/overview#case-2746

Так же хочу уточнить, что метод «CardStateV2.EDIT» актуален только до версии 7.7.0. Для всех следующих версий нужно будет делать его замену. Похожий пример реализации: https://community.creatio.com/articles/error-when-trying-add-new-activity-history-connecred-object?_gl=1*ol2aml*_gcl_au*MTYxNTAzNjkzMi4xNjkyOTU4NzI3

Полезная ссылка по решению загрузки пользовательского модуля с параметрами для конструктора объекта модуля:

https://community.terrasoft.ua/questions/loadmodule-s-parametrami-konstruktora-kak

В конце для загрузки фото с модуля нужно отладить загрузку файла во вложения и вызов ендпоинта /0/rest/FileApiService/UploadFile

 

С уважением,

Ангелина

Anhelina,

Благодарю за подробный ответ, мне не понятен последний момент. С отладкой загрузки файла. Мы можем реализовать этот кейс вызвав функцию upload(config), которая реализована в FileDetailV2?  Если да, то подскажите где посмотреть примеры?

Ислам,

Вы можете вызвать функцию, передав нужное значение в config, так: this.Terrasoft.ConfigurationFileApi.upload(config, callback);

Модуль ConfigurationFileApi нужно добавить в зависимости: define(" ", [… " ConfigurationFileApi "], …

Так же могут быть полезными статьи:

https://academy.terrasoft.ua/docs/developer/ehlementy_interfejsa/strani…

https://community.terrasoft.ua/questions/vstavit-element-photocontainer…

Anhelina,

Я реализовал вызов Upload и у меня добавляется при нажатии на фотографировать фото в детали, но деталь ломается. Сразу после этого она перестает обновляться, то есть если я перехожу по другим записям деталь зависает и выводит две ошибки:

1)  "Message DetailRendered is not defined in DetailModuleV2 (CardModuleV2_9d571769-06d3-44bf-a1bc-94c8fa686266_FinApplicationContactPage_detail_DocListInFinAppDetail_detail_nested_FilesDocListInFinAppFile) module"



2)



Я так понимаю ошибка происходит тут в файле FileDetailV2: 









Для ясности оставлю код и детали и миксина, которые снимает фото с веб камеры: 

ДЕТАЛЬ:

 

define("FileDetailV2", ["ModalBox", "CameraPageMixin","ConfigurationEnums","ConfigurationFileApi"],
function(ModalBox, ConfigurationEnums) {
	return {
		attributes: {},
		messages: {},
		mixins: {
			CameraPageMixin: "Terrasoft.CameraPageMixin"
		},
		methods: {
 
			getWebCamClick: function() {
				var webCamModuleContainer = this.Ext.create("Terrasoft.Container", {
					id: this.mixins.CameraPageMixin.containerId,
					classes: { 
						wrapClassName: ["webcam-module-container-class"] 
					}
				});
				var photoContainerId = this.Ext.create("Terrasoft.Container", {
					id: this.mixins.CameraPageMixin.photoContainerId,
					classes: { 
						wrapClassName: ["photo-container-class"] 
					}
				});
			    var captureButton = this.Ext.create("Terrasoft.Button", {
			       caption: "Сделать фото",
			        handler: function() {
				        this.onCapturePhotoClick();
				    }.bind(this) 
			    });
			    var closeButton = this.Ext.create("Terrasoft.Button", {
			    	caption: "Закрыть окно",
			        handler: function() {
				        this.closeModalBox();
				    }.bind(this)
			    });
				var parentRecordId = this.get("MasterRecordId");
				var modalBoxConfig = {
					minHeight : "1",
					minWidth : "1",
					maxHeight : "100",
					maxWidth : "100",
			        id: this.sandbox.id + "_CustomModalBox",
			        handler: this,
			        selector: "#CustomModalBox",
			        renderTo: Ext.getBody(),
			        instanceConfig: {
			            parentRecordId: parentRecordId
			        }
			    };
			    var modalBoxContainer = ModalBox.show(modalBoxConfig,  this.destroy.bind(this));
			    ModalBox.setSize(510, 440);
			    modalBoxContainer.setStyle("background-color", "#FFFFFF");
 
 
				webCamModuleContainer.render(modalBoxContainer);
				photoContainerId.render(modalBoxContainer);
				captureButton.render(modalBoxContainer);
				closeButton.render(modalBoxContainer);
 
			    this.mixins.CameraPageMixin.openWebCamClick.apply(this, arguments);
			},
			onCapturePhotoClick: function(callback) {
 
			   var files = this.mixins.CameraPageMixin.takePhoto.apply(this, arguments);
				var config = this.onFileSelect(files);
				if (config) {
					this.Terrasoft.ConfigurationFileApi.upload(config, callback);
				}
			},
			closeModalBox: function() {
				this.mixins.CameraPageMixin.closeWebCamAndRemoveContainer.apply(this, arguments);
			    ModalBox.close();
			}
 
		},
		diff: /**SCHEMA_DIFF*/[
			{
			    "operation": "merge",
			    "name": "AddRecordButton",
			    "parentName": "Detail",
			    "propertyName": "tools",
			    "values": {
			        "itemType": Terrasoft.ViewItemType.BUTTON,
			        "tag": "addFileButton",
			        "fileUpload": false,
			        // "filesSelected": {"bindTo": "onFileSelectOveridden"},
			        "click": {"bindTo": "getWebCamClick"},
			        // "visible": {"bindTo": "getAddRecordButtonVisible"},
			        "imageConfig": {"bindTo": "Resources.Images.AddButtonImage"}
			    }
			}
			]/**SCHEMA_DIFF*/
	};
});

 Миксин: 

define("CameraPageMixin", [], function() { 
    Ext.define("Terrasoft.configuration.mixins.CameraPageMixin", {
        alternateClassName: "Terrasoft.CameraPageMixin",
 
		afterRender: function() {
            this.callParent(arguments);
            this.webcamStarted = false;
        },
	    videoWidth: 500,
	    videoHeight: 380,
	    videoStream: null,
	    containerId: "WebCamModuleContainer",
	    photoContainerId: "PhotoModuleContainer",
 
        onGetApplicationId: function(applicationId) {
           this.alert(applicationId);
        },
	    openWebCamClick: function() {
	           try {
	               var videoElement = document.createElement("video");
	               videoElement.setAttribute("autoplay", "true");
	               videoElement.width = this.videoWidth;
	               videoElement.height = this.videoHeight;
 
	               navigator.mediaDevices.getUserMedia({ video: true })
	                   .then(function(stream) {
	                       videoElement.srcObject = stream;
	                       this.videoStream = stream;
 
	                     var container = this.Ext.get(this.containerId);
	                     if (container) {
	                          container.dom.appendChild(videoElement);
	                          this.webcamStarted = true;
	                      } else {
	                          window.console.error("Ошибка: элемент с идентификатором " 
	                          + this.containerId + " не найден в DOM.");
	                	  }
	                   }.bind(this))
	                   .catch(function(error) {
	                       window.console.error("Ошибка при получении доступа к веб-камере:", error);
	                   }); 
	           } catch (e) {
	                 window.console.error("Произошла ошибка при инициализации веб-камеры:", e);
	           }
	    },
 
	    takePhoto: function() {
	        var videoElement = document.querySelector("video");
	        if (videoElement.srcObject) {
				var desiredWidth = 1000; 
		        var desiredHeight = 1000;
	            var canvas = document.createElement("canvas");
				canvas.width = desiredWidth;
		        canvas.height = desiredHeight;
	            var context = canvas.getContext("2d");
	            context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
 
	           var photoData = canvas.toDataURL("image/jpeg");
			   var byteString = atob(photoData.split(",")[1]);
		       var mimeString = photoData.split(",")[0].split(":")[1].split(";")[0];
		       var ab = new ArrayBuffer(byteString.length);
		       var ia = new Uint8Array(ab);
		       for (var i = 0; i < byteString.length; i++) {
		           ia[i] = byteString.charCodeAt(i);
		       }
		       var blob = new Blob([ab], {type: mimeString});
		       var files = new File([blob], "photo.jpeg", {type: "image/jpeg"});
		        return files;
	        }
			  return null;
	    },
 
	    closeWebCamAndRemoveContainer: function() {
	        if (this.videoStream) {
	            this.videoStream.getTracks().forEach(function(track) {
	                track.stop();
	            });
	        }
	        var container = this.Ext.get(this.containerId);
	         if (container) {
	             container.dom.remove();
	         }
 
	    }
	 });
    return Ext.create(Terrasoft.CameraPageMixin);
});



 

Здравствуйте Ислам!

После воспроизведения данного Вами кода, ошибка №1 не возникала (вероятно из-за разных версий продукта), но появлялась ошибка «Maximum call stack size exceeded error». Причина - обращение к AddRecordButton. Советую сделать замещение в diff на новую кнопку в FileDetailV2:

diff: /**SCHEMA_DIFF*/[
	{
		"operation": "insert",
		"name": "CustomButton",
		"parentName": "Detail",
		"propertyName": "tools",
		"values": {
			"caption": "Click me",
			"itemType": Terrasoft.ViewItemType.BUTTON,
			"click": {"bindTo": "getWebCamClick"},
			"visible": true
		}
	}
]/**SCHEMA_DIFF*/

Добавление фотографий в деталь не выполнялось. Я внесла несколько изменений в ваш код, теперь функционал работает. При открытии модального окна вы можете несколько раз нажать на кнопку «Сделать фото» и после каждого клика будет добавлено новое фото. Прикрепляю обновленные методы CameraPageMixin:

takePhoto: function() {
	var videoElement = document.querySelector("video");
	if (videoElement.srcObject) {
		var desiredWidth = 1000; 
		var desiredHeight = 1000;
		var canvas = document.createElement("canvas");
		canvas.width = desiredWidth;
		canvas.height = desiredHeight;
		var context = canvas.getContext("2d");
		context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
 
		var photoData = canvas.toDataURL("image/jpeg");
		var base64Part = photoData.split(",")[1];
		var buffer = this.base64ToArrayBuffer(base64Part);
		var mimeString = photoData.split(",")[0].split(":")[1].split(";")[0];
		var blob = new Blob([buffer], {type: mimeString});
		var files = new File([blob], "photo.jpeg", {type: "image/jpeg"});
		return files;
	}
	  return null;
},
 
base64ToArrayBuffer: function (base64) {
	var binaryString = atob(base64);
	var bytes = new Uint8Array(binaryString.length);
	for (var i = 0; i < binaryString.length; i++) {
		bytes[i] = binaryString.charCodeAt(i);
	}
	return bytes.buffer;
},

Ошибка №2 возникает из-за потери контекста. В FileDetailV2 метод onFileSelect вызывает getIsNewRecord, а getIsNewRecord отправляет сокетное сообщение GetCardState на DetailModuleV2, хотя должен его отправлять в BasePageV2. Воспроизводится, если хотя бы раз открыть контейнер до перезахода на страницу. Поймать точный момент возникновения проблемы у меня не получилось, к сожалению.

Показать все комментарии