/** * Survey response submission handler controller. */ angular.module('kalgudiApp.surveys').controller('surveyResponseController', ['$scope', '$state', '$rootScope', 'kalgudiLiterals', '$injector', 'surveyServices', 'helpandlegalservice', "Upload", function ($scope, $state, $rootScope, kalgudiLiterals, $injector, surveyService, helpandlegalservice, Upload) { /** * Checking the user device mobile/Desktop */ if (!IS_MOBILE_DEVICE) { $uibModal = $injector.get('$uibModal'); } else { $ionicModal = $injector.get('$ionicModal'); lazysync = $injector.get('lazysync'); $scope.modal = $ionicModal.fromTemplateUrl($rootScope.themebasepathvalue + 'surveys/assist-member-modal.html', { scope: $scope, animation: 'slide-in-up', }).then(function (modal) { $scope.modal = modal; }); } /** * Survey response submission fields */ // Different question types $scope.QUESTION_TYPE = { YES_NO: 'YES_NO', TEXT: 'TEXT', RATING: 'RATING', DATE: 'DATE', MULTIPLE_CHOICE_QUESTION: 'MULTIPLE_CHOICE_QUESTION', MULTIPLE_CHOICE_SELECTION: 'MULTIPLE_CHOICE_SELECTION', }; $scope.surveyId; $scope.surveyDetails; /** * Tells the max length of character that user can give for a text answer. */ var textLength = 2000; $scope.textLength = textLength; // Flags for survey submission $scope.isSurveyExpired = false; $scope.isSubmitted = false; $scope.isResubmittable = false; $scope.isDisabled = false; $scope.canSubmit = false; $scope.isAssisted = false; // User response $scope.surveyResponse = []; //isAdmin flag got from $state.params $scope.isAdmin = $state.params.adminFlag; $scope.selectedQuestionToAddMedia; /** * Initializes survey response controller variables */ $scope.init = function () { try { $scope.surveyId = $state.params.surveyId; $scope.profileId = $state.params.profileId || $rootScope.loggedInUserBusinessProfile.profileKey; $scope.isAssisted = ($state.params.isAssisted == 'assist'); $scope.currentQuestionIndex = 0; $scope.isAttachmentsRequired = false; // if ($scope.isAssisted) $scope.getTargettedMembers(); $scope.getSurvey(); } catch (e) { console.log('Unable to initialize survey response submission page.', e); } }; /* ------------------------- DECLARE FUNCTIONS BELOW ------------------------- */ /** * Gets, survey details from service. */ $scope.getSurvey = function () { // You cannot do anything without survey ID if (!$scope.surveyId) { console.log('Cannot get survey details without survey ID.'); return; } $rootScope.spinerisActive = true; // Get survey details from service surveyService.getSurveyDetails($scope.surveyId, $scope.profileId).then( function (res) { // res = JSON.parse(localStorage['s2']); // Get data if response is OK if (res.code == 200 || res.code == 201) { try { $scope.surveyDetails = JSON.parse(res.data); } catch (e) { $scope.surveyDetails = res.data; } $scope.isSurveyUnderProgram = typeof $scope.surveyDetails.entityId !== 'undefined'; // Trim the expiry date $scope.surveyDetails.expiryDate = new Date($scope.surveyDetails.expiryDate.split(' ')[0]); // Check survey submission status once survey details are ready $scope.checkSurveySubmission(); $scope.createSurveyResponse($scope.surveyDetails.questions); if ($scope.isAssisted) $scope.getTargettedMembers(); } $rootScope.spinerisActive = false; }, function (err) { console.log('Unable to get survey details for ID = ' + $scope.surveyId, err); $rootScope.spinerisActive = false; } ); }; /** * Survey text responses may have two different structure. * Old structure: * `response: "",` * New structure: * `response: { * text: "", * attachments: [] * }` * * All previous surveys responses have old response structure. * This function converts both the response type to single structure. * It will convert previous response structure to new response structure. * * @param {any} question Survey question object */ $scope.getNormalizedSurveyTextResponse = function (question) { // Only normalize text responses, // for rest of the question types return the answer if (question.questionType !== $scope.QUESTION_TYPE.TEXT && question.questionType !== $scope.QUESTION_TYPE.DATE) { return question.answer; } if (typeof question.answer === 'undefined') { return { text: '', attachments: [] } } else if (typeof question.answer === 'string') { return { text: question.answer, attachments: [] }; } else { return question.answer; } }; /** * Checks whether the user can submit survey or not. */ $scope.checkSurveySubmission = function () { // Survey details not available hence, cannot check if (!$scope.surveyDetails) return; // Raise survey expiry flag $scope.isSurveyExpired = (new Date() > $scope.surveyDetails.expiryDate); // User already submitted survey or not $scope.isSubmitted = $scope.surveyDetails.isResponded; // Raise survey re-submission flag $scope.isResubmittable = $scope.surveyDetails.isResubmittable; $scope.isDisabled = $scope.surveyDetails.isDisabled; // User can submit a survey if and only if // its not expired and // if not submitted else // if submitted then its re-submittable $scope.canSubmit = (!$scope.isSurveyExpired && (!$scope.isSubmitted || $scope.isResubmittable)); $scope.canSubmit = $scope.canSubmit && ($scope.isAssisted || $scope.profileId == $rootScope.loggedInUserBusinessProfile.profileKey); }; /** * Prepare survey user response object with all questions and selected answers. * @param {any[]} questions List of all questions * @param {any} response User response */ $scope.createSurveyResponse = function (questions) { // Do nothing if you dont have any questions if (!questions) return; // Filter out duplicates questions.forEach(function (q) { if (q.questionType == $scope.QUESTION_TYPE.MULTIPLE_CHOICE_QUESTION) { q.options = q.options.filter(function (item, pos) { return q.options.indexOf(item) == pos; }) } }); // Copy all questions to survey response $scope.surveyResponse = questions; // If there is response // if (response && response.answers) { // // Actual answers is in 0th element of answers field // response.answers = response.answers[0]; // For each element in survey responses $scope.surveyResponse.forEach(function (q) { // Assign answers to questions try { q.response = $scope.getNormalizedSurveyTextResponse(q); if (q.questionType === $scope.QUESTION_TYPE.DATE) { if (q.response && q.response.text) { q.response.text = new Date(q.response.text); // Check for invalid date if (q.response.text instanceof Date && isNaN(q.response.text)) { q.response.text = ''; } } } } catch (e) { console.log(e); } }); // } else { // $scope.surveyResponse.forEach(function (q) { // q.response = ''; // }); // } }; /** * Sets, rating to a rating type question in survey. * @param {any} question Question in which rating response to set. * @param {number} rating Rating to set. */ $scope.updateRating = function (question, rating) { // Update rating if you have question obj if (question) question.response = rating; console.log(question); }; /** * Toggle current selected option in the question response. * * @param {any} question Question object * @param {string} option Current selected option */ $scope.toggleMultipleSelection = function (question, option) { // If already selected then remove it from selection // Else push option in selected response list (question.response.indexOf(option) >= 0) ? question.response.splice(question.response.indexOf(option), 1) : question.response.push(option); } /** * Checks, if current option is selected or not in MCS. * * @param {any} question Question object * @param {string} option Current selected option. * @returns Returns true if selected otherwise false. */ $scope.isSelected = function (question, option) { return (question.response.indexOf(option) >= 0); } /** * Submit all survey responses to server. */ $scope.submitSurvey = function () { $rootScope.spinerisActive = true; const requestPayload = { "surveyId": $scope.surveyId, "answers": {}, "respondedTS": new Date(), "userId": $scope.assistantDetails.profileKey || $rootScope.loggedInUserBusinessProfile.profileKey, "userName": $scope.assistantDetails.firstName || $rootScope.loggedInUserBusinessProfile.firstName, }; if ($scope.isAssisted) { requestPayload.assistantDetails = { profileKey: $rootScope.loggedInUserBusinessProfile.profileKey, firstName: $rootScope.loggedInUserBusinessProfile.firstName, profilePicURL: $rootScope.loggedInUserBusinessProfile.profilePicUrl, } } $scope.surveyResponse.forEach(function (res) { var response = ''; if (Array.isArray(res.response)) { response = res.response.join(", "); } else { if (typeof res.response === 'undefined' || typeof res.response.text === 'undefined') { response = typeof res.response !== 'undefined' ? res.response + "" : ''; } else { try { if (res.questionType === $scope.QUESTION_TYPE.DATE) { const d = new Date(res.response.text); res.response.text = (d.getYear() + 1900) + '-' + (d.getMonth() + 1) + '-' + (d.getDate()); } if (IS_MOBILE_DEVICE) { delete res.datePicker; } else { // delete } } catch (e) { throw e; } response = res.response; } } // if (res.responseAttachment) { // requestPayload.answers[res.id] = { // text: response, // attachments: res.responseAttachment // }; // } else { // } requestPayload.answers[res.id] = response || ''; }); // Allow offline survey submissions if network is not available if (!$rootScope.networkAvaliable && IS_MOBILE_DEVICE) { lazysync.addToStaging(requestPayload, lazysync.STAGING_TYPE.SURVEYS); $rootScope.commonTopErrorAlert('Your survey submission will be synced later when network comes back.'); $rootScope.spinerisActive = false; history.back(); return; } // Submit the survey surveyService.submitSurvey(requestPayload, $scope.isSubmitted).then( function (res) { const msg = $scope.isSubmitted ? 'Survey response updated.' : 'Survey response submitted.' if (IS_MOBILE_DEVICE) { $rootScope.showAlertBox(msg, 'Response submitted'); } else { $rootScope.showSuccessMessage(msg, '', 4000); } $rootScope.spinerisActive = false; // Update survey details // $scope.getSurvey(); window.history.back(); }, function (err) { console.log(err); $rootScope.spinerisActive = false; } ); } /** * Opens already submitted answers attachment image fullview. * * @param {any} question */ $scope.openSubmittedAnswerAttachmentFullview = function (question) { const message = { lstOfAttachments: question.response.attachments, }; $scope.openImageFullview(message); }; /** * Opens new answer attachment image fullview. * * @param {any} question */ $scope.openAnswerAttachmentFullview = function (question) { const message = { lstOfAttachments: question.responseAttachment, }; $scope.openImageFullview(message); }; /** * Opens question attachment image fullview. * * @param {any} question */ $scope.openQuestionAttachmentFullview = function (question) { const message = { lstOfAttachments: question.attachments, }; $scope.openImageFullview(message); }; /** * Opens default kalgudi image fullview dialog. * * @param {any} attachments */ $scope.openImageFullview = function (attachments) { const modalInstance = $uibModal.open({ templateUrl: 'webapp/themes/html/newsFeed/shareAthoughtFullview.html', controller: 'sharefullviewController', size: 'md', windowClass: 'share-full', resolve: { items: function () { return attachments; } } }); } /** * Sets, selected question to add a media attachment. Later * after uploading media to s3, the uploaded media will get injected * to this selected question. * * @param {any} question */ $scope.attachMedia = function (question) { $scope.selectedQuestionToAddMedia = question; } if (IS_MOBILE_DEVICE) { $rootScope.$on("uploadedS3URL", function (event, objectS3URL) { if ($scope.selectedQuestionToAddMedia) { // $scope.selectedQuestionToAddMedia.response = typeof $scope.selectedQuestionToAddMedia.responseAttachment === 'object' && // Array.isArray($scope.selectedQuestionToAddMedia.responseAttachment) // ? $scope.selectedQuestionToAddMedia.responseAttachment // : []; delete objectS3URL.localFile; delete objectS3URL.size; delete objectS3URL.name; // Add geo tagging var lat = ""; var long = ""; if (Array.isArray(LATITUDELONGITUDEVALUES) && LATITUDELONGITUDEVALUES.length >= 2) { lat = LATITUDELONGITUDEVALUES[0]; long = LATITUDELONGITUDEVALUES[1]; } objectS3URL.geoLocation = { latitude: lat, longitude: long }; $scope.selectedQuestionToAddMedia.response.attachments.push(objectS3URL); } }); /* Mobile date picker */ const datePicker = { todayLabel: 'Today', closeLabel: 'Close', inputDate: new Date(), step: "1", format: "12", callback: function (val) { datePickerCallback(val); } } var datePickerCallback = function (val) { if (typeof (val) === 'undefined') { } else { // $scope.surveyObject.expiryDate = val; $scope.datePicker.inputDate = val; s // $scope._selectedQuestion.response.text = val; }; } $scope.injectDatePickerObjectToQuestion = function (question) { question.datePicker = { todayLabel: 'Today', closeLabel: 'Close', inputDate: new Date(), step: "1", format: "12", callback: function (val) { if (typeof (question.response) === 'undefined') { question.response = { text: '', attachments: [] }; } question.response.text = val; } }; } /* Mobile date picker ends */ } else { /** * Uploads and attaches multiple images to a question. */ $scope.attachImageWeb = function(question,doucumentType){ var tempObj = { uploadType: doucumentType, } // tempObj.uploadType = 'IMAGE'; var modalInstance = $uibModal.open({ templateUrl: $rootScope.themebasepathvalue + 'shared/uploadMultimedia.html', controller: 'uploadMultimediaController', windowClass: 'app-modal-window', size: 'lg', resolve: { items: function () { return tempObj; } } }); // uploadedMedia will contain all uploaded objects as an array modalInstance.result.then(function (uploadedMedia) { // question.responseAttachment = typeof question.responseAttachment === 'object' && Array.isArray(question.responseAttachment) ? question.responseAttachment : []; for(i in uploadedMedia){ try { // Delete unnecessary files delete uploadedMedia[i].name; delete uploadedMedia[i].size; // Append http/s if not exists if (!uploadedMedia[i].url.includes(env.secure)) { uploadedMedia[i].url = env.secure + uploadedMedia[i].url; } // Add geo tagging var lat = ""; var long = ""; if (Array.isArray(LATITUDELONGITUDEVALUES) && LATITUDELONGITUDEVALUES.length >= 2) { lat = LATITUDELONGITUDEVALUES[0]; long = LATITUDELONGITUDEVALUES[1]; } uploadedMedia[i].geoLocation = { latitude: lat, longitude: long }; } catch (e) { console.warn('Unable to attach images to survey question', e); } question.response.attachments = typeof question.response.attachments !== 'undefined' ? question.response.attachments : []; question.response.attachments.push(uploadedMedia[i]); } }); }; // $scope.attachImageWeb = function (question, index) { // $scope.isAttachmentsRequired = !$scope.isAttachmentsRequired; // $scope.currentQuestionIndex = index; // } // function getFileExtention(filename) { // return filename.split('.').pop(); // } // $scope.onFileSelected = function ($files, $file, $newFiles, $duplicateFiles, $invalidFiles, $event) { // $scope.currentFileDetails = $files; // helpandlegalservice.uploadS3Policy('businessTrace', $files[0].type).then(function (result) { // $scope.policyData = result; // $scope.compressTraceAttachmentsAndUpLoad($file, $files); // }); // } // $scope.compressTraceAttachmentsAndUpLoad = function (tempFile, files) { // var constructedName = $rootScope.loggedInUserBusinessProfile.profileKey + '_' + Math.floor(new Date() / 100) + '.' + getFileExtention(files[0].name); // Upload.upload({ // url: ATTACH_BUCKETNAME, // method: 'POST', // data: { // key: 'data/TRACE/' + constructedName, // the key to store the file on S3, could be file name or customized // AWSAccessKeyId: 'AKIAJPKIEGQPZLTARDXQ', // acl: 'public-read', // sets the access to the uploaded file in the bucket: private, public-read, ... // policy: $scope.policyData.policy, // base64-encoded json policy (see article below) // signature: $scope.policyData.signature, // base64-encoded signature based on policy string (see article below)*/ // "Content-Type": tempFile.type != '' ? tempFile.type : 'application/octet', // content type of the file (NotEmpty) // // this is needed for Flash polyfill IE8-9 // file: tempFile // } // }).progress(function (evt) { // $scope.spinnerPicUpload = true; // }).success(function (data, status, headers, config) { // var request = { // "attachmentType": 'gallery', // "attachmentStatus": true // } // $scope.uploadFileUrl = SERVER_IP + "/data/TRACE/" + constructedName; // console.log($scope.uploadFileUrl); // var fileFormats = ["jpg", "png", "pdf", "txt", "doc", "docx", "xlsx", "ppt", "pptx", "jpeg", "gif", "3gpp", "quicktime", "wav", "tiff"]; // var checkfiletypes = ""; // var checkfilesize = ""; // if (files.length != 0) { // for (index in files) { // $scope.attachmentName = files[index].name; // var filename = files[index].name.split("."); // filename = filename.length == 2 ? filename[1].toLowerCase() : ""; // if (fileFormats.indexOf(filename) > -1) { // } else { // checkfiletypes = "notsupported"; // } // if (files[index].size > 2097152) { // checkfilesize = "notSupportedSize"; // } // } // } // if (checkfilesize != "notSupportedSize" && checkfiletypes != "notsupported") { // $scope.status = true; // if ($scope.surveyResponse[$scope.currentQuestionIndex].response.hasOwnProperty("attachments")) { // $scope.surveyResponse[$scope.currentQuestionIndex].response.attachments.push({ // "url": $scope.uploadFileUrl, // "context": "Attachment", // "msgType": filename, // 'name': $scope.attachmentName, // 'size': files[0].type, // "geoLocation": // { // "latitude": "", // "longitude": "" // } // }); // } // else { // $scope.surveyResponse[$scope.currentQuestionIndex].response.attachments = []; // $scope.surveyResponse[$scope.currentQuestionIndex].response.attachments.push({ // "url": $scope.uploadFileUrl, // "context": "Attachment", // "msgType": files[0].size, // 'name': $scope.attachmentName, // 'size': files[0].type, // "geoLocation": // { // "latitude": "", // "longitude": "" // } // }); // } // } // if (checkfilesize == "notSupportedSize") { // alert($scope.profileLiterals.searchByKey('KL_upload_0005')); // } // if (checkfiletypes == "notsupported") { // alert($scope.profileLiterals.searchByKey('KL_CNTS_0123')); // } // }).error(function (data, status, headers, config) { // var request = { // "attachmentType": 'gallery', // "attachmentStatus": false // } // }); // } /* Web date picker */ $scope.datevar = { fromDate: new Date(), toDate: new Date() } $scope.dateFormat = 'dd, MMM yyyy'; $scope.datePickerOptions = { formatYear: 'yy', startingDay: 1, minDate: new Date(1995, 5, 22), maxDate: new Date(2030, 5, 22) }; $scope.openDatePicker = function (question, indexDate) { question._showDatePicker = !question._showDatePicker; }; $scope.datePickerDateChanged = function (date) { console.log(date); }; /* Web date picker ends */ } /* ------------------------- DIGITAL ASSISTANCE METHODS --------------------------- */ $scope.assistMemberModal = { title: 'Select member', }; $scope.searchAssistedMember = ''; $scope.assistantDetails = {}; $scope.surveyMembers = []; $scope.filterSurveyMembers = $scope.surveyMembers; $scope.openMembersDialog = function () { $scope.modal.show(); }; $scope.closeAssistedMemberModal = function () { $scope.modal.hide(); } $scope.selectMember = function (user) { $scope.assistantDetails = user; } $scope.filterUsers = function (filter) { try { filter = filter.toLowerCase(); } catch (e) { } $scope.filterSurveyMembers = $scope.surveyMembers.filter(function (member) { if ((member.firstName && member.firstName.toLowerCase().includes(filter)) || (member.location && member.location.includes(filter))) return member; }); }; $scope.getTargettedMembers = function () { $rootScope.spinerisActive = true; function addMembers(res) { $rootScope.spinerisActive = false; try { $scope.surveyMembers = JSON.parse(res.data); } catch (e) { $scope.surveyMembers = res.data; } $scope.filterSurveyMembers = $scope.surveyMembers; console.log($scope.surveyMembers); } if ($scope.isSurveyUnderProgram) { surveyService.getMembersOfSurveyUnderProgram($scope.surveyId, 0).then( function (res) { addMembers(res); }, function (err) { $rootScope.spinerisActive = false; console.log('Unable to get survey details.', err); } ); } else { surveyService.getMembers($scope.surveyId, 0).then( function (res) { // $rootScope.spinerisActive = false; // try { // $scope.surveyMembers = JSON.parse(res.data); // } catch (e) { // $scope.surveyMembers = res.data; // } // $scope.filterSurveyMembers = $scope.surveyMembers; // console.log($scope.surveyMembers); addMembers(res); }, function (err) { $rootScope.spinerisActive = false; console.log('Unable to get survey details.', err); } ); } }; $scope.constructProfilePicUrl = function (profileKey) { if (!profileKey) return ''; const BASE_URL = window.location.origin; const URL = BASE_URL + '/data/profilepics/' + profileKey + '.png?1519119679507'; return URL; }; $scope.downloadAttachment = function (attachment) { if (attachment.hasOwnProperty('url')) { var a = document.createElement('a'); a.href = attachment.url; a.download = attachment.url; //a.target = '_blank'; a.click(); } } // Initialize survey response page. $scope.init(); } ]);