"use strict"; (function () { 'use strict'; angular.module('myitsmApp') .service('attachmentService', ['$resource', '$http', '$timeout', 'systemAlertService', '$q', '$modal', 'objectValueMapperService', 'configurationModel', '$filter', function ($resource, $http, $timeout, systemAlertService, $q, $modal, objectValueMapperService, configurationModel, $filter) { var resource = $resource('', {}, { getAttachmentsInfo: { url: '/smartit/rest/attachment/info/:type/:id', method: 'GET', isArray: true }, getPlansForChangeRequest: { url: '/smartit/rest/change/plans/:id', method: 'GET', isArray: true }, getPlansForRelease: { url: '/smartit/rest/release/:id/plans', method: 'GET', isArray: true }, uploadAttachment: { url: '/smartit/rest/attachment/file/:type/:id', method: 'POST', isArray: true, headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); if (data.length > 0) { _.each(data, function (attachment) { formData.append('file[]', attachment.file); }); } else { formData.append('file', data.file); } return formData; } }, uploadProfileThumbnail: { url: '/smartit/rest/:type/:id/thumbnail?:query', method: 'PUT', isArray: false, transformRequest: function (data) { var formData = new FormData(); formData.append('file', data.file); return formData; }, transformResponse: function (data) { return { thumbnail: data }; }, headers: { 'Content-Type': undefined } }, addWorknoteWithAttachment: { url: '/smartit/rest/attachment/file/:type/:id/worknote', method: 'POST', isArray: true, headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); formData.append('text', data.noteText || data.worknote); !_.isUndefined(data.access) && formData.append('access', data.access); !_.isUndefined(data.locked) && formData.append('locked', data.locked); !_.isUndefined(data.brokerVendorName) && formData.append('brokerVendorName', data.brokerVendorName); data.shareWithVendor && formData.append('shareWithVendor', true); !_.isUndefined(data.vendorTicketId) && formData.append('vendorTicketId', data.vendorTicketId); data.workInfoType && formData.append('type', data.workInfoType); if (data['Email.Subject']) { formData.append('Email.Subject', data['Email.Subject']); formData.append('Email.Body', data['Email.Body']); data['Email.From.Person'] && formData.append('Email.From.Person', JSON.stringify(data['Email.From.Person'])); data['Email.To.Person'] && formData.append('Email.To.Person', JSON.stringify(data['Email.To.Person'])); data['Email.To.InternetEmail'] && formData.append('Email.To.InternetEmail', data['Email.To.InternetEmail']); } if (data.attachments.length > 0) { if (data.attachments.length === 1) { formData.append('file', data.attachments[0].file); } else { for (var i = 0, l = data.attachments.length; i < l; i++) { formData.append('file[]', data.attachments[i].file); } } } return formData; } }, addWorknoteWithAttachmentBulk: { url: '/smartit/rest/attachment/file/bulk/worknote', method: 'POST', isArray: true, headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); formData.append('text', data.noteText || data.worknote); !_.isUndefined(data.access) && formData.append('access', data.access); !_.isUndefined(data.locked) && formData.append('locked', data.locked); if (data['Email.Subject']) { formData.append('Email.Subject', data['Email.Subject']); formData.append('Email.Body', data['Email.Body']); data['Email.From.Person'] && formData.append('Email.From.Person', JSON.stringify(data['Email.From.Person'])); data['Email.To.Person'] && formData.append('Email.To.Person', JSON.stringify(data['Email.To.Person'])); data['Email.To.InternetEmail'] && formData.append('Email.To.InternetEmail', data['Email.To.InternetEmail']); } if (data.attachments.length > 0) { if (data.attachments.length === 1) { formData.append('file', data.attachments[0].file); } else { for (var i = 0, l = data.attachments.length; i < l; i++) { formData.append('file[]', data.attachments[i].file); } } } if (data.ticketList) { formData.append('ticketList', JSON.stringify(data.ticketList)); } return formData; } }, addAttachmentToWorknote: { url: '/smartit/rest/attachment/file/worknote/:type/:id', method: 'POST', isArray: true, headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); formData.append('file', data.file); return formData; } }, createChangePlan: { url: '/smartit/rest/:type/:id/plans', method: 'POST', isArray: true, headers: { 'Content-Type': undefined }, transformRequest: function (data) { return prepareFormDataForPlans(data); } }, updateChangePlan: { url: '/smartit/rest/:type/:parentId/plans/:id', method: 'PUT', isArray: true, headers: { 'Content-Type': undefined }, transformRequest: function (data) { return prepareFormDataForPlans(data); } }, deletePlan: { url: '/smartit/rest/:type/:parentId/plans/:planId', method: 'DELETE' //isArray: true, //headers: {'Content-Type': undefined}, /*transformRequest: function (data) { return prepareFormDataForPlans(data); }*/ } ///rest/change//plans/ }); /** * Get attachments info * @param id * @param type * @returns {ng.IPromise} */ this.getAttachmentsInfo = function (id, type) { if (type === EntityVO.TYPE_CHANGE) { return this.getPlansForChangeRequest(id); } if (type === EntityVO.TYPE_RELEASE) { return this.getPlansForRelease(id); } return resource.getAttachmentsInfo({ id: id, type: type }).$promise .then(function (response) { if (!response[0]) { return []; } return normalizeAttachments(response); }); }; /** * Get plans with attachments for Change request * @param id * @param {Array} plansFilter * @returns {ng.IPromise} */ this.getPlansForRelease = function (id, plansFilter) { var types = _.isArray(plansFilter) ? plansFilter.join() : plansFilter; var params = types ? { types: types } : {}; params.id = id; return resource.getPlansForRelease(params).$promise .then(function (response) { if (!response[0] || !response[0].items || !response[0].items[0].objects) { return []; } var plans = response[0].items[0].objects; var planGroupIndexing = {}, groupedPlans = _.groupBy(plans, function (item) { return item.workNote.workNoteTypeId; }); _.each(plans, function (plan) { if (plan.workNote.attachmentCount > 0) { plan.attachmentInfos = normalizeAttachments(plan); } if (groupedPlans[plan.workNote.workNoteTypeId].length > 1) { planGroupIndexing[plan.workNote.workNoteTypeId] ? planGroupIndexing[plan.workNote.workNoteTypeId]++ : (planGroupIndexing[plan.workNote.workNoteTypeId] = 1); plan.typeIndex = planGroupIndexing[plan.workNote.workNoteTypeId]; } }); return plans; }); }; /** * Get plans with attachments for Change request * @param id * @param {Array} plansFilter * @returns {ng.IPromise} */ this.getPlansForChangeRequest = function (id, plansFilter) { var types = _.isArray(plansFilter) ? plansFilter.join() : plansFilter; var params = types ? { types: types } : {}; params.id = id; return resource.getPlansForChangeRequest(params).$promise .then(function (response) { if (!response[0] || !response[0].items || !response[0].items[0].objects) { return []; } var plans = response[0].items[0].objects; var planGroupIndexing = {}, groupedPlans = _.groupBy(plans, function (item) { return item.workNote.workNoteTypeId; }); _.each(plans, function (plan) { if (plan.workNote.attachmentCount > 0) { plan.attachmentInfos = normalizeAttachments(plan); } if (groupedPlans[plan.workNote.workNoteTypeId].length > 1) { planGroupIndexing[plan.workNote.workNoteTypeId] ? planGroupIndexing[plan.workNote.workNoteTypeId]++ : (planGroupIndexing[plan.workNote.workNoteTypeId] = 1); plan.typeIndex = planGroupIndexing[plan.workNote.workNoteTypeId]; } }); return plans; }); }; /** * Get attachment file * * @param type * @param attachment * @returns {*} */ this.getAttachmentFile = function (type, attachment, returnAsBlob, isMyITComment) { attachment.loadingDetails = true; var request; // For broadcast created from AR (or any attachment created from comment), the attachment will contain attachmentReference if (!_.isEmpty(attachment.attachmentReference)) { request = { method: 'POST', url: '/smartit/rest/attachment/file/' + type, data: attachment.attachmentReference, responseType: 'blob' }; } // Comments from MyIT via POI Asset else if (attachment.id && isMyITComment) { request = { method: 'GET', url: '/smartit/rest/attachment/social/file/download/' + attachment.id, responseType: 'blob' }; } // For broadcast created from UC, the attachment will not contain attachmentReference, use a different rest call // so that attachment is retrieved from Social instead of AR else if (attachment.id) { request = { method: 'GET', url: '/smartit/rest/attachment/file/' + type + '/get/' + attachment.id, responseType: 'blob' }; } else { return $q.reject('attachment info missing'); } if (window.FormData) { return $http(request).success(function (fileAsBlob) { if (returnAsBlob) { return fileAsBlob; } if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE Specific var blobObject = new Blob([fileAsBlob]); window.navigator.msSaveOrOpenBlob(blobObject, attachment.name); attachment.loadingDetails = false; } else { // use timeout to get around the '$digest already in progress' exception $timeout(function () { var a = document.createElement('a'); document.body.appendChild(a); a.style.display = 'none'; var objectUrl = URL.createObjectURL(fileAsBlob); attachment.loadingDetails = false; a.href = objectUrl; a.download = attachment.name; a.click(); // FireFox won't work if this line is present -> URL.revokeObjectURL(objectUrl); a.remove(); }, 0); } }); } else { var url = '/smartit/rest/attachment/file/' + type + '?name=' + attachment.name; if (!_.isEmpty(attachment.attachmentReference)) { _.each(attachment.attachmentReference, function (refValue, key) { url += '&' + key + '=' + refValue; }); } else if (attachment.id) { url = '/smartit/rest/attachment/file/' + type + '/get/' + attachment.id; } window.location.href(url); //due to proper headers url change does not happen attachment.loadingDetails = false; return $q.when(1); } }; /** * Prepares file for upload * * @param options * @returns {{pendingSave: boolean}} */ this.prepareFileToUpload = function (options) { var attachment = prepareFileToUploadInternal(options); if (attachment && !configurationModel.isFileExtensionAllowed(attachment.fileExt)) { systemAlertService.error({ text: $filter('i18n')('attachment.fileExtension.error'), clear: false }); attachment = null; } return attachment; }; function prepareFileToUploadInternal(options) { var thumbnailFormats = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tga', 'tif', 'tiff'], fileInput = options.fileInput, fileToUpload = { pendingSave: true }; if (window.FileReader) { var file; if (!options.fileToPrepare) { var inputDOM = angular.element(options.fileInput || '.' + options.inputClass); file = inputDOM[0].files[0]; } else { file = options.fileToPrepare; } var dataUrlFileReader = new FileReader(), binaryFileReader = new FileReader(); fileToUpload.name = file.name; fileToUpload.size = file.size; fileToUpload.file = file; var extMatch = fileToUpload.name.match(/\.([^\.]*)$/); if (extMatch) { fileToUpload.fileExt = extMatch[1]; if (thumbnailFormats.indexOf(fileToUpload.fileExt.toLowerCase()) !== -1) { dataUrlFileReader.readAsDataURL(file); dataUrlFileReader.onload = function (event) { $timeout(function () { fileToUpload.thumbnail = event.target.result; if (fileToUpload.thumbnail) { var m = fileToUpload.thumbnail.match('data:(.*)?;'); fileToUpload.contentType = m && m[1] || null; } }); }; } else { $timeout(function () { fileToUpload.fileGenericIconClass = new AttachmentVO().getFileGenericIconClass(fileToUpload.name); }); } } binaryFileReader.readAsArrayBuffer(file); binaryFileReader.onload = function (event) { $timeout(function () { fileToUpload.binaryData = event.target.result; }); }; return fileToUpload; } else { if (!fileInput.value) { return; } var filePath = fileInput.value; fileToUpload.fileInput = angular.element(fileInput); fileToUpload.name = (filePath.indexOf('/') >= 0) ? filePath.split('/').pop() : filePath.split('\\').pop(); fileToUpload.fileGenericIconClass = new AttachmentVO().getFileGenericIconClass(fileToUpload.name); $timeout(function () { fileToUpload.fileInput .before(fileInput.cloneNode()) .hide(); }); return fileToUpload; } } /** * Dismiss attachment * * @param scope * @param $event * @param attachment * @param context */ this.dismissAttachment = function (scope, $event, attachment, context) { var index = scope.attachments.indexOf(attachment); if (index >= 0) { var removed = scope.attachments.splice(index, 1); if (!attachment.attachmentReference) { scope.attachmentToUpload.splice(scope.attachmentToUpload.indexOf(attachment), 1); } else { if (context && context === 'detail') { scope.attachmentToDelete.push(removed[0]); } } var descField = objectValueMapperService.getFieldByName('desc'); if (descField) { // process attachments to delete descField.value.attachmentToDelete = scope.attachmentToDelete; descField.value.attachmentToUpload = scope.attachmentToUpload; } } $event.stopImmediatePropagation(); }; /** * Upload attachment * * @param profileType * @param id * @param attachments * @returns {*} */ this.uploadAttachment = function (profileType, id, attachments) { if (window.FileReader) { return resource.uploadAttachment({ type: profileType, id: id }, attachments).$promise .then(function (response) { if (!response[0]) { return []; } attachments.pendingSave = false; var normalizedResp = normalizeAttachments(response); _.each(normalizedResp, function (attachInfo) { var attachFile = _.findWhere(attachments, { name: attachInfo.name }); if (attachFile) { // SW00547633 - For task, we are passing an array here and line 493 is working // differently when compared with passing an object for other ticket types and this // is causing issues with deep cloning of ticket. So, this is a hack to fix the // issue with deep cloning and to keep the changes minimal, need to be addressed later attachFile.binaryData = undefined; angular.extend(attachInfo, attachFile); } attachInfo.pendingSave = false; }); return normalizedResp; }) .catch(function (err) { systemAlertService.error({ text: err.data.error, clear: false }); return $q.reject(err); }); } else { var config = prepareIframeTransportSettings('attachments', { type: profileType, id: id }, attachments); return this.uploadUsingIframeTransport(config); } }; /** * Upload using iframe transport * @param config * @param noDataNormalization * @returns {ng.IPromise|promise} */ this.uploadUsingIframeTransport = function (config, noDataNormalization) { var uploadDefer = $q.defer(); $.ajax(config).success(function (resp) { console.log(resp); var respJSON = resp ? JSON.parse(resp) : []; var respData = noDataNormalization ? respJSON : normalizeAttachments(respJSON); uploadDefer.resolve(respData); }); return uploadDefer.promise; }; /** * Delete attachment * * @param type * @param params * @returns {ng.IPromise|*} */ this.deleteAttachment = function (type, params) { return $http({ method: 'DELETE', headers: { 'Content-Type': 'application/json' }, url: '/smartit/rest/attachment/' + type, data: params }) .catch(function (err) { systemAlertService.error({ text: err.data.error, clear: false }); return $q.reject(err); }); }; /** * Upload profile thumbnail * * @param id * @param type * @param fileInput * @param query * @returns {*} */ this.uploadProfileThumbnail = function (id, type, fileInput, query) { var profileImage = this.prepareFileToUpload({ fileInput: fileInput }); if (profileImage) { if (window.FileReader) { return resource.uploadProfileThumbnail({ type: type, id: id, query: query }, profileImage).$promise; } else { var config = prepareIframeTransportSettings('thumbnail', { type: type, id: id, query: query }, profileImage), uploadDefer = $q.defer(); $.ajax(config).success(function (resp) { console.log(resp); uploadDefer.resolve({ thumbnail: resp }); }); return uploadDefer.promise; } } return $q.when({}); }; /** * Add worknote with attachment * * @param params * @param worknote * @returns {*} */ this.addWorknoteWithAttachment = function (params, worknote) { if (window.FileReader) { return resource.addWorknoteWithAttachment(params, worknote).$promise; } else { var data = [ { name: 'text', value: worknote.noteText }, { name: 'access', value: worknote.access }, { name: 'type', value: worknote.workInfoType } ]; var config = prepareIframeTransportSettings('worknoteCreate', { type: params.type, id: params.id, classId: params.classId }, worknote.attachments, data); return this.uploadUsingIframeTransport(config, true); } }; this.addWorknoteWithAttachmentBulk = function (worknote) { if (window.FileReader) { return resource.addWorknoteWithAttachmentBulk(worknote).$promise; } else { var data = [ { name: 'text', value: worknote.noteText || worknote.worknote }, { name: 'access', value: worknote.access } ]; worknote.locked && data.push({ name: 'locked', value: worknote.locked }); worknote['Email.Subject'] && data.push({ name: 'Email.Subject', value: worknote['Email.Subject'] }); worknote['Email.Body'] && data.push({ name: 'Email.Body', value: worknote['Email.Body'] }); worknote['Email.From.Person'] && data.push({ name: 'Email.From.Person', value: JSON.stringify(worknote['Email.From.Person']) }); worknote['Email.To.Person'] && data.push({ name: 'Email.To.Person', value: JSON.stringify(worknote['Email.To.Person']) }); worknote['Email.To.InternetEmail'] && data.push({ name: 'Email.To.InternetEmail', value: worknote['Email.To.InternetEmail'] }); worknote.ticketList && data.push({ name: 'ticketList', value: JSON.stringify(worknote.ticketList) }); var config = prepareIframeTransportSettings('worknoteCreateBulk', undefined, worknote.attachments, data); return this.uploadUsingIframeTransport(config, true); } }; /** * Add attachment to worknote * * @param type * @param id * @param attachment * @param classId * @returns {*} */ this.addAttachmentToWorknote = function (type, id, attachment, classId) { if (window.FileReader) { return resource.addAttachmentToWorknote({ type: type, id: id }, attachment).$promise; } else { var config = prepareIframeTransportSettings('worknoteUpdate', { type: type, id: id, classId: classId }, attachment); return this.uploadUsingIframeTransport(config); } }; this.createChangePlan = function (id, type, plan) { return resource.createChangePlan({ id: id, type: type }, plan).$promise.then(function (response) { if (!response[0] || !response[0].items || !response[0].items[0]) { return []; } var plans = response[0].items; _.each(plans, function (plan) { if (plan.workNote.attachmentCount > 0) { plan.attachmentInfos = normalizeAttachments(plan); } }); return { data: plans, action: 'created' }; }); }; this.updateChangePlan = function (params, request) { return resource.updateChangePlan(params, request).$promise.then(function (response) { if (!response[0] || !response[0].items || !response[0].items[0]) { return []; } var plans = response[0].items; _.each(plans, function (plan) { if (plan.workNote.attachmentCount > 0) { plan.attachmentInfos = normalizeAttachments(plan); } }); return { data: plans, action: 'updated' }; }).catch(function (err) { systemAlertService.error({ text: err.data.error, clear: false }); return $q.reject(err); }); }; this.deletePlan = function (parentId, type, planId) { return resource.deletePlan({ parentId: parentId, type: type, planId: planId }).$promise .then(function () { return { data: [planId], action: 'deleted' }; }); }; this.normalizeAttachments = function (data) { return normalizeAttachments(data); }; this.showAttachmentPreviewDialog = function (planData) { return $modal.open({ template: '', windowClass: 'attachments-previewer-modal', backdropClass: 'attachments-previewer-backdrop', controller: ['$scope', function ($scope) { $scope.plan = planData; }] }); }; function prepareIframeTransportSettings(reqType, urlParams, attachments, data) { var defaultConfig = { url: '', files: '', iframe: true, dataType: 'text' }; switch (reqType) { case 'thumbnail': defaultConfig.url = '/smartit/rest/' + urlParams.type + '/' + urlParams.id + '/thumbnail' + (urlParams.query ? '?' + urlParams.query : ''); break; case 'attachments': defaultConfig.url = '/smartit/rest/attachment/file/' + urlParams.type + '/' + urlParams.id; break; case 'worknoteCreate': defaultConfig.url = '/smartit/rest/attachment/file/' + urlParams.type + '/' + urlParams.id + '/' + (urlParams.classId ? urlParams.classId + '/' : '') + 'worknote'; break; case 'worknoteCreateBulk': defaultConfig.url = '/smartit/rest/attachment/file/bulk/worknote'; break; case 'worknoteUpdate': defaultConfig.url = '/smartit/rest/attachment/file/worknote/' + urlParams.type + '/' + urlParams.id + (urlParams.classId ? '/' + urlParams.classId : ''); } var fileInput; if (_.isArray(attachments)) { fileInput = []; _.each(attachments, function (item, index) { item.fileInput.attr({ name: 'file[]', multiple: 'true', id: 'attachmentFile_' + index }); item.fileInput.prop('value', 'sdfasdfasdfasd'); item.fileInput.prop('disabled', null); fileInput.push(item.fileInput[0]); }); } else { fileInput = attachments.fileInput; fileInput.prop('disabled', null); } if (data) { defaultConfig.data = data; defaultConfig.processData = false; } defaultConfig.files = fileInput; return defaultConfig; } function normalizeAttachments(data) { return (data[0] ? (data[0].items || []) : (data.attachmentInfos || [])).map(function (attachment) { return new AttachmentVO().build(attachment); }); } function prepareFormDataForPlans(data) { var formData = new FormData(); formData.append('text', data.text); formData.append('type', data.type); !_.isUndefined(data.access) && formData.append('access', data.access); !_.isUndefined(data.locked) && formData.append('locked', data.locked); if (data.attachmentInfos.length > 0) { formData.append('attachmentInfos', JSON.stringify(data.attachmentInfos)); for (var i = 0, l = data.attachments.length; i < l; i++) { formData.append('file', data.attachments[i].file); } } return formData; } } ]); })();