{"version":3,"sources":["a3.pilot.app.js","a3.pilot.main.js","app.module.js","app.route.js","app.run.js","app.settings.js","app.version.js","Graph.settings.js","MyDirectives.module.js","AirportContacts/AirportContacts.service.js","AirportHotels/AirportHotels.service.js","Bucket/Bucket.controller.js","Bucket/Bucket.service.js","Bucket/BucketDayInfo.controller.js","Bucket/BucketModal.controller.js","Bucket/Proposal.directive.js","Bucket/ProposalInfo.controller.js","Common/DataCleaner.service.js","Common/fltSplit.filter.js","Common/Generic.service.js","Common/GenericModal.service.js","Common/GenericValues.service.js","Common/IndexedDB.service.js","Common/PushNotifier.service.js","Common/SettingsMain.service.js","Common/Update.service.js","Common/Utils.service.js","CalendarNotifications/Autoland.service.js","CalendarNotifications/calendarNotifications.directive.js","CalendarNotifications/ReminderModal.controller.js","CrewCheckIn/CheckIn.service.js","CrewCheckIn/CrewCheckInModal.controller.js","CrewInfo/CrewCall.controller.js","CrewInfo/CrewCall.service.js","CrewInfo/CrewCheckIn.service.js","CrewInfo/CrewInfo.directive.js","CrewInfo/CrewPreviousInfo.directive.js","CrewInfo/LogCall.service.js","CrewInfo/PreviousDuty.service.js","CrewRoute/CrewHotels.service.js","CrewRoute/CrewMeals.service.js","CrewRoute/CrewRoute.controller.js","CrewRoute/CrewRoute.service.js","CrewRoute/CrewRouteRefreshModal.controller.js","Extenders/Array.js","Extenders/Date.js","GroundDuties/GroundDuty.controller.js","Extenders/String.js","Directives/autoRefreshFlight.directive.js","Directives/basic-footer.directive.js","Directives/chart.directive.js","Directives/crew-meals.directive.js","Directives/flight-crew.directive.js","Directives/flightFooter.directive.js","Directives/flightHeader.directive.js","Directives/ground-crew.directives.js","Directives/ground-header.directive.js","Directives/ground-services.directive.js","Directives/mainFooter.directive.js","Directives/memos-by-category.directive.js","Directives/security-search.directive.js","Directives/showErrorMessage.directive.js","Directives/update-confirm.directive.js","Flights/AddFlight.controller.js","Flights/Calendar.controller.js","Flights/Flight.service.js","Flights/FlightCrewMember.service.js","Flights/SearchPastGDCtrl.controller.js","FlightInformation/AimsCrewMemos.directive.js","FlightInformation/AimsCrewMemos.service.js","FlightInformation/AircaftPositions.service.js","FlightInformation/event-history.directive.js","FlightInformation/flight-status.directive.js","FlightInformation/FlightConfig.controller.js","FlightInformation/FlightGate.controller .js","FlightInformation/FlightGate.service.js","FlightInformation/FlightInfo.controller.js","FlightInformation/ground-information.directive.js","FlightInformation/GroundServices.service.js","FlightInformation/PaxName.filter.js","FlightInformation/reports-panel.derective.js","FlightInformation/ssr.directive.js","FlightInformation/SyncPax.controller.js","FlightInformation/TurnAroundTimes.directive.js","GroundDuties/GroundDuty.service.js","GroundDuties/SearchPastGD.service.js","Helpers/encryptionInterceptor.service.js","Helpers/exceptionHandler.config.js","Helpers/http401interceptor.service.js","Helpers/httpCrewTokenInterceptor.service.js","Helpers/httpHeaderInterceptor.service.js","Helpers/httpProvider.config.js","Helpers/localStorageMD5.config.js","Helpers/Log.service.js","Helpers/UserToken.service.js","Helpers/Utilities.js","Training/competences.directive.js","Training/FlightCourse.controller.js","Training/instructions.directive.js","Training/training-menu.directive.js","LeaveRequest/FlexCombinations.directive.js","LeaveRequest/LeaveRequest.controller.js","LeaveRequest/LeaveRequest.service.js","LeaveRequest/LeaveRequestInstructions.controller.js","LeaveRequest/SpecificCombinations.directive.js","Login/Login.controller.js","Login/PilotAPI.service.js","Login/User.service.js","Memos/CalendarRedirectModal.controller.js","Memos/MandatoryModal.controller.js","Memos/Memo.service.js","Memos/MemoImages.service.js","Memos/MemoModal.controller.js","Memos/Memos.controller.js","Messages/Message.controller.js","Messages/Message.filter.js","Messages/Message.service.js","Messages/MessageModal.controller.js","Passengers/Passenger.controller.js","Passengers/Pax.controller .js","Passengers/PaxInfo.service.js","Report/AircraftType.service.js","Report/byCategory.filter.js","Report/OpenReportDialog.controller.js","Report/PilotReportLocalEdit.service.js","Report/PilotReportLocalEditCreator.service.js","Report/PilotReportSendToServer.service.js","Report/PilotReportSyncResult.service.js","Report/PilotReportTemplate.service.js","Report/Report.controller.js","Report/ReportGuid.service.js","Report/ReportsHistory.controller.js","Report/ReportsHistory.service.js","Report/searchTextFilterforCategories.filter.js","Report/ServerCabinReport.service.js","Report/ServerPilotReport.service.js","Report/unique.filter.js","Safety/Fatigue.controller.js","Safety/Safety.controller.js","Safety/SafetyReport.service.js","ScheduleAcknowledge/AcknowledgeModal.controller.js","ScheduleAcknowledge/ScheduleAcknowledge.service.js","SWUpdate/SWUpdate.service.js","Synch/InfoAPI.service.js","Synch/SyncAPI.service.js","Synch/Synch.controller.js","Synch/SyncLog.service.js","Ticket/Photo.service.js","Ticket/Ticket.controller.js","Ticket/TicketAPI.service.js","Ticket/TicketModal.controller.js","TrainingReadOnly/competences-read-only.directive.js","TrainingReadOnly/course-read-only.directive.js","TrainingReadOnly/grading-read-only.directive.js","TrainingReadOnly/pilot-function-read-only.directive.js","TrainingReadOnly/sector-history.directive.js","TrainingReadOnly/syllabus-progress-read-only.directive.js","TrainingReadOnly/syllabus-read-only.directive.js","Training/certificate-exam.directive.js","Training/CompetenceModal.controller.js","Training/course-footer.directive.js","Training/course.directive.js","Training/Course.service.js","Training/FlightSession.service.js","Training/grading.directive.js","Training/GroundCourse.controller.js","Training/media.directive.js","Training/ModuleHistory.controller.js","Training/non-eligible-trainees.directive.js","Training/NotificationModal.controller.js","Training/notifications.directive.js","Training/pilotFunction.directive.js","Training/releasable-module.directive.js","Training/release-warning.directive.js","Training/ReleaseSignatureModal.controller.js","Training/SignatureModal.controller.js","Training/syllabus-item-header.directive.js","Training/syllabus.directive.js","Training/TraineeSignatureModal.controller.js","Training/TrainingSession.service.js","Utilities/Debug.controller.js","Utilities/Debug.service.js","Utilities/ResetDevice.controller.js"],"names":["modalUpdates","isDownloanding","isCheckForUpdate","window","navigator","$","modal","backdrop","keyboard","show","removeClass","find","hide","success","addClass","setTimeout","noUpdate","failure","errorMessage","text","on","e","hasClass","location","reload","call","cacheHandler","cacheStatusValues","onDownloading","logEvent","onCached","onChecking","onProgress","onObsolete","onError","message","console","error","onNoUpdate","onUpdateReady","cache","swapCache","applicationCache","addEventListener","click","alert","url","origin","ajax","type","undefined","update","angular","bootstrap","document","a3_pilot_reports","module","routeConfig","$routeProvider","when","controller","templateUrl","reloadOnSearch","otherwise","redirectTo","config","runBlock","$rootScope","$timeout","$location","UserFactory","UserTokenFactory","PilotReportLocalEditFactory","SettingsMain","$anchorScroll","SWUpdateService","LogService","valid","$on","event","next","current","indexOf","$$path","isLoggedIn","preventDefault","path","initialize","serviceWorker","getRegistration","then","registration","SWRegistration","checkUpdates","yOffset","$$route","editingPage","getEditingPage","setEditingPage","getPilotReportLocalEditFromTemp","link","this","attr","debug","idbSupported","isOffline","onLine","user","getUser","token","setToken","run","constant","code","description","key","value","barOptions","pieDoughnutOptions","segmentShowStroke","segmentStrokeColor","segmentStrokeWidth","percentageInnerCutout","animationSteps","animationEasing","animateRotate","animateScale","legendTemplate","onAnimationComplete","showTooltip","segments","tooltipEvents","showTooltips","scaleShowGridLines","scaleGridLineColor","scaleGridLineWidth","scaleShowHorizontalLines","scaleShowVerticalLines","bezierCurve","bezierCurveTension","pointDot","pointDotRadius","pointDotStrokeWidth","pointHitDetectionRadius","datasetStroke","datasetStrokeWidth","datasetFill","directive","$q","URL","webkitURL","restrict","scope","maxwidth","maxheight","quality","imagetype","onfilechange","element","whenError","$apply","onFileFailureCallback","err","whenReady","img","src","HTMLCanvasElement","imageResult","dataURL","toDataURL","options","imageType","fileName","filename","fileType","onFileChangeCallback","data","onfileerror","bind","evt","target","dataTransfer","files","file","maxWidth","parseFloat","maxHeight","canvas","i","length","name","loadImage","parseMetaData","exif","orientation","get","AirportContactFactory","GenericService","objCallback","Iata","Contacts","objType","fromObjectList","objList","getAirportContactsFromStorage","list","setAirportContactsToStorage","airportContacts","saveAll","clearAirportContactsFromStorage","removeAll","getAirportContacts","airportIata","all","airport","filter","item","factory","AirportHotelFactory","Hotels","getAirportHotelsFromStorage","setAirportHotelsToStorage","airportHotels","clearAirportHotelsFromStorage","getAirportHotels","fltDate","forEach","hotel","fltActiveHotels","HotelPriorities","ActiveBegin","ActiveEnd","ActivePriority","PriorityNo","BucketCtrl","$scope","BucketFactory","MessageFactory","defaultCalendarDate","ownDuties","approvedDuties","state","isSecure","isUserSA","position","logged_user_info","aimsId","getCalendarData","showErrorMessage","selectedDate","getCalendarSelectedDate","progressBarBox","getDutyObject","responseData","Duties","SharedDuties","ApprovedDuties","number_of_messages","getMessagesFromStorage","number_of_messages_not_readen","getCountOfUnreadMessages","notification","duties","NewPendingProposalsCount","NewApprovedProposalsCount","NewRejectedProposalsCount","notificationText","IsUpdated","HasApprovedProposals","hasPrevious","createNotification","events","formatDuties","appvovedEvents","concat","fullCalendar","defaultView","calendarStyle","getCalendarViewStyle","detectMobile","getDefaultView","defaultDate","firstDay","lang","editable","draggable","selectable","selectHelper","unselectAuto","disableResizing","droppable","fixedWeekCount","nextDayThreshold","header","left","center","right","timeFormat","displayEventEnd","eventOrder","eventRender","prepend","each","className","index","icon","listViewColor","icons","otherInfos","info","label","append","num","add","eventResize","changeView","dayRender","eventClick","calEvent","shareable","isOwnDuty","isApproved","isOwnApproved","bootbox","dialog","title","buttons","cancel","callback","dutyId","gotoDayBucketView","_id","height","setCalendarViewStyle","calendar","setupView","status","statusText","dutiesEvents","log","eClassName","getEventClassName","eIcons","getEventIcons","eTitle","getEventTitle","TotalSharedDuties","eOtherInfos","getOtherInfos","Id","start","DutyBegin","DutyEnd","DutyDateS","end","sortOrder","Shareable","color","push","duty","Shared","Title","eventClass","class","hasApprovedTrade","infos","PendingProposalsCount","BookmarksCount","innerWidth","innerHeight","setCalendarSelectedDate","isOpen","closeButton","hideAll","$http","apiUrl","Content-Type","getDutyById","shareDuty","errorCallback","dutyMinified","Comments","CrewInformation","Email","Phone","post","acknowledgeProposal","proposalId","fetchProposal","createProposal","proposal","evaluateProposal","put","undoProposalStatus","fetchSharedProposal","sharedDutyId","BucketDayCtrl","$routeParams","$uibModal","isSharedLate","currentDutyId","initialized","displayMessage","hasErrors","showResponse","responseText","responseHasErrors","confirmUnshare","confirm","getData","fromShareBtn","open","size","resolve","result","refresh","isLoading","currentDutyDate","totalItems","currentPage","today","Date","dutyDay","trimmedToday","trimmedDutyDay","diffDays","DifferenceInDays","trimTime","contains","getDay","getUTCHours","checkLateShare","approvedDuty","Status","initProposalsView","returnToBucket","activeTab","proposals","toggle","Accepted","Rejected","Pending","Bookmarks","getProposalBorderStyle","textclass","State","hasTimeChange","showMobileProposalCriteria","filterProposal","isShown","isAcknowledged","hasProposals","pageOptions","viewby","itemsPerPage","maxSize","setPage","pageNo","setItemsPerPage","BucketModalCtrl","$uibModalInstance","closeDuty","close","submitted","$filter","terminal","actionDisabled","sharedCount","attrs","updateProposal","newProp","errorCall","loading","insertInformation","ProposedDuties","RequestedDuties","HasMultiDuties","AllDuties","tableMaxRowLength","matchedDuty","Proposed","Requested","createDisabled","proposedDutiesIdList","requestedDutiesIdList","onSuccessMessage","onFailureMessage","previousStatus","confirmCreateProposal","successful","Duty","Array","fetch","viewInfoModal","id","getFirstInfoIcon","getSecondInfoIcon","hasSecondInfoIcon","getTextColor","getFirstActionIcon","hasFirstActionIcon","getSecondActionIcon","hasSecondActionIcon","getFetchIcon","getInfoMessage","firstAction","secondaryAction","showEndDate","DifferenceInMinutes","showTime","dutyCommentElipsis","charNo","comments","substring","showFullComment","toggleFullCommentVisibility","ProposalInfoModalCtr","allDuties","previous","DataCleanerFactory","localStorageMD5Service","IndexedDBService","objCallbackRatings","deleteOrphanedLocalFlights","existingLocalFlights","finalLocalFlights","pilotReportLocalEdits","hasPilotReport","j","FlightId","FlightAimsId","set","CrewMealId","TimeStamp","deleteAllReports","remove","deleteAllServerData","deleteAllData","clearAll","deleteDatabase","deleteOrphanedLocalReports","existingLocalPilotReports","flights","finalLocalPilotReports","deleteSynchedLocalPilotReports","deleted","h","pilotReports","AuthorAimsId","deleteOldCrewMealsRatings","res","lastDate","setDate","getDate","crewMealIdsFiltered","r","saveOne","fltSplit","formattedFltNo","String","replace","objectType","initiate","objects","fromObject","obj","object","extend","arrayLength","GetId","getOne","save","updatedobject","newObjects","constructor","createNew","guid","deleteFromList","itemIndex","splice","newobjList","GenericValuesFactory","newObjList","newObj","Code","getValuesFromStorage","setValuesToStorage","clearValuesFromStorage","getValuesFromStorageAsStrings","objs","init","deferred","defer","request","indexedDB","onupgradeneeded","db","oldVersion","createObjectStore","keyPath","createIndex","unique","gameStore1","objectStoreNames","store4","store","onsuccess","onerror","reject","promise","storeName","entity","tx","transaction","objectStore","oncomplete","ex","onabort","addAll","count","getById","getByIndex","indexName","openCursor","IDBKeyRange","only","results","cursor","getAll","removeByIndex","openKeyCursor","primaryKey","clear","PushNotifier","FlightFactory","PaxInfoFactory","service","Generate","body","browserSupportsNotifications","Notification","permission","formatInfoToCompare","flightId","flightInfo","getFlightFromStorage","paxinfo","getPaxInfoFromStorage","CTOT","ATD","ETA","ETD","DepartureGate","DepartureStand","ScheduledDepartureTimeUTC","LastRun","toString","compareAndExtractChanges","currentData","updatedData","changes","ovalue","nvalue","moment","utc","format","oldValue","newValue","MessageGenerator","x","phrase","CheckForPermissionsAndSupport","permissionQ","requestPermission","PageMainSettings","EditingPage","getSettings","settings","settingsStored","calendarViewStyle","setSettings","UpdateService","SyncLogFactory","updater","synclog","getSyncLog","isUpdated","version","NeedsSync","updateSyncVersion","patcher","toSizeString","n","f","RangeError","v","u","gibi","tebi","Math","pow","toFixed","AutolandFactory","autolandSupportingAcTypes","autolandCount","flightsLeft","totalAEFlights","showAutolandModal","getAutolandFromStorage","setAutolandToStorage","AutolandOperations","totalAegeanFlights","aegeanFlights","date","firstDayOfMonth","getFullYear","getMonth","lastDayOfMonth","Position","IsDHC","includes","AcType","DutyDate","getAEFlightsForCurrentMonth","flightDates","map","a","ScheduledArrival","getFlightsLeftForCurrentMonth","autoland","canShowModal","canShowAutolandModal","calendarNotifications","MemoFactory","ScheduleAcknowledgeFactory","LeaveRequestFactory","CheckInFactory","GroundDutyFactory","$route","draftReports","completedReports","hasUnsetTraining","gotoUnreadMemos","gotoMessages","gotoLeaves","reportsCounter","parseInt","acknowledge","showPanel","showAutolandReminder","showScheduleChangesReminder","hasScheduleChanges","openCheckIn","showCheckInAction","hasManualEntry","gotoGroundDutyInfo","GroundDutyId","removeManualEntry","groundDuty","removeGroundDuty","leaveRequest","getLeaveRequestInformation","leaveRequestCloseDate","CloseDate","unreadMemosCount","getUnreadMemos","memos","Category","retVal","checkInInfo","getCheckInInfoFromStorage","AimsId","now","std","STD","minFetchTime","maxFetchTime","isAfter","isBefore","hasAEFlights","prepareAutolandData","$root","GroupStatus","showNotificationPanel","showScheduleChangesModal","showReminderModal","manualGroundDuties","getManualGroundDutiesFromStorage","manualDuties","hasPendingCourse","findManualEntries","ReminderModalCtrl","updateShowScheduleChangesModal","response","setCheckInInfoToStorage","checkInFailedCallBack","checkIn","confirmed","Confirmed","ErrorExplanation","updateCheckInCallBack","saveCheckInDelay","delayMinutes","DelayMinutes","updateCheckInDelayCallBack","CheckInModalCtrl","GetCheckInInfoFromServer","showContent","handleRefreshResponse","responseObj","handleSubmitResponse","handleDelayMessageResponse","CheckInAction","BackToActions","ConfirmCheckIn","SendDelayMessage","selectedDelayMinutes","onMinutesChange","minutes","numberDown","numberUp","CrewCallCtrl","crew","CrewCallFactory","LogCallFactory","crewId","beforeCall","logData","Requester","Requestee","saveLogCall","LogCall","CrewId","phoneNumber","getCrewCallsFromStorage","setCrewCallsToStorage","saveCrewCall","crewCall","getCrewCallFromStorage","getFlightCrewCallsFromStorage","cleanOldData","flightIds","phoneNumbers","keepingPhoneNumbers","dateSTD","fromUTC","dateSTA","STA","sta","cleanFlightCrewNumbers","saveFlightPhoneNumbers","PhoneNumber","FlightCheckInsFactory","CheckIn","WillBeThereAt","getCrewCheckInFromStorage","setCrewCheckInToStorage","updateFlightCrewCheckInToStorage","storedCheckInsFiltered","FlightInfo","getFlightCrewCheckInFromStorage","previousCheckIns","crewInfo","openPhoneConfirmation","showInfoRow","differentUser","phoneAvailable","previousDutyAvailable","PreviousDuty","isDifferent","phonesAvailable","checkInStatusAvailable","crewMembers","isDHC","crewPreviousInfo","filterByPreviousDuty","getLogCallsFromStorage","cleanLogsFromStorage","PreviousDutyFactory","getPreviousDutiesFromStorage","setPreviousDutiesToStorage","savePreviousDuty","previousDuty","getPreviousDutyFromStorage","getFlightPreviousDutiesFromStorage","previousDuties","cleanFlightPreviousDuties","saveFlightPreviousDuties","CrewHotelFactory","showHotelsAcTypes","CrewName","Base","Airport","HotelNo","HotelName","GroundTime","getCrewHotelsFromStorage","setCrewHotelsToStorage","showHotelsInCalendar","CrewMealFactory","CateringMealId","Description","ratingSubmitResponseObj","getCrewMealsFromStorage","setCrewMealsToStorage","getCrewMealFromStorage","cateringMealId","crewMeals","sendCrewMealsRatingReport","ratingForm","objectToAdd","saveReportSuccessCallBack","hasRating","crewMealId","some","getCrewMealsDidNotEatReasons","CrewRouteCtrl","CrewRouteFactory","dutyNo","crewRouteDuty","getCrewRouteFromStorage","groundDuties","getGroundDutiesByDutyNo","DutyType","Start","getFlightsByDutyNo","flight","ScheduledDeparture","crewRoute","currentDutyDay","differentDay","day1","day2","openRefresh","crewroute","transferData","sync","forceSync","DutyDay","DutyNo","Route","CrewMeals","getCrewRoutesFromStorage","setCrewRoutesToStorage","crewRoutes","setCourseCompleted","courseId","cr","FlightIds","getFlightsFromStorage","crewRouteCourse","Courses","CourseId","isSame","flightCourse","updateFlight","setCoursePending","CrewRouteRefreshModalCtrl","InfoAPIService","SyncAPIService","FlightSessionFactory","CourseFactory","isRefreshing","refreshResultsVisible","collapse","isCollapsed","Number","DataStatus","datatype","isTraining","currentFlights","currentGroundDuties","refreshCrewRoute","newFlights","newGroundDuties","needsSynch","updateFlightStatusSetter","setupFlightInfo","updateFlightLocalStorage","updateFlights","trainingCourses","TrainingCourses","trainingCourse","upsertCourse","course","applyTraineeInfoToSession","FlightDate","session","updateGroundStatusSetter","setupGroundInfo","updateGroundDutyLocalStorage","updateGroundDuties","prototype","dynamicSort","property","orderByAsc","sortedArray","sort","b","arr","toUTC","getTime","getTimezoneOffset","setHours","_DatetoJSON","toJSON","groundDutyId","_nonIterableSpread","TypeError","relatedTrainees","_iterableToArray","iter","Symbol","iterator","Object","from","_arrayWithoutHoles","elem","isArray","_arrayLikeToArray","len","not","arr2","_typeof","firstDate","secondDate","diffInMins","date1","date2","floor","diffInDays","MinutesToString","hours","mins","AddDays","days","valueOf","endsWith","suffix","startsWith","str","reverse","split","join","getHash","shaObj","jsSHA","autorefresh","$interval","AircaftPositionsFactory","browserNotificationsEnabled","autoUpdateInterval","autoUpdateIntervalTimeOffset","showAlternativeNotifications","showAutoUpdatePanel","ScheduledDepartureTimeStamp","autoflightInfoInterval","currentInfo","intervalTime","departureTime","depTimestamp","nowTimeStamp","absoluteMinuteDiff","abs","timerDelayGenerator","getPax","getFlightFromTotalFlights","paxInfo","aircaftPositions","getAircaftPositionsByFlightId","flightETA","updatedInfo","DepartureEU","radioModel","$watch","basicFooter","gotoMessageLibrary","gotoFAQs","gotoBucketCalendar","gotoCalendar","logout","clearActiveUser","template","chartObject","chart","context","getContext","width","Chart","chartType","chartInstance","destroy","$sce","attributes","togglePanel","panelId","route","HasRegChanged","noClicked","clearFormData","yesClicked","submitRatingClicked","flightCrewMeals","CrewMealsDescriptions","findIndex","HasRating","manageResponseMessage","canceClicked","isFlightPanel","isRoutePanel","routeCrewMeals","showCrewMealsPanel","Rating","DidNotEatReasonId","submitRatingMessage","DidNotEatReasons","popoverInfo","trustAsHtml","contentHtml","FlightCrewMeal","hasRegChanged","FlightNo","FlightDeparture","values","CrewMealsCateringIds","crewMealDetails","keys","getFlightsByFlightId","acTailNo","AcTailNo","panelToShow","flightFooter","orderByFilter","ReportGuidFactory","handleIfReport","report","getPilotReportLocalEditForFlight","ReportGuid","deleteTempReport","restoreGuid","openReportDialog","gotoFlight","returnTimeDiff","paxTimeDiffInMins","round","nextFlight","previousFlight","currentFlight","getFlightsByRoute","getPreviousAndNextFlights","messagesCount","unreadMessagesCount","messages","getMemosForFlight","memosForCurrentFlight","getMessagesFromIds","ReadDt","departure","openSyncPopover","firstSyncWarning","secondSyncWarning","lastSync","enableSyncPopover","showTimeDiff","gotoFlightInfo","openPilotReport","encodeURIComponent","getLocalFlightFromStorage","serverReportForThisUser","getServerPilotReportForUser","serverReportsByAnotherUser","getServerPilotReportsByAnotherUser","localReport","ReportId","openReport","resetDevice","danger","gotoMemosLibrary","gotoPaxInfo","showMobileMenu","userPosition","SynchPaxAndGates","gotoTicket","goToSafetyReport","goToFatigueReport","syncWarning","toggleCrewList","dynamicSize","CrewMembers","Trainees","groundServices","GroundServicesFactory","PilotReportLocalEditCreatorFactory","arrival","isInFinalState","LineStatus","saveNewUsedState","createNewLocalReportForFlight","DepartureGroundServices","ArrivalGroundServices","saveReport","updateFlightFromReport","setPilotReportToStorage","getGroundServicesByStation","checkForNewGroundServices","mainFooter","getMemosFromStorage","memosCount","gotoMemos","leaveRequestInformation","gotoLeaveRequests","memosByCategory","MemoImagesFactory","day","filterMemos","distinctMemos","normalizeMemos","allMemos","distinctMemosAll","getMemoImagesFromStorage","allMemoImages","distinctData","sortData","imageId","normalizeMemoImages","distinctMemosImagesAll","q","deleteIndexedDB","setMemosToStorage","setMemoImagesToStorage","recreateIndexedDB","memo","memoList","LastUpdated","memoDateA","memoDateB","temp","getMemosForCrewRoute","getMemosForGroundDuty","openMemo","saveOneMemoToStorage","markGroundDutiesUnread","securitySearch","showSecurityMsg","securitySearchRequired","DepartureUK","DepartureCDG","DepartureCountry","Departure","PreviousEU","hasMessage","updateConfirm","needUpdate","waiting","checkVersionExpiration","AddFlightCtrl","AircraftTypeFactory","doCancel","doAdd","processForm","minSelectableDate","maxSelectableDate","minSelectableDateStr","maxSelectableDateStr","selectedTime","hstep","mstep","ismeridian","dateFormat","hourFormat","datepicker","opened","openDatepicker","createFlightFromUIValues","flightDate","formData","flightDateStr","flightSTD","flightTimeStr","getHours","getMinutes","flightNumber","flightDeparture","flightDestination","flightRegNo","flightAcType","createLocalFlight","actypes","getAircraftTypesFromStorage","aircraftTypes","formFlight","$valid","newFlight","saveLocalFlight","CalendarCtrl","TrainingSessionFactory","pendingOverdueReports","storageUsage","usedSize","isReload","NeedsToSync","getFlightsFromStorageAndCheckIfTooOld","getLocalFlightsAndMergeWithServerFlights","needsToSync","getGroundDutiesFromStorage","crewRoutesEvents","routes","crewRouteEvents","classname","second_icon","courseStatuses","courses","trainingStatus","dutyEnd","duration","diff","asHours","courseIds","flightSessions","dutyBegin","existingSessions","s","isBetween","HasLimitedInfo","trainees","formatCrewRoutes","groundDutiesEvents","groundEvents","RelatedGroundDuties","coursesFlat","relatedDutyCourse","groundSessions","existingSession","Unread","formatGroundDuties","flightEvents","getRoute","TrainingIndicatorCode","IsScheduleChanged","isScheduleChanged","formatFlights","specialDates","getScheduleChangesFromStorage","crewHotelsEvents","hotels","endOf","formatHotels","cell","objdate","_d","dayClick","gotoCrewRouteInfo","lastLog","canShowSync","isOpenUpdateModal","openSynch","getMandatoryUnreadMemos","mandatoryUnread","addFlight","searchPastGroundDuties","setLastShow","synchresult","savedGroundSessions","savedFlightSessions","$log","ServerPilotReportFactory","ServerCabinReportFactory","FlightCrewMemberFactory","liveVersion","Flight","CrewAimsId","Arrival","LineStatusDescr","LocalReportId","ServerReportLink","ScheduledDepartureDateUTC","LocalReportHasNothingToReport","ServerReportHasNothingToReport","CabinReportId","IsLocal","cabinReports","pilotReportStatusDescr","BookedC","BookedY","BookedInf","BookedPad","BookedChld","ActualC","ActualY","ActualInf","ActualPad","ActualChld","DepartureICAO","DepartureName","ArrivalICAO","ArrivalCountry","ArrivalName","DepartureTimezone","ArrivalTimezone","CallSign","FlightsFilters","Zones","getDescription","initializePilotReportStatus","getPilotReportStatusDescr","dataIsRecent","setFlightsToStorage","storeFlightsWithReportsAndMessages","flightsX","pilotReportsX","cabinReportsX","messagesX","pr","me","fi","pri","Source","constSourceStoredOwn","constSourceStoredOther","cri","mi","QueryType","trim","Country","FlightDirection","AirportA","AirportB","Registration","clearFlightsFromStorage","datetime","number","destination","regno","actype","localFlights","flightIndex","serverFlights","markScheduleChangedFlights","oldFlights","exists","lastScheduleDate","getLastScheduleDate","initializeFlights","mergeFlightInfo","currentFlightInfo","DepartureSchengen","ArrivalSchengen","ArrivalEU","ATA","DepartureCountryISO","ArrivalCountryISO","getCabinReportId","CabinReportLink","allflights","reportIndex","userAimsId","hasServerReportForThisUser","hasServerReportsByAnotherUser","NothingToReport","ReportedItems","GenericModalFactory","FlightCrewMember","sex","shortname","SearchPastGDCtrl","PastGroundDutyFactory","isCourseLimited","hasError","closeModal","searchGD","getPastGroundDuties","availableCources","pendingDuties","pendingGroundDuties","isManualEntry","addGroundDuty","aimsCrewMemos","AimsCrewMemosFactory","getAimsCrewMemosByDate","Line","OrderNo","getAimsCrewMemosFromStorage","setAimsCrewMemosToStorage","clearAimsCrewMemosFactoryFromStorage","crewMemos","datesMemos","PreviousFlightNo","PreviousStation","PreviousSTA","PreviousETA","PreviousATA","PreviousGATE","PreviousSTAND","NextFlightNo","NextStation","NextSTD","NextETD","NextATD","NextGATE","NextSTAND","getAircaftPositionsFromStorage","setAircaftPositionsToStorage","clearAircaftPositionsFromStorage","updateAircraftPositionsToStorage","aircraftPositions","flightStatus","FlightConfigCtrl","dismiss","ETAdate","STDdate","ETAtimestamp","STDtimestamp","setUTCFullYear","getUTCFullYear","setUTCMonth","getUTCMonth","setUTCDate","getUTCDate","FlightGateCtrl","FlightGateFactory","items","distinct_gates","searchFilters","gates","getAfterSTDFromStorage","isConnectedFlightClose","connection","connFlightDate","TimeDifference","time","timeString","sign","dayString","ms","daysms","hoursms","substr","IsOld","searchText","addFilter","filters","toUpperCase","applyFilter","removeFilter","TotalFlights","Dep","connectingTime","STD_lcl","flightGateTime","Codeshares","distinct_gate","Gate","DepGate","Arr","pax","UpdatedDate","lastUpdate","flightArrivalTime","timeDate","newFlightgates","hasGates","FlightGate","STD_Diff","STA_Diff","STA_lcl","ETD_lcl","ETA_lcl","DepStand","previousUpdate","previousGate","previousSTD","previousSTD_lcl","previousSTD_Diff","previousSTA","previousSTA_lcl","previousSTA_Diff","dtSTD","dtSTA","dtETD","dtETA","dtSTD_lcl","dtSTA_lcl","dtETD_lcl","dtETA_lcl","timeSTD","timeSTA","timeETD","timeETA","timeSTD_lcl","timeSTA_lcl","timeETD_lcl","timeETA_lcl","hasETD","hasETA","depDelay","arrDelay","setUpdatedNow","gateChanged","stdChanged","staChanged","stdDiffChanged","staDiffChanged","changesToString","getKey","stringIsoToDateTime","dt","year","month","stringIsoToDateString","stringIsoToTimeString","self","hour","min","getFromStorage","setToStorage","processUpdatedData","listPrevious","flightPrevious","hasChanged","previousLength","p","dep","flightgates","dateETD","FlightInfoCtrl","showCatIIApprachAcTypes","showGroundInfoAcTypes","hasIcon","crewCheckInStatuses","dutyDate","crewPhoneNumbers","hideSidePanel","shownSideMenu","sideMenuItems","showSidePanel","menuItem","html","goToPanel","hash","onlyUnique","phoneNumberInfo","startOf","previousDutyInfo","isFlight","arrivalDate","showArrivalDate","departureDate","showDepartureDate","showDate","GroundDutyDate","statuses","flightCrewPreviousDuty","cabinCrewPreviousDuty","dhcCrewPreviousDuty","hasPreviousDuties","dayOfFlight","showCatIIApprachSection","showGroundInfoSection","isEnabled","isPanelOpen","IsProvisional","showConnFlights","flightZones","zones","zoneTitles","Class","zone","RenderFlightZones","openMessage","markReaden","getTextClass","getTopClass","getBottomClass","crewChart","cp","fo","sa","fa","dhcCp","dhcFo","dhcSa","dhcFa","labels","datasets","fillColor","strokeColor","highlightFill","highlightStroke","generateCrewChart","cStat","PaxTotalC","ConfigurationC","yStat","PaxTotalY","ConfigurationY","listSentTimestamp","MCT","openFlightConfig","selectedItem","toggleViewMode","openGates","groundInfo","printHotelType","HotelType","printContactType","contactType","stations","stationsInfo","filterHotelType","filterContactType","showInfo","station","stationInfo","Name","ActiveHotels","ActiveContacts","ActiveGeneralInfo","contactInfo","ContactTypes","distinct","ContactType","findDistinctContactTypes","hotelInfo","HotelTypes","findDistinctHotelTypes","objCallBack","Station","getGroundServicesFromStorage","setGroundServicesToStorage","Services","IsDefault","Used","clearGroundServicesFromStorage","paxNames","input","PassengerSummaryC","Passengers","PassengerSummaryY","PRM","UMNR","DEP","reportsPanel","showSafetyReport","trimmedFlightDate","openCabinReport","ssr","ssrCodes","showRecomendedWaterAcTypes","totalPax","startDate","endDate","detailedInfo","properties","propertiesArray","htmlPopover","Total","FQTVGold","FQTVSilver","DEAF","BLND","DPNA","INAD","MEDA","CBBG","OTH","showFQTVGold","showFQTVSilver","showUMNR","showPRM","showDEAF","showBLND","showDPNA","showDEP","showINAD","showMEDA","showCBBG","showOTH","waterQuantity","showRecomendedWater","SyncPaxCtrl","hideElements","showOnSuccess","showOnEmptyData","showOnSuccessNoFlightData","showOnOutOfDateRange","isFetchingFlightData","flightDataStatus","updateStatusGenerator","newDuty","Error","msg","JSON","stringify","CabinServiceManagementLists","turnAroundTimes","turnAroundTimesSupportingAcTypes","showTaTpanel","supportsTurnAround","TaTMinutes","startofTAT","prevATA","prevSTA","lateArrival","inadequateGroundTime","comparedValue","ShowlateArrival","GroundDutyCtrl","toggleEditMode","selectTrainee","trainee","Absent","updateGroundDuty","dutyCourses","refreshGroundDuty","DutyId","CourseIds","refreshSuccess","getGroundDutyFromStorage","getGroundDutyActiveCourses","traineesFlat","related","DutyDescription","Instructors","setGroundDutiesToStorage","instructors","IsInstructor","mergeGroundDutyInfo","currentGroundDutyInfo","GroundDutyNo","apply","_toConsumableArray","groundDutyCourse","allCoursesAreCompleted","every","relatedDuty","mergeGroundDutiesToStorage","incomingDuty","incomingTraineesFlat","incomingTrainee","existingDuty","existingTraineesFlat","existingTrainee","encryptionInterceptor","method","encryptedData","absolutePath","lastIndexOf","exceptionConfig","$provide","decorator","extendExceptionHandler","$delegate","exception","cause","http401interceptor","headers","isError","responseError","rejection","httpCrewTokenInterceptor","$$url","expiresAt","crewToken","expires","httpHeaderInterceptor","aimsIdToString","toJson","httpProviderConfig","$httpProvider","defaults","useXDomain","common","interceptors","localStorageMD5Config","localStorageMD5ServiceProvider","localStorageServiceProvider","exec","href","setStorageType","setPrefix","setStorageCookie","enableCompression","$injector","$window","lastError","stackTrace","getToken","contentType","errorUrl","beforeSend","setRequestHeader","loggingError","warn","stack","arguments","errorDescr","timestamp","postFilter","s4","random","sort_by","field","primer","A","B","validateTraineeCompetences","Grading","_unsupportedIterableToArray","GradingMessage","competence","GradeA","GradeB","o","minLen","slice","test","IsMultiday","FlexCombination","seasonConfiguration","seasonRequest","sortSetupOrderNo","period","LeaveRequestPrioritySlots","setupOrderNo","MockLeaveRequestPrioritySlots","assign","LeaveRequestPriorityPeriods","temp2","fromJson","sortableOptions","handle","stop","removeSlot","slotIndex","LeaveRequestPrioritySlotsHelper","LeaveRequestCtrl","setupMockLeaveRequestPriorities","priorities","slots","tempOrderNo","findSlot","onSuccessSendRequest","closeDateStr","LeaveRequestInformation","ShowSuccessMessage","ShowErrorMessage","onErrorSendRequest","getRandomBorderColor","season","cssClass","Configuration","getRandomTextColor","IsValidLeaveRequest","isValid","LeaveRequest","RequestNoleave","invalidSelectedLeaveDays","LeaveRequestSeasons","LeaveRequestPriorities","HasInvalidPeriod","showHelp","showSuccessLeaveApplicationMessage","getConfigurationDetails","QualificationGroup","RequestLessDays","RequestNoLeave","YearId","MemberId","seasons","HasSpecificCombinations","Type","SeasonId","StartDate","EndDate","Slots","Configurations","ConfigurationId","mergeRequest","Seasons","leaveRequestSeason","configurationDays","Days","Priority","initializeNewRequest","updateLeaveRequestSeason","Periods","ConfigurationPeriodId","parse","totalDays","hasConfig","LeaveDays","showCombo","radioConfigurationModel","sendRequest","saveLeaveRequest","addComment","leaveRequestApiURL","saveLeaveRequestInformation","cleanRequest","LeaveRequestInstructionsCtrl","normalizePage","page","instructionPages","nextPage","previousPage","SpecificCombinations","seasonRequests","recalculatePriorities","specificCombinations","resetEditablePeriods","isEditable","IsEditEnabled","selectEditablePeriod","selectedSlotTemp","selectedRequestTemp","selectedSlotDaysTemp","updateEditablePeriod","slot","removeSpecificCombination","priority","indexOfRemovedObj","addNewSpecificCombination","newSpecificCombinationPriority","getBorderClass","hasEmptyFields","hasFilledFields","isDisabled","CSSclass","EndDay","StartDay","LoginCtrl","isSupported","isLoggingIn","goSecure","errorName","goNormal","moreInfo","toggleMoreInfo","un","val","pw","formLogin","txtName","$setViewValue","txtPass","username","$modelValue","password","login","tokenExtended","showTokenExtensionForm","Message","showExtendTokenBootBox","extendToken","getElementById","readOnly","PilotAPIService","hashedPwd","syncDialogLastDt","aimsid","setUser","setActiveUser","act","onfinally","localUser","newHashedPwd","usr","Token","CalendarRedirectModalCtrl","MandatoryModalCtrl","gotoMandatoryUnreadMemos","Memos","Memo","addMemoToStorage","ValidateCountryCategory","criteria","isDepartureCategory","isArrivalCategory","Special","Field","FieldOptional","departureField","arrivalField","special","isDeparture","isArrival","PassengersHasSsrCode","memoCriterion","PassengerSummaryX","isValidZone","CriteriaZone","FlightZones","getAllUnreadGroundDutyMemos","memosCollection","unreadGroundDutyMemos","MemoCriteria","clearMemosFromStorage","flightMemos","ValidFrom","ValidTo","AcRegistration","RouteStart","RouteEnd","ViceVersa","TrainingIndicatorId","getStoredMemosIds","memoIds","memoIdRead","deleteMemoFromStorage","MemoId","setMemosFromServer","memoIdsToSend","lastSyncDate","IsMemoIncluded","IsNew","groundDutyMemos","fromDutyDate","toDutyDate","getAllPaxInfoFromStorage","paxInfoResult","inserted","g","Zone","IsMandatory","z","addMemoImageToStorage","MemoImage","MemoImages","saveOneMemoImageToStorage","deleteMemoImageFromStorage","MemoImageId","deleteMemoImageByMemoId","setImagesToServer","images","clearMemoImagesFromStorage","getMemoImagesByIndex","MemoModalCtrl","hasCountry","hasFlightNo","hasAirport","hasRoute","hasAcType","hasZone","hasEuropean","hasSchengen","hasAcRegistration","hasSsrCode","hasTrainingIndicator","hasGroundDuties","hasNone","showImage","image","Image","write","outerHTML","Body","MemosCtrl","searchResultsCount","sum","searchResults","MemosByCategories","filterList","selectMemoCategory","category","selected","toggleSidePanel","searchMemos","filteredMemos","toLowerCase","newList","memoTitle","memoBody","select","active","tommorowTimestamp","expired","MessageCtrl","messageCount","isEnable","AuthorName","PositionCP","PositionFA","PositionFO","PositionSA","FeedbackCause","setMessagesToStorage","clearMessagesFromStorage","Ids","selectedMessages","getUnreadMessages","filteredMessages","messageId","markReadAsSynched","readMessages","Synched","getUnsynchedReadMessages","filtered","storeMessagesFromServer","MessageModalCtrl","messageBody","PassengerCtrl","passenger","PaxCtrl","showMobileMenuFilters","filterPax","filterPaxC","initializeFilters","filterPaxY","filterAdults","filterChildren","filterInfants","filterFqtvSilver","filterFqtvGold","filterConnections","showConnections","filterUMs","filterSpecialMeals","showMeals","filterWheelchair","filterAssistance","filterDeportees","filterDHC","viewMode","mode","showPaxName","showDetails","filterRow","row","filterFqtv","Columns","filterCol","howClose","openPassenger","inputObject","IsEmptySeat","SeatMode","resetFilters","initializeViewMode","specialMeals","connectingPax","ConnectingFlights","Seatmap","SpecialMeal","SpecialMealB","ConnectingFlightId","Connection","col","IsValid","Cabin","InfantName","Fqtv","SSR","IsUMNR","TierLevel","IsGroupPRM","IsDEAF","IsBLND","IsDPNA","IsINAD","IsGroupDEP","STD_utc","STA_utc","MarketingFlightNos","SupplementaryInfo","Offpoints","ConnFlights","curtainRows","Statistics","GetStatistics","cabinType","RowNo","savePaxInfoToStorage","paxInfos","setPaxInfoToStorage","updatePaxInfo","toObjectList","setAircraftTypesToStorage","clearAircraftTypesFromStorage","questions","query","out","CategoryLabel","Label","OpenReportDialogCtrl","canCreateNewLocalReport","allServerReports","IsSameUser","serverReports","createNewLocalReport","openLocalReport","openServerReport","PilotReportLocalEdit","AuthorId","Created","Sections","ActiveItems","WarningItems","AutolandSatisfactory","AutolandUnsatisfactory","AutolandWorkOrderNo","AutolandWorkOrderNoIsValid","catApproachUnsatisfactory","catApproachSatisfactory","GroundServicesSectionHasValue","updateTotals","saveReportAsTemp","allActiveItems","allWarningItems","sectionCount","sectionActiveItems","sectionWarningItems","itemCount","Items","ItemHasValue","ItemValue","allReports","getPilotReportsFromStorage","setPilotReportsToStorage","getPilotReportLocalEdit","reportGuid","depStorageGroundServices","found","ServiceType","deleteReport","updatedReports","pilotReportLocalEdit","getPilotReportLocalEditCountThatNeedToBeSynched","getPilotReportLocalEditThatNeedToBeSynched","getNewReport","markReportAsSynched","PilotReportTemplateFactory","flightAimsId","existingReport","newReportGuid","getNextGuid","reportTemplate","getPilotReportTemplateFromStorage","newReport","PilotReportSendToServerFactory","PilotReportSendToServer","AuthorCrewId","AuthorCrewAimsId","Autoland","PilotReportSendToServerItem","TemplateItemId","Value","Remarks","getReportFromPilotReportLocalEdit","newItem","getCompletedListFromPilotReportLocalEdits","cabinReportLocalEdits","fixUsedValueLS","PilotReportSyncResultFactory","Result","getSyncResult","syncResults","getPilotReportSyncResultsFromStorage","setPilotReportSyncResultsToStorage","pilotReportSyncResults","clearPilotReportSyncResultsFromStorage","getSuccesses","getFailures","PilotReportTemplate","PilotReportTemplateItem","PresetComments","PilotReportTemplateSection","rptt","sectionsTemp","sct","itemsTemp","itm","setPilotReportTemplateToStorage","pilotReportTemplate","clearPilotReportTemplateFromStorage","ReportCtrl","aircraftLateArrivalReportId","inadequateGroundTimeReportId","discard","reportId","newLocalReport","infoSaveOperation","setCategory","section","newCategoryFilters","categoryFilters","categoryfilters","deleteReportClicked","autoAdjustTarget","autoAdjustTimer","autoAdjustRun","t","style","overflow","scrollHeight","saveDraftClicked","saveClicked","cancelClicked","reportItemValueChanged","adjustTextarea","$event","clearTimeout","clearRemarks","reportChanged","AutolandChanged","CatApproachChanged","isValidWorkOrderNo","workOrderNo","validationWorkOrderNo","isNaN","logIt","showAutolandSection","panels","showOnlyOne","visible","catApproach","GetCategoryCSS","itemsInCategory","completed","countDHC","schedullDepartureTimestamp","isFuture","showCompleted","compressedMode","showAll","categoryFilter","infosaveactiontype","infosaveaction","Guid","reportGuids","guidList","getReportGuidsFromStorage","setReportGuidsToStorage","clearReportGuidsFromStorage","validGuidIndex","resultingGuid","getRemainingReportGuids","repGuid","ReportsHistoryCtrl","ReportsHistoryFactory","reportType","fetchReports","getReportsHistory","contentToShow","reports","showError","handleResponse","checkConnectionStatus","ImageData","imageData","closeImage","isNothingToReport","constSourceLocalOwn","constSourceLocalOther","uniqueList","FatigueCtrl","SafetyReportFactory","confirmCreateFatigueReport","saveFatigueReport","alertStyle","responseMessage","flightNo","flightDep","flightArr","flightRegistration","occurenceTitle","attachedFiles","sizeLimitKb","fileTooLargeMsg","fileUploaded","fileResult","uploadedFile","fileBlobb","showMaxFiles","removeFile","attachedFile","arrayLenght","showMaxImages","appendPhoto","isIFileTooLarge","isLarge","submitFatigueReport","fatigueReport","SafetyCtrl","operationalPhases","clearForm","atcCallsign","alertType","usefulness","originalRa","subsequentRa","isRaFollowed","eventLocation","airMiss","trafficBearing","distance","altitude","relativeAltitude","visualContact","seatbelt","paxNo","birdSpecies","numberSeen","birdNo","birdSize","areaOfDamage","speed","hasPilotWarned","birdEventLocation","runwayUsed","eqpwsEventLocation","confirmCreateReport","saveSafetyReport","tcas","egpws","bird","selectedCategory","categories","usefulnesses","selectedPhase","meteo","trainingFlight","seatbeltSign","isFileTooLarge","showSelectedCategory","submitForm","formFlightReport","submitResponseObj","getResponse","getResponseFailed","safetyReport","aqdBaseURL","AcknowledgeModalCtrl","ConfirmAcknowledge","acknowledgeChanges","Results","dates","setAllScheduleChangesToStorage","scheduleChanges","dateList","dateS","stringToDate","fistChange","datesToAcknowledge","DatesWithChanges","updateScheduleChangesCallBack","acknowledgeFailedCallBack","register","reg","refreshing","postMessage","updateStatusSetter","dataStatus","array","AircraftPositions","updatePilotReportLocalEditFromSynch","FlightCourses","newDutyInfo","updateCrewCheckIn","crewRouteInfo","to","relativeFlightMatcher","oldflight","relativeFlights","oldFlightNo","lastDigit","setPilotReportReportToStorage","doSync","allSavedReports","reportsToSend","messagesToSend","phoneCallLog","CrewCallReports","syncData","SyncPilotReports","Messages","MemoIds","CrewCallLog","LastSyncDate","SyncPilotData","orgFlights","flightData","CrewRoutes","CateringCrewMeals","CrewHotels","CrewCheckInInfo","ScheduleChanges","ResponseSuccess","rawTrainingCourses","setCoursesFromServer","flightGates","AircaftPositions","AirportContacts","AirportHotels","serverMemoIds","Images","cabinServiceManagementLists","guids","GroundServices","reportResults","syncResult","setSyncLog","toDate","verifyFlightAimsIds","verifyFlightIds","missingIds","missingAimsIds","m","SynchCtrl","syncResultsVisible","isSynching","reportstobesynched","number_of_reports_to_sync","isFirstSync","isTooOldSync","syncVersion","reportCredits","syncTableData","doSynch","showSyncResults","ok","syncResultsTableData","syncSuccesses","syncFailures","reports_to_sync","sync_successes_descr","sync_failures_descr","unreadMessages","syncResultsOk","SyncLog","lastShow","can","newLog","syncLog","clearSyncLog","setLastScheduleDate","PhotoFactory","Photo","RemarksShort","PhotoData","FileType","TicketCtrl","TicketAPIService","ticket","photos","maximumAttatchedPhotos","photo","imageTooLargeMsg","gotoHome","Version","sendTicket","validateTicket","imageUploaded","isImageTooLarge","removePhoto","isLogged","DeviceData","sizeActual","getStoredValues","TicketModalCtrl","Competences","hasSelectedSubCompetence","SubCompetences","Selected","phases","leftScroll","querySelector","scrollLeft","rightScroll","selectedTraineeSession","traineeSession","showSession","selectedTraineeBadge","selectedAbsentTraineeSession","PhaseId","TraineesSessions","grading","GradeType","pilotFunctionReadOnly","history","phase","syllabusGroups","traineeSessionItems","showRemarks","oneAtATime","filterItems","showItem","hasRemarks","toggleItems","ItemsGrouped","syllabusGroup","Syllabus","SyllabusItems","syllabusItem","Tries","relatedSessionItem","SyllabusProgress","SyllabusItemId","TryGrading","attempt","historyTriesCount","isReadOnly","newTriesCount","TriesPerformedCount","completedItem","MandatoryCount","PanelClass","setPanelStyle","SelectedGroup","setPanelStyleByProgress","setPanelStyleBySelected","group","firstTry","certificateExam","collapseAll","validateTrainee","getRemainingCharacters","max","gradeUp","isCertificateValid","Grade","gradeMax","gradeDown","isExamValid","gradeMin","dutyCourse","isGround","gradeBase","ReleaseGrading","CertificateGradeBase","validateGrading","CertificateOutcome","calculateOutcome","updateSession","isAllOpen","Session","gradingStatus","sessions","EligibilityStatus","CompetenceModalCtrl","competences","gradingSelection","missingGrading","c","missingPerformanceIndicators","hasMandatory","sub","isCompetenceValid","manageCompetenceGrading","hadMandatory","hadOptional","hasOptional","MandatorySub","OptionalSub","showComments","GradeC","GradeD","GradeE","selectSubCompetence","openGradingModal","courseFooter","gotoGroundDuty","gotoCrewRoute","trainingFlightIds","TrainingFlightIds","Media","setReleaseStatus","ShowReleaseWarning","AvailableRelease","checkReleaseAvailability","requiresTraineeSignature","endOfSessionSignature","DayGrading","TraineeSignature","endOfModuleSignature","ReleasedPhase","RequiresTraineeSignature","Authorized","allSignaturesComplete","someSignaturesComplete","MinDays","MinSectors","phaseInfo","Phases","completedDays","completedSectors","Sessions","pastSession","Sectors","CompletedDays","CompletedSectors","ModuleType","AircraftTypes","visitedAircrafts","AircraftTypesVisited","inputAircrafts","pendingAircrafts","pairPendingAircrafts","pendingArviList","arvi","showReleaseWarning","selectedTrainee","mergeSyllabusItemWithSession","sessionItem","RepeatRequired","deepCopy","originalObject","setTraineeCompetences","traineeCompetences","traineeCompetence","existingCompetence","y","commonSub","setSubCompetenceValues","updated","first","last","manageSubmission","sessionSectors","sector","PM","PF","SessionSectorSeats","PilotFunctions","sectors","pilot","NonApplicable","PMsector","sec","isPM","PFsector","isInstructor","relevantSector","seat","Seat","submittedSession","SessionDate","GroundDutyIds","AircraftVisits","SelectedMedia","SyntheticDeviceId","selectedDevice","selection","ReleaseGradeType","TraineeSessions","SyllabusVersionId","PrepareSessionForSubmission","requiresInstructorSignature","syllabusSignature","SignatureRequired","selectedItems","traineeSelectedItems","Set","syllabusItemSignature","InstructorSignature","RequiresInstructorSignature","confirmationMsg","ConfirmationMessage","releaseGrading","modalInstance","submitSession","SaveSession","isReleased","sessionTrainee","syllabusItems","performedTries","mandatoryCount","Released","withRelease","SignaturePassword","syllabusPending","syllabus","isSyllabusGradingValid","IsGradable","gradableSyllabusItems","gradableSyllabusItemIds","invalidItems","gradingType","selectedTry","invalidGrading","invalidCompetences","SyllabusValidationErrors","updateTraineeSignatures","validateTraineeForm","border","scrollToTop","traineeDetailsMsg","InFlight","SyllabusErrors","isDayGradingValid","isReleaseGradingValid","isCertificateGradingValid","isDayCompetencesValid","isReleaseCompetencesValid","isGradeValid","gradingValidationInfo","isTraineeGradingValid","availableCourseInfo","oneTraineeAtATime","allAbsent","SubmitSession","dateAllowed","trainingDay","selectedSeats","isSeatValid","isPilotFunctionValid","traineesPending","hasNoAircraft","hasNoDevice","isGradingValid","invalidTrainees","isValidForm","getSessionTrainees","scrollTo","reloadReleasePanel","reloadRelease","showReleasePanel","availableCourse","isCheck","traineeSyllabi","TraineeIds","filterSelectedSyllabus","showTrainee","filterPresentTrainees","selectedPhaseIndex","CrewCoursePhases","releaseTrainee","crewIds","showReleaseBtn","showGroupReleaseBtn","releaseGroup","openTraineeSignature","signatureSuccess","resetSignature","getTraineeClass","textClass","allSyllabusCompleted","validSyllabusGrading","isReleaseSelected","toggleBtn","reloadFooter","dayCompetences","MandatorySubCompetences","OptionalSubCompetences","releaseCompetences","traineeSyllabus","historyTries","History","itemsHistory","allHistoryTries","historyTry","performedTry","ActionNo","InstructorName","SubmissionDate","AcTypes","pendingTriesLeft","pendingTries","isFirstTry","DefaultGrade","tries","sessionTries","tryItem","relatedSessionTry","extraTries","existingItem","SyllabusGrouping","setSyllabus","setTraineeSessions","getCourseFromStorage","getCoursesFromStorage","errorOnSaveCallback","localCourse","saveOneCourseToStorage","addCourseToStorage","setCoursesToStorage","Course","localCourses","IsCourseIncluded","updateCourseInfo","errorOnNetwork","traingingApiURL","FetchedTime","FetchedDutyCodes","LastFetchedDutyId","updateFlightCourseInfo","FetchedCrewRoute","getCoursesFromStorageByIds","selectedResults","setCourseOutdated","NeedsRefresh","FlightCourseCtrl","gotoCourse","stickySelectedTrainee","toggleView","refreshCourse","refreshErrorMsg","initCourse","courseTrainees","viewFromFlight","afterRefresh","getSession","CourseTrainees","SequenceWarning","isCourseComplete","IsCompleted","needsSubmit","fetched","HasLimitedSession","isCourseOutdated","headerMsg","hasPendingTraining","hasNotifications","manageCourseStatus","isEdit","savedCourse","getCrewRouteFlightTrainees","IsTrainee","addSessionToStorage","saveSessionToStorage","flatSullabusItems","flatItem","SessionId","SessionComments","ItemId","InstructorAimsId","createFlatHistorySullabusItem","mergeSyllabusWithHistory","_course$CourseTrainee","traineeEligibility","TraineeEligibilty","inactiveTrainees","eligibleTraineeIds","eligibleTrainees","crewCoursePhaseDutyNos","crewrouteTrainingIndicators","coursePhase","FlightTrainingIndicators","relatedDutyNos","relatedPhases","fti","firstPhase","PhaseStatus","RepeatRequestedItems","isSelected","createNewPhaseTrainees","nonEligibleTrainees","NonEligibleTrainees","EligibilityDesc","filterTraineesByEligibility","traineePhase","calculatePhaseStatus","hasSelectedPhase","isFirst","isLast","getSelectedPhase","ActivePhaseStatus","Selectable","invalidPhaseTrainee","mergeCourseWithSession","setSession","localSession","isNewSession","commentInput","filterValidTrainees","filterTrainee","saveComment","isDayGrading","hasCertificateExam","GroundCourseCtrl","applyAttendanceFromGroundDuty","availableRelease","tr","HasDayGrading","HasReleaseGrading","instructions","warningMessageText","viewModuleHistory","phaseId","isParallel","currentActiveOrderNo","SequentialWarning","oldSessions","historyPhase","hasHistory","StatusClass","BtnClass","TextClass","furtherAheadPhases","traineeInstructions","TraineeInstructions","examinerInstructions","ExaminerInstructions","continueSubmission","cancelSubmission","media","isObjectEmpty","addAircraftRow","selectedAircraft","aircraft","removeAircraftRow","acIndex","InSimulator","InAircraft","InClassroom","SyntheticDevices","ModuleHistoryCtrl","selectedSession","historyTrainee","selectedSubmittedSessionBadge","sessionId","initHistory","HistoryPhase","historyTrainees","hasSectors","hasDayGrading","hasReleaseGrading","ses","SectorsByAcType","acType","sectorSummary","totalSectors","allAcTypes","sectorGroup","SectorSummary","TotalSectors","setTraineeSummary","setHistoryTrainees","traineeSessionId","dutyTrainees","allEligibilityTrainees","dutyTrainee","courseTrainee","allCategory","categorizeTrainee","NotificationModalCtrl","notifications","showHistory","filterSession","showSessionTrainees","selectedSubmittedSession","selectSession","historyAvailable","SubmittedSessions","submittedDay","pilotFunction","selectSeat","leg","hasMultipleTrainees","otherPilotId","operatingPilots","otherSector","selectFunction","reloadPilotFunction","trainingFlights","instructor","traineeTrainingIndicator","createLegInfo","legs","traineeSeatOptions","instructorSeatOptions","SeatOptions","traineeFlightIds","crewMember","l","nonActiveLeg","nameArray","FirstName","LastName","pilotSector","existingInfo","incomingSector","existingSector","initializePilotFunctions","releasableModule","Submit","RadioModel","TraineeName","submitRelease","SubmitRelease","toggleTrainee","selectedCrewId","submittedSessions","releaseSession","CouldBeReleased","AllVisitedAcTypes","initializeTrainees","warningTrainees","filterSelectedTrainee","ReleaseSignatureModalCtrl","submit","successMessage","signaturePassword","responseTraineeCrewIds","traineeInfo","isConfirmed","confirmAircraft","aircraftVisits","requiredSignature","finalPendigArVis","released","pendingVisits","maxLength","maxList","hasPendingAircraftVisits","SignatureModalCtrl","confirmSubmit","releaseWarning","isGroundDuty","releaseSubmit","withGrading","allAvailable","notReleased","itemSelection","selectTry","pendingAttempt","selectGrading","triggerSyllabusClick","el","triggerHandler","updateTraineesSyllabus","updateTry","itemAutoSelection","hasCompetencesGrading","itemTry","tryCompetenceGrading","invalidItem","addTry","newTry","removeTry","pop","selectTryFromHeader","firstPendingTry","gradeFromHeader","TraineeAimsId","TraineeSignatureModalCtrl","signatureTrainee","confirmReset","traineeSign","credentials","Password","Username","PositionCode","authorizeTrainee","confirmation","trainingMenu","FullDate","savedCourses","StatusDesc","manageGroundCourseStatuses","Day","manageFlightCourseStatus","AIMS_ID","getGroundCourseTrainees","groundDutyTraineeDutyNos","GroundDutyCodes","gdc","FilterByRole","flightCrewTrainee","getDutySessions","DebugCtrl","DebugFactory","adminkey","authorized","checkAuthorized","verify","md5hash","CheckAuthorized","refreshStoredValues","Data","storedValues","addKeyName","updateAll","updateAllJson","exit","ResetDeviceCtrl","cancelReset"],"mappings":"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","file":"../a3.pilot.app.js","sourcesContent":["\"use strict\";\n\n//***Modal Dialog for Application Updates - non angular **/\nvar modalUpdates;\nvar isDownloanding = false;\nvar isCheckForUpdate = false;\n(function () {\n if ('applicationCache' in window && !('serviceWorker' in navigator)) {\n modalUpdates = $('.modal-updating').modal({\n backdrop: 'static',\n keyboard: true,\n show: false\n });\n\n modalUpdates.show = function () {\n modalUpdates.removeClass('update-success');\n modalUpdates.find('.progress').show();\n modalUpdates.find('.message-success').hide();\n modalUpdates.find('.message-danger').hide();\n modalUpdates.find('.message-no-update').hide();\n modalUpdates.find('.btn-update-retry').hide();\n modalUpdates.find('.btn-update-close').hide();\n modalUpdates.find('.btn-update-ok').hide();\n modalUpdates.modal('show');\n };\n\n modalUpdates.hide = function () {\n modalUpdates.modal('hide');\n };\n\n modalUpdates.success = function () {\n modalUpdates.find('.progress').hide();\n modalUpdates.find('.message-success').show();\n modalUpdates.find('.message-no-update').hide();\n modalUpdates.find('.message-danger').hide();\n modalUpdates.find('.btn-update-close').hide();\n modalUpdates.find('.btn-update-ok').show();\n modalUpdates.addClass('update-success');\n setTimeout(function () {\n modalUpdates.modal('hide');\n }, 2000);\n };\n\n modalUpdates.noUpdate = function () {\n modalUpdates.show();\n modalUpdates.find('.progress').hide();\n modalUpdates.find('.message-success').hide();\n modalUpdates.find('.message-danger').hide();\n modalUpdates.find('.message-no-update').show();\n modalUpdates.find('.btn-update-retry').hide();\n modalUpdates.find('.btn-update-close').hide();\n modalUpdates.find('.btn-update-ok').show();\n isCheckForUpdate = false;\n };\n\n modalUpdates.failure = function (errorMessage) {\n modalUpdates.show();\n modalUpdates.find('.progress').hide();\n modalUpdates.find('.message-success').hide();\n modalUpdates.find('.message-danger').show();\n modalUpdates.find('.message-no-update').hide();\n modalUpdates.find('.btn-update-close').show();\n modalUpdates.find('.btn-update-ok').hide();\n\n if (errorMessage && errorMessage != '') {\n modalUpdates.find('.update-error').text(errorMessage);\n } else {\n modalUpdates.find('.update-error').text('');\n }\n };\n\n modalUpdates.on('hidden.bs.modal', function (e) {\n var b = modalUpdates.hasClass('update-success');\n if (b) location.reload(true);\n });\n }\n}).call(void 0); //** ApplicationCache Events & Actions **//\n\n(function () {\n ////////////////////////////////////////////////////index scripts (cache)////////////////////////////////////////////////////\n if ('applicationCache' in window && !('serviceWorker' in navigator)) {\n // Convenience array of status values\n var cacheHandler = function cacheHandler() {};\n\n cacheHandler.cacheStatusValues = [];\n cacheHandler.cacheStatusValues[0] = 'uncached';\n cacheHandler.cacheStatusValues[1] = 'idle';\n cacheHandler.cacheStatusValues[2] = 'checking';\n cacheHandler.cacheStatusValues[3] = 'downloading';\n cacheHandler.cacheStatusValues[4] = 'updateready';\n cacheHandler.cacheStatusValues[5] = 'obsolete';\n\n cacheHandler.onDownloading = function (e) {\n isDownloanding = true;\n modalUpdates.show();\n cacheHandler.logEvent(e);\n };\n\n cacheHandler.onCached = function (e) {\n modalUpdates.hide();\n cacheHandler.logEvent(e);\n };\n\n cacheHandler.onChecking = function (e) {\n //ShowWaitDialog();\n cacheHandler.logEvent(e);\n };\n\n cacheHandler.onProgress = function (e) {};\n\n cacheHandler.onObsolete = function (e) {};\n\n cacheHandler.onError = function (e) {\n //debugger;\n var message = \"Could not download application updates due to an unexpected error.\\n\" + \"make sure that cache.manifest is being served with MIME type: text/cache-manifest\"; //actual error message if any\n\n if (e.message) message = e.message;\n console.error(message); //hide update dialog if visible\n\n if (isDownloanding) {\n modalUpdates.failure(message);\n } else {\n modalUpdates.hide();\n }\n };\n\n cacheHandler.onNoUpdate = function (e) {\n if (isCheckForUpdate) {\n modalUpdates.noUpdate();\n } else {\n modalUpdates.hide();\n }\n\n isDownloanding = false;\n cacheHandler.logEvent(e);\n };\n\n cacheHandler.onUpdateReady = function (e) {\n try {\n cache.swapCache();\n } catch (e) {}\n\n cacheHandler.logEvent(e);\n isDownloanding = false;\n modalUpdates.success(); //location.reload(true);\n }; // Log every event to the console\n\n\n cacheHandler.logEvent = function (e) {\n /*\r\n var status, type, message; //online, \r\n //online = (navigator.online) ? 'yes' : 'no';\r\n status = cacheHandler.cacheStatusValues[cache.status];\r\n type = e.type;\r\n message = '';//'online: ' + online;\r\n message += 'CACHE: event: ' + type;\r\n message += ', status: ' + status;\r\n if (type == 'error' && navigator.online) {\r\n \tmessage += ' (prolly a syntax error in manifest)';\r\n }\r\n console.log(message);\r\n */\n };\n\n var cache = window.applicationCache;\n cache.addEventListener('cached', cacheHandler.onCached, false);\n cache.addEventListener('checking', cacheHandler.onChecking, false);\n cache.addEventListener('downloading', cacheHandler.onDownloading, false);\n cache.addEventListener('error', cacheHandler.onError, false); //cache.addEventListener('error', cacheHandler.logEvent, false);\n\n cache.addEventListener('noupdate', cacheHandler.onNoUpdate, false);\n cache.addEventListener('obsolete', cacheHandler.onObsolete, false);\n cache.addEventListener('progress', cacheHandler.onProgress, false);\n cache.addEventListener('updateready', cacheHandler.onUpdateReady, false);\n }\n\n $('#update-error-btn').click(function () {\n var alert = $('.hidden-update-error');\n\n if (alert.hasClass('hidden')) {\n alert.removeClass('hidden');\n $('#update-error-btn').text(\"show less\");\n } else {\n alert.addClass('hidden');\n $('#update-error-btn').text(\"show more\");\n }\n });\n $('body').on('click', '#update-check-btn', function () {\n isCheckForUpdate = true;\n var url = location.origin;\n $.ajax({\n type: \"GET\",\n url: url,\n cache: false,\n success: function success() {\n //get cache\n var cache = window.applicationCache; // Update the user's cache\n\n if (cache != null || cache != undefined) {\n cache.update();\n }\n }\n /*,\r\n error: function(){ \r\n console.log('error');\r\n }*/\n\n });\n });\n}).call(void 0);\n\"use strict\";\n\n$(function () {\n angular.bootstrap(document, ['a3.pilot.reports']);\n});\nvar a3_pilot_reports = angular.module('a3.pilot.reports', [//angular modules\n'ngSanitize', 'ngRoute', 'ngTouch', //3rd party modules\n'angular-md5', 'LocalStorageModule', 'ui.bootstrap', 'nya.bootstrap.select', 'ui.toggle', 'ui.sortable', //Our modules\n'LocalStorageMD5Module', 'MyDirectives']);\n\"use strict\";\n\n(function () {\n 'use strict'; // setup routing\n\n a3_pilot_reports.config(routeConfig);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name routeConfig\r\n * @description \r\n * Route configuration\r\n * @ngInject\r\n */\n\n function routeConfig($routeProvider) {\n $routeProvider.when('/', {\n controller: 'CalendarCtrl',\n templateUrl: './views/calendar.html'\n }).when('/login', {\n controller: 'LoginCtrl',\n templateUrl: './views/login.html'\n }).when('/flightinfo/:flightId', {\n controller: 'FlightInfoCtrl',\n templateUrl: 'views/flight-info.html',\n reloadOnSearch: false\n }).when('/report/:reportId', {\n controller: 'ReportCtrl',\n templateUrl: './views/report.html'\n }).when('/report/:reportId/:flightId', {\n controller: 'ReportCtrl',\n templateUrl: './views/report.html'\n }).when('/pdf/:reportId', {\n controller: 'ReportCtrl',\n templateUrl: './views/report.html'\n }).when('/pax/:flightId', {\n controller: 'PaxCtrl',\n templateUrl: 'views/pax.html'\n }).when('/addflight', {\n controller: 'AddFlightCtrl',\n templateUrl: './views/addflight.html'\n }).when('/reset', {\n controller: 'ResetDeviceCtrl',\n templateUrl: './views/reset.html'\n }).when('/messages/:flightId', {\n controller: 'MessageCtrl',\n templateUrl: 'views/messages.html'\n }).when('/messages/', {\n controller: 'MessageCtrl',\n templateUrl: 'views/messages.html'\n }).when('/debug', {\n controller: 'DebugCtrl',\n templateUrl: './views/debug.html'\n }).when('/memos/:filter', {\n controller: 'MemosCtrl',\n templateUrl: 'views/Memos/memos.html'\n }).when('/memos', {\n controller: 'MemosCtrl',\n templateUrl: 'views/Memos/memos.html'\n }).when('/ticket', {\n controller: 'TicketCtrl',\n templateUrl: 'views/ticket.html'\n }).when('/bucket', {\n controller: 'BucketCtrl',\n templateUrl: 'views/Bucket/bucketCalendar.html'\n }).when('/bucketDay/:dutyId', {\n controller: 'BucketDayCtrl',\n templateUrl: 'views/Bucket/bucketDay.html'\n }).when('/leaverequest', {\n controller: 'LeaveRequestCtrl',\n templateUrl: 'views/LeaveRequest/leaveRequest.html'\n }).when('/groundDuty/:groundDutyId', {\n controller: 'GroundDutyCtrl',\n templateUrl: 'views/GroundDuty/groundDuty-info.html'\n }).when('/crewRoute/:dutyNo/:dutyDay', {\n controller: 'CrewRouteCtrl',\n templateUrl: 'views/CrewRoute/crew-route-info.html'\n }).when('/reportsHistory/:reportId/:flightId?/:reportType', {\n controller: 'ReportsHistoryCtrl',\n templateUrl: 'views/reportsHistory.html'\n }).when('/flightcourse/:courseId/:dutyNo/:dutyDay/:date', {\n controller: 'FlightCourseCtrl',\n templateUrl: 'views/Training/flightCourse.html'\n }).when('/flightcourse/:courseId/:dutyNo/:dutyDay/:date/:flightId', {\n controller: 'FlightCourseCtrl',\n templateUrl: 'views/Training/flightCourse.html'\n }).when('/groundcourse/:courseId/:dutyId/:date', {\n controller: 'GroundCourseCtrl',\n templateUrl: 'views/Training/groundCourse.html'\n }).when('/groundHistory/:courseId/:dutyId/:date/:phaseId', {\n controller: 'ModuleHistoryCtrl',\n templateUrl: 'views/Training/moduleHistory.html'\n }).when('/flightHistory/:courseId/:dutyNo/:dutyDay/:date/:phaseId', {\n controller: 'ModuleHistoryCtrl',\n templateUrl: 'views/Training/moduleHistory.html'\n }).when('/safetyreport/flightcrewreport/:flightId', {\n controller: 'SafetyCtrl',\n templateUrl: 'views/Safety/flightCrewReport.html'\n }).when('/safetyreport/fatiguereport/:flightId', {\n controller: 'FatigueCtrl',\n templateUrl: 'views/Safety/fatigueReport.html'\n }).otherwise({\n redirectTo: '/'\n });\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.run(runBlock);\n /* @ngInject */\n\n function runBlock($rootScope, $timeout, $location, UserFactory, UserTokenFactory, PilotReportLocalEditFactory, SettingsMain, $anchorScroll, SWUpdateService, LogService) {\n //make sure that each route change validates that the user is still logged in\n var valid = ['/login', '/reset', '/debug', '/ticket'];\n $rootScope.$on('$routeChangeStart', function (event, next, current) {\n if (valid.indexOf($location.$$path) < 0 && !UserFactory.isLoggedIn()) {\n event.preventDefault();\n $location.path('/login');\n } //START - SERVICE WORKERS\n\n\n if ('serviceWorker' in navigator) {\n SWUpdateService.initialize();\n navigator.serviceWorker.getRegistration().then(function (registration) {\n $rootScope.SWRegistration = registration;\n });\n SWUpdateService.checkUpdates($rootScope.SWRegistration);\n } //END - SERVICE WORKERS\n\n\n $anchorScroll.yOffset = 100;\n\n if (!current || !current.$$route || current.$$route.controller != next.$$route.controller) {\n //Check if temp report of any kind exists\n var editingPage = SettingsMain.getEditingPage();\n SettingsMain.setEditingPage(null);\n\n if (editingPage == 'report') {\n // check if a temp report exists in local storage\n if (PilotReportLocalEditFactory.getPilotReportLocalEditFromTemp() != null) {\n $location.path(\"report/temp\");\n }\n }\n }\n });\n $(\"body\").on(\"click\", \".memo-body a\", function () {\n var link = $(this).attr(\"href\");\n\n if (link && link.indexOf(\"surveymonkey\") > 0) {\n LogService.debug(link);\n }\n });\n $rootScope.idbSupported = \"indexedDB\" in window;\n $rootScope.isOffline = !window.navigator.onLine;\n window.addEventListener('offline', function (e) {\n $timeout($rootScope.isOffline = !window.navigator.onLine);\n });\n window.addEventListener('online', function (e) {\n $timeout($rootScope.isOffline = !window.navigator.onLine);\n }); //maintain the user token, outside the localStorage, needed for submitting js errors\n\n var user = UserFactory.getUser();\n if (user && user.token) UserTokenFactory.setToken(user.token);else UserTokenFactory.setToken('');\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n // Warning!!! This an auto generated file. Any Changes will be lost. If u want to add or edit go to config.json \n a3_pilot_reports.constant(\"liveVersion\", true);\n a3_pilot_reports.constant(\"defaultCalendarDate\", null);\n a3_pilot_reports.constant(\"defaultBucketDate\", null);\n a3_pilot_reports.constant(\"aircraftLateArrivalReportId\", 169);\n a3_pilot_reports.constant(\"inadequateGroundTimeReportId\", 170);\n a3_pilot_reports.constant(\"apiUrl\", \"https://flightloguat.aegeanair.com/api/v2.0\");\n a3_pilot_reports.constant(\"ssrCodes\", [{\n \"code\": \"AOXY\",\n \"description\": \"Airline Supplied Oxygen\"\n }, {\n \"code\": \"AVIH\",\n \"description\": \"Animal in Hold\"\n }, {\n \"code\": \"AVML\",\n \"description\": \"Vegetarian Hindu meal\"\n }, {\n \"code\": \"BBNL\",\n \"description\": \"Baby meal request\"\n }, {\n \"code\": \"BIKE\",\n \"description\": \"Request for carriage of bicycle\"\n }, {\n \"code\": \"BLML\",\n \"description\": \"Bland meal request\"\n }, {\n \"code\": \"BLND\",\n \"description\": \"Blind passenger information\"\n }, {\n \"code\": \"CBBG\",\n \"description\": \"Bulky cabin baggage request\"\n }, {\n \"code\": \"CHLD\",\n \"description\": \"Child information\"\n }, {\n \"code\": \"CHML\",\n \"description\": \"Child Meal Request\"\n }, {\n \"code\": \"DBML\",\n \"description\": \"Diabetic meal request\"\n }, {\n \"code\": \"DEAF\",\n \"description\": \"Deaf passenger information\"\n }, {\n \"code\": \"DEPA\",\n \"description\": \"Accompanied Deportee Information\"\n }, {\n \"code\": \"DEPU\",\n \"description\": \"Deportee unaccompanied\"\n }, {\n \"code\": \"DHCS\",\n \"description\": \"Deadhead crew seating\"\n }, {\n \"code\": \"DPNA\",\n \"description\": \"Disabled passenger needing assistance\"\n }, {\n \"code\": \"EMIG\",\n \"description\": \"Emigrant\"\n }, {\n \"code\": \"ESAN\",\n \"description\": \"Passenger with emotional support/psychiatric\"\n }, {\n \"code\": \"ESCD\",\n \"description\": \"Passenger escorting deportee\"\n }, {\n \"code\": \"EXST\",\n \"description\": \"Request for extra seat\"\n }, {\n \"code\": \"FAMS\",\n \"description\": \"Family seating\"\n }, {\n \"code\": \"FPML\",\n \"description\": \"Fruit platter meal request\"\n }, {\n \"code\": \"FRED\",\n \"description\": \"Meal and assist request\"\n }, {\n \"code\": \"GFML\",\n \"description\": \"Gluten intolerant meal request\"\n }, {\n \"code\": \"GPST\",\n \"description\": \"Group seating request\"\n }, {\n \"code\": \"HAJJ\",\n \"description\": \"HAJJ Passengers\"\n }, {\n \"code\": \"HNML\",\n \"description\": \"Hindu meal request\"\n }, {\n \"code\": \"INAD\",\n \"description\": \"Inadmissable\"\n }, {\n \"code\": \"INFT\",\n \"description\": \"Infant information\"\n }, {\n \"code\": \"KSML\",\n \"description\": \"Kosher meal request\"\n }, {\n \"code\": \"LCML\",\n \"description\": \"Low calorie meal request\"\n }, {\n \"code\": \"LFML\",\n \"description\": \"Low fat meal request\"\n }, {\n \"code\": \"LSML\",\n \"description\": \"Low salt meal request\"\n }, {\n \"code\": \"MAAS\",\n \"description\": \"Meal and assist request\"\n }, {\n \"code\": \"MEDA\",\n \"description\": \"Medical assistance information\"\n }, {\n \"code\": \"MEQT\",\n \"description\": \"Medical equipment\"\n }, {\n \"code\": \"MOML\",\n \"description\": \"Halaal meal request\"\n }, {\n \"code\": \"NFML\",\n \"description\": \"No fish meal request\"\n }, {\n \"code\": \"NLML\",\n \"description\": \"Low lactose meal request\"\n }, {\n \"code\": \"NOML\",\n \"description\": \"Meal on board not required\"\n }, {\n \"code\": \"PETC\",\n \"description\": \"Pet in cabin request\"\n }, {\n \"code\": \"POXY\",\n \"description\": \"Passenger own oxygen\"\n }, {\n \"code\": \"RVML\",\n \"description\": \"Vegetarian raw meal request\"\n }, {\n \"code\": \"SEML\",\n \"description\": \"Seafood meal request\"\n }, {\n \"code\": \"SFML\",\n \"description\": \"Seafood meal request\"\n }, {\n \"code\": \"SPML\",\n \"description\": \"Special meal request\"\n }, {\n \"code\": \"SVAN\",\n \"description\": \"Passenger with service animal in cabin\"\n }, {\n \"code\": \"UMNR\",\n \"description\": \"Unaccompanied minor information\"\n }, {\n \"code\": \"VGML\",\n \"description\": \"Vegetarian vegan meal request\"\n }, {\n \"code\": \"VJML\",\n \"description\": \"Vegetarian Jain meal request\"\n }, {\n \"code\": \"VLML\",\n \"description\": \"Vegetarian Lacto-Ovo meal request\"\n }, {\n \"code\": \"VOML\",\n \"description\": \"Vegetarian Oriental meal request\"\n }, {\n \"code\": \"WCBD\",\n \"description\": \"Wheelchair Dry-cell battery request\"\n }, {\n \"code\": \"WCBW\",\n \"description\": \"Wheelchair Wet-cell battery request\"\n }, {\n \"code\": \"WCHC\",\n \"description\": \"Wheelchair To seat request\"\n }, {\n \"code\": \"WCHR\",\n \"description\": \"Wheelchair To aircraft door request\"\n }, {\n \"code\": \"WCHS\",\n \"description\": \"Wheelchair Up/down stairs request\"\n }, {\n \"code\": \"WCLB\",\n \"description\": \"Wheelchair - Lithium ion Battery\"\n }, {\n \"code\": \"WCMP\",\n \"description\": \"Wheelchair Manual powered request\"\n }, {\n \"code\": \"WCOB\",\n \"description\": \"Wheelchair On board request\"\n }, {\n \"code\": \"WEAP\",\n \"description\": \"WEAP Firearms or ammunition booked & carried as checked\"\n }, {\n \"code\": \"XBGS\",\n \"description\": \"DCS Excess Baggage Request\"\n }]);\n a3_pilot_reports.constant(\"bookmarkThreshold\", 15);\n a3_pilot_reports.constant(\"autolandSupportingAcTypes\", [\"319\", \"320\", \"321\", \"32Q\", \"32N\"]);\n a3_pilot_reports.constant(\"turnAroundTimesSupportingAcTypes\", [\"319\", \"320\", \"321\", \"32Q\", \"32N\"]);\n a3_pilot_reports.constant(\"showRecomendedWaterAcTypes\", [\"319\", \"320\", \"321\", \"32Q\", \"32N\"]);\n a3_pilot_reports.constant(\"showCatIIApprachAcTypes\", [\"DH4\", \"DH8\", \"AT4\"]);\n a3_pilot_reports.constant(\"showGroundInfoAcTypes\", [\"DH4\", \"DH8\", \"AT4\"]);\n a3_pilot_reports.constant(\"showHotelsAcTypes\", [\"DH4\", \"DH8\", \"AT4\"]);\n a3_pilot_reports.constant(\"operationalPhases\", [{\n \"key\": \"3287\",\n \"value\": \"On Stand\"\n }, {\n \"key\": \"3288\",\n \"value\": \"Towing\"\n }, {\n \"key\": \"9242\",\n \"value\": \"Towing - Stand to Stand\"\n }, {\n \"key\": \"9243\",\n \"value\": \"Towing - to/from maint\"\n }, {\n \"key\": \"3289\",\n \"value\": \"Parked\"\n }, {\n \"key\": \"3290\",\n \"value\": \"Pushback\"\n }, {\n \"key\": \"3291\",\n \"value\": \"Taxi-out\"\n }, {\n \"key\": \"3292\",\n \"value\": \"Take-off\"\n }, {\n \"key\": \"3293\",\n \"value\": \"Initial Climb\"\n }, {\n \"key\": \"3294\",\n \"value\": \"Climb\"\n }, {\n \"key\": \"3295\",\n \"value\": \"Cruise\"\n }, {\n \"key\": \"3296\",\n \"value\": \"Descent\"\n }, {\n \"key\": \"3297\",\n \"value\": \"Holding\"\n }, {\n \"key\": \"3298\",\n \"value\": \"Approach\"\n }, {\n \"key\": \"3299\",\n \"value\": \"Landing\"\n }, {\n \"key\": \"3300\",\n \"value\": \"Taxi-in\"\n }, {\n \"key\": \"3301\",\n \"value\": \"Maintenance\"\n }, {\n \"key\": \"3302\",\n \"value\": \"All\"\n }, {\n \"key\": \"3303\",\n \"value\": \"In Aircraft\"\n }, {\n \"key\": \"3304\",\n \"value\": \"In Position at Aircraft\"\n }, {\n \"key\": \"3305\",\n \"value\": \"In Transit To / From Stand\"\n }, {\n \"key\": \"3306\",\n \"value\": \"Moving on Stand\"\n }, {\n \"key\": \"3307\",\n \"value\": \"Positioning to Aircraft\"\n }, {\n \"key\": \"3308\",\n \"value\": \"Removing from Aircraft\"\n }, {\n \"key\": \"3309\",\n \"value\": \"Other\"\n }, {\n \"key\": \"3310\",\n \"value\": \"Hover\"\n }, {\n \"key\": \"3311\",\n \"value\": \"In Flight\"\n }, {\n \"key\": \"3312\",\n \"value\": \"Multiple\"\n }, {\n \"key\": \"3313\",\n \"value\": \"Parked On / By Stand\"\n }, {\n \"key\": \"9241\",\n \"value\": \"Arrival\"\n }, {\n \"key\": \"9244\",\n \"value\": \"Arrival - Marshaling\"\n }, {\n \"key\": \"9245\",\n \"value\": \"Arrival - Guidance\"\n }, {\n \"key\": \"9246\",\n \"value\": \"Servicing\"\n }, {\n \"key\": \"9247\",\n \"value\": \"Servicing - De-icing\"\n }, {\n \"key\": \"9248\",\n \"value\": \"Servicing - Fueling\"\n }, {\n \"key\": \"9249\",\n \"value\": \"Servicing - Catering\"\n }, {\n \"key\": \"9250\",\n \"value\": \"Servicing - Lavatory\"\n }, {\n \"key\": \"9251\",\n \"value\": \"Servicing - Water\"\n }, {\n \"key\": \"9252\",\n \"value\": \"Servicing - Cleaning\"\n }, {\n \"key\": \"9253\",\n \"value\": \"Servicing - Line Maint\"\n }, {\n \"key\": \"9254\",\n \"value\": \"Servicing - Coning\"\n }, {\n \"key\": \"9255\",\n \"value\": \"Servicing - GPU\"\n }, {\n \"key\": \"9256\",\n \"value\": \"Servicing - PCA\"\n }, {\n \"key\": \"9257\",\n \"value\": \"Servicing - Bridging\"\n }, {\n \"key\": \"9258\",\n \"value\": \"Servicing - Chocking\"\n }, {\n \"key\": \"9259\",\n \"value\": \"Loading\"\n }, {\n \"key\": \"9260\",\n \"value\": \"Loading - Passenger\"\n }, {\n \"key\": \"9261\",\n \"value\": \"Loading - Baggage\"\n }, {\n \"key\": \"9262\",\n \"value\": \"Loading - Cargo\"\n }, {\n \"key\": \"9263\",\n \"value\": \"Unloading\"\n }, {\n \"key\": \"9264\",\n \"value\": \"Unloading - Passenger\"\n }, {\n \"key\": \"9265\",\n \"value\": \"Unloading - Baggage\"\n }, {\n \"key\": \"9266\",\n \"value\": \"Unloading - Cargo\"\n }]);\n})();\n\"use strict\";\n\n(function () {\n // Warning!!! This an auto generated file. Any Changes will be lost. If u want to add or edit go to config.json \n a3_pilot_reports.constant(\"version\", \"appVersion_20211203144132\");\n})();\n\"use strict\";\n\n(function () {\n 'use strict'; //Default Configuration For Charts\n\n a3_pilot_reports.constant('barOptions', barOptions);\n a3_pilot_reports.constant('pieDoughnutOptions', pieDoughnutOptions); //Default Configuration For Charts\n\n var pieDoughnutOptions = {\n //Boolean - Whether we should show a stroke on each segment\n segmentShowStroke: true,\n //String - The colour of each segment stroke\n segmentStrokeColor: \"#fff\",\n //Number - The width of each segment stroke\n segmentStrokeWidth: 2,\n //Number - The percentage of the chart that we cut out of the middle\n percentageInnerCutout: 50,\n // This is 0 for Pie charts\n //Number - Amount of animation steps\n animationSteps: 100,\n //String - Animation easing effect\n animationEasing: \"easeOutBounce\",\n //Boolean - Whether we animate the rotation of the Doughnut\n animateRotate: true,\n //Boolean - Whether we animate scaling the Doughnut from the centre\n animateScale: false,\n //String - A legend template\n legendTemplate: \"\",\n onAnimationComplete: function onAnimationComplete() {\n this.showTooltip(this.segments, true);\n },\n tooltipEvents: [],\n showTooltips: true\n };\n var barOptions = {\n ///Boolean - Whether grid lines are shown across the chart\n scaleShowGridLines: true,\n //String - Colour of the grid lines\n scaleGridLineColor: \"rgba(0,0,0,.05)\",\n //Number - Width of the grid lines\n scaleGridLineWidth: 1,\n //Boolean - Whether to show horizontal lines (except X axis)\n scaleShowHorizontalLines: true,\n //Boolean - Whether to show vertical lines (except Y axis)\n scaleShowVerticalLines: true,\n //Boolean - Whether the line is curved between points\n bezierCurve: true,\n //Number - Tension of the bezier curve between points\n bezierCurveTension: 0.4,\n //Boolean - Whether to show a dot for each point\n pointDot: true,\n //Number - Radius of each point dot in pixels\n pointDotRadius: 4,\n //Number - Pixel width of point dot stroke\n pointDotStrokeWidth: 1,\n //Number - amount extra to add to the radius to cater for hit detection outside the drawn point\n pointHitDetectionRadius: 20,\n //Boolean - Whether to show a stroke for datasets\n datasetStroke: true,\n //Number - Pixel width of dataset stroke\n datasetStrokeWidth: 2,\n //Boolean - Whether to fill the dataset with a colour\n datasetFill: true,\n //String - A legend template\n legendTemplate: \"\"\n };\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n angular.module('MyDirectives', [])\n /* Used to capture images from the device's camera\r\n * and resize them using given dimensions and quality\r\n * \r\n */\n .directive('image', function ($q) {\n 'use strict';\n\n var URL = window.URL || window.webkitURL;\n return {\n restrict: 'A',\n scope: {\n /*image: '=',*/\n maxwidth: '@?',\n maxheight: '@?',\n quality: '@?',\n imagetype: '@?',\n onfilechange: '&'\n },\n link: function postLink(scope, element, attrs, ctrl) {\n var onFileChangeCallback = scope.onfilechange;\n var onFileFailureCallback = scope.onfileerror;\n var filename = \"\";\n var options;\n\n var getOptions = function getOptions() {\n var options = {\n maxWidth: parseFloat(scope.maxwidth) || 1024,\n maxHeight: parseFloat(scope.maxheight) || 768,\n quality: parseFloat(scope.quality) || 0.8,\n imageType: scope.imagetype || 'image/jpeg',\n canvas: true\n };\n return options;\n };\n\n var whenError = function whenError(errorMessage) {\n scope.$apply(function () {\n if (typeof onFileFailureCallback == 'function') {\n //to pass data in the message, we need to have an object with attrs named as in\n //the html part, eg onfilechange=\"imageChanged(data)\"\n onFileFailureCallback({\n err: errorMessage\n });\n }\n });\n };\n\n var whenReady = function whenReady(img) {\n if (!(img.src || img instanceof HTMLCanvasElement)) {\n whenError('Loading image file failed');\n } else {\n var data = img.src || img.toDataURL(options.imageType, options.quality);\n var imageResult = {\n dataURL: data,\n fileName: filename,\n fileType: options.imageType\n };\n scope.$apply(function () {\n if (typeof onFileChangeCallback == 'function') {\n //to pass data in the message, we need to have an object with attrs named as in\n //the html part, eg onfilechange=\"imageChanged(data)\"\n onFileChangeCallback({\n data: imageResult\n });\n }\n });\n }\n };\n\n element.bind('change', function (evt) {\n evt.preventDefault(); //e = e.originalEvent;\n\n var target = evt.dataTransfer || evt.target;\n var files = target && target.files;\n\n if (files) {\n var file;\n options = getOptions(); //read latest settings\n\n for (var i = 0; i < files.length; i++) {\n file = files[i];\n filename = file.name; //start by get metadata, to autoset the orientation of the image\n\n loadImage.parseMetaData(file, //when metadata are ready, use them and then load image\n function (data) {\n if (data.exif) {\n options.orientation = data.exif.get('Orientation');\n }\n\n if (!loadImage(file, whenReady, options)) {\n whenError('Your browser does not support capturing images.');\n }\n });\n }\n }\n });\n }\n };\n });\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('AirportContactFactory', AirportContactFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AirportContactFactory\r\n * @description \r\n * Add, Update, Delete and Get Airport Contacts.\r\n * @ngInject\r\n */\n\n function AirportContactFactory(GenericService) {\n /**\r\n * Initialize the AirportContact\r\n * @memberof AirportContactFactory\r\n */\n function Airport() {\n this.Iata = null;\n this.Contacts = null;\n }\n /*function Contact() {\r\n this.No=null;\r\n this.ContactType=null;\r\n this.Company=null;\r\n this.Terminal=null;\r\n this.IsPrimary=null;\r\n this.Address=null;\r\n this.Frequencies=null;\r\n this.Remarks=null;\r\n this.OperatingHoursMon=null;\r\n this.OperatingHoursTue=null;\r\n this.OperatingHoursWed=null;\r\n this.OperatingHoursThu=null;\r\n this.OperatingHoursFri=null;\r\n this.OperatingHoursSat=null;\r\n this.OperatingHoursSun=null;\r\n this.Persons=null;\r\n } \r\n \r\n function Person() {\r\n this.No=null;\r\n this.Department=null;\r\n this.Name=null;\r\n this.ContactDetails=null;\r\n } \r\n \t\tfunction ContactDetails() {\r\n this.Type=null;\r\n this.Details=null;\r\n }*/\n\n\n var objType = 'airportContacts';\n var objCallback = Airport;\n var service = {\n fromObjectList: fromObjectList,\n getAirportContactsFromStorage: getAirportContactsFromStorage,\n setAirportContactsToStorage: setAirportContactsToStorage,\n clearAirportContactsFromStorage: clearAirportContactsFromStorage,\n getAirportContacts: getAirportContacts\n };\n /**\r\n * Extend an array of Objects from the default airportContact Object\r\n * @memberof AirportContactFactory\r\n * @param {Array} objList an Array Of airportContact\r\n * @returns {Array} airportContact\r\n */\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n /**\r\n * Get airportContacts\r\n * @memberof AirportContactFactory\r\n * @returns {Array} airportContacts\r\n */\n\n\n function getAirportContactsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save airportContacts to storage\r\n * @memberof AirportContactFactory\r\n * @param {Array} airportContacts A list of AirportContacts\r\n */\n\n\n function setAirportContactsToStorage(airportContacts) {\n GenericService.saveAll(airportContacts, objType, objCallback);\n }\n /**\r\n * Remove the airportContacts of the local storage\r\n * @memberof AirportContactFactory\r\n */\n\n\n function clearAirportContactsFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get the contacts for a given airport\r\n * @memberof AirportContactFactory\r\n */\n\n\n function getAirportContacts(airportIata) {\n var all = this.getAirportContactsFromStorage();\n if (!all) return null;\n var airport = all.filter(function (item) {\n return item.Iata == airportIata;\n });\n if (!airport || airport.length == 0) return null; //we expect a single airport item per iata\n\n return airport[0]; //return GenericService.fromObjectList(airport[0].Contacts, Contact);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('AirportHotelFactory', AirportHotelFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AirportHotelFactory\r\n * @description \r\n * Add, Update, Delete and Get Airport Hotels.\r\n * @ngInject\r\n */\n\n function AirportHotelFactory(GenericService) {\n /**\r\n * Initialize the AirportHotel\r\n * @memberof AirportHotelFactory\r\n */\n function Airport() {\n this.Iata = null;\n this.Hotels = null;\n }\n\n var objType = 'airportHotels';\n var objCallback = Airport;\n var service = {\n fromObjectList: fromObjectList,\n getAirportHotelsFromStorage: getAirportHotelsFromStorage,\n setAirportHotelsToStorage: setAirportHotelsToStorage,\n clearAirportHotelsFromStorage: clearAirportHotelsFromStorage,\n getAirportHotels: getAirportHotels\n };\n /**\r\n * Extend an array of Objects from the default airportHotel Object\r\n * @memberof AirportHotelFactory\r\n * @param {Array} objList an Array Of airportHotel\r\n * @returns {Array} airportHotel\r\n */\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n /**\r\n * Get airportHotels\r\n * @memberof AirportHotelFactory\r\n * @returns {Array} airportHotels\r\n */\n\n\n function getAirportHotelsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save airportHotels to storage\r\n * @memberof AirportHotelFactory\r\n * @param {Array} airportHotels A list of AirportHotels\r\n */\n\n\n function setAirportHotelsToStorage(airportHotels) {\n GenericService.saveAll(airportHotels, objType, objCallback);\n }\n /**\r\n * Remove the airportHotels of the local storage\r\n * @memberof AirportHotelFactory\r\n */\n\n\n function clearAirportHotelsFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get the Hotels for a given airport\r\n * @memberof AirportHotelFactory\r\n */\n\n\n function getAirportHotels(airportIata, fltDate) {\n var all = this.getAirportHotelsFromStorage();\n if (!all) return null;\n var airport = all.filter(function (item) {\n return item.Iata == airportIata;\n });\n if (!airport || airport.length == 0) return null; //for each airport hotel\n //from all available hotel priorities, find the one matching the active period \n\n angular.forEach(airport[0].Hotels, function (hotel) {\n var fltActiveHotels = hotel && hotel.HotelPriorities ? hotel.HotelPriorities.filter(function (item) {\n return fltDate >= item.ActiveBegin && fltDate <= item.ActiveEnd;\n }) : [];\n if (!fltActiveHotels || fltActiveHotels.length == 0) return; //hotel inactive in FltDate - ActivePriority will be undefined for this hotel\n\n hotel.ActivePriority = fltActiveHotels[0].PriorityNo; //set the ActivePriority field for the hotel to be displayed in UI\n }); //we expect a single airport item per iata\n\n return airport[0]; //return GenericService.fromObjectList(airport[0].Hotels, Hotel);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('BucketCtrl', BucketCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name BucketCtrl\r\n * @description \r\n * View bucket\r\n * @ngInject\r\n */\n\n function BucketCtrl($scope, $location, BucketFactory, UserFactory, MessageFactory, $timeout, SettingsMain, defaultCalendarDate) {\n var ownDuties = [];\n var sharedDuties = [];\n var approvedDuties = [];\n $scope.state = 'bucketCalendar';\n var user = UserFactory.getUser();\n $scope.isSecure = UserFactory.isSecure();\n $scope.isUserSA = user.position == 'SA' ? true : false;\n $scope.logged_user_info = user.aimsId + ' - ' + user.name;\n $scope.getCalendarData = getCalendarData;\n $scope.showErrorMessage = false;\n var selectedDate = SettingsMain.getCalendarSelectedDate(); //Redirect to month that was previously selected\n\n SettingsMain.setCalendarSelectedDate(null); //Then reinitialize to current month\n\n getCalendarData();\n\n function getCalendarData() {\n progressBarBox(true);\n BucketFactory.getDutyObject(function (responseData) {\n ownDuties = responseData.data.data.Duties;\n sharedDuties = responseData.data.data.SharedDuties;\n approvedDuties = responseData.data.data.ApprovedDuties;\n setupView();\n progressBarBox(false);\n })[\"catch\"](function (error) {\n progressBarBox(false);\n $scope.showErrorMessage = true;\n console.error('Load duties error', error.status, error.statusText);\n });\n }\n\n function setupView() {\n if (!UserFactory.isLoggedIn()) {\n $location.path(\"/login\");\n }\n\n $scope.number_of_messages = MessageFactory.getMessagesFromStorage().length;\n $scope.number_of_messages_not_readen = MessageFactory.getCountOfUnreadMessages();\n /*var ownEvents = formatDuties(ownDuties, true, false);\r\n if (sharedDuties.length > 0) {\r\n var sharedEvents = formatDuties(sharedDuties, false, false);\r\n var events = ownEvents.concat(sharedEvents);\r\n } else {\r\n var events = ownEvents;\r\n }*/\n\n $scope.notification = createNotification(ownDuties);\n var ownEvents = formatDuties(ownDuties, true, false);\n var events = ownEvents;\n\n if (approvedDuties != null || approvedDuties != undefined) {\n if (approvedDuties.length > 0) {\n var appvovedEvents = formatDuties(approvedDuties, true, true);\n var events = events.concat(appvovedEvents);\n }\n }\n\n calendar(events);\n }\n /**\r\n * Transform routes in calendar events\r\n * @memberof BucketCtrl\r\n * @param {array} routes - The Scheduled Routes \r\n * @return {array} events \r\n */\n\n\n function formatDuties(duties, isOwnDuty, isApproved) {\n var dutiesEvents = [];\n\n for (var i = 0; i < duties.length; i++) {\n if (duties[i].IsUpdated) {\n console.log(duties[i]);\n }\n /*************** Add main event for duty *********************/\n // var eType = (isOwnDuty ? 'own-' : 'shared-') + duties[i].DutyType.toLowerCase();\n\n\n var eClassName = getEventClassName(duties[i], isOwnDuty, isApproved);\n var eIcons = getEventIcons(duties[i], isOwnDuty, isApproved);\n var eTitle = getEventTitle(duties[i], isOwnDuty) + (duties[i].TotalSharedDuties == undefined ? \"\" : duties[i].TotalSharedDuties);\n var eOtherInfos = getOtherInfos(duties[i], isOwnDuty);\n var event = {\n _id: duties[i].Id,\n // type: eType,\n icons: eIcons,\n className: eClassName[\"class\"],\n title: eTitle,\n start: duties[i].DutyBegin == duties[i].DutyEnd ? duties[i].DutyDateS : duties[i].DutyBegin,\n end: duties[i].DutyBegin == duties[i].DutyEnd ? null : duties[i].DutyEnd,\n sortOrder: isOwnDuty ? 1 : -1,\n otherInfos: eOtherInfos,\n shareable: duties[i].Shareable,\n isOwnDuty: isOwnDuty,\n isApproved: isApproved,\n isOwnApproved: duties[i].HasApprovedProposals,\n listViewColor: eClassName.color\n };\n dutiesEvents.push(event);\n }\n\n return dutiesEvents;\n }\n\n function createNotification(duties) {\n var NewPendingProposalsCount = 0;\n var NewApprovedProposalsCount = 0;\n var NewRejectedProposalsCount = 0;\n var notificationText = null;\n\n for (var i = 0; i < duties.length; i++) {\n if (duties[i].IsUpdated) {\n if (duties[i].HasApprovedProposals) {\n NewApprovedProposalsCount++;\n } else {\n NewPendingProposalsCount += duties[i].NewPendingProposalsCount;\n NewRejectedProposalsCount += duties[i].NewRejectedProposalsCount;\n }\n }\n }\n /* var notification = {\r\n NewPendingProposalsCount : NewPendingProposalsCount,\r\n NewApprovedProposalsCount : NewApprovedProposalsCount,\r\n NewRejectedProposalsCount : NewRejectedProposalsCount\r\n }*/\n\n\n if (NewPendingProposalsCount + NewApprovedProposalsCount + NewRejectedProposalsCount > 0) {\n notificationText = \"You have \";\n var hasPrevious = false;\n\n if (NewPendingProposalsCount) {\n notificationText = notificationText + NewPendingProposalsCount + \" pending\";\n hasPrevious = true;\n }\n\n if (NewRejectedProposalsCount) {\n var conjuction = hasPrevious ? NewApprovedProposalsCount ? \", \" : \" and \" : \"\";\n notificationText = notificationText + conjuction + NewRejectedProposalsCount + \" rejected\";\n hasPrevious = true;\n }\n\n if (NewApprovedProposalsCount) {\n var conjuction = hasPrevious ? \" and \" : \"\";\n notificationText = notificationText + conjuction + NewApprovedProposalsCount + \" accepted\";\n }\n\n notificationText = notificationText + \" proposals.\";\n }\n\n return notificationText;\n }\n /**\r\n * Returns an array of strings for icons to display in the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {array} icons - The array of strings for icons to display in the event tile.\r\n */\n\n\n function getEventIcons(duty, isOwnDuty, isApproved) {\n var icons = [];\n if (!isOwnDuty) icons.push('fa-sing-in');else {\n if (duty.IsUpdated) icons.push('fa-star text-orange');\n /* if (duty.PendingProposalsCount > 0 && !isApproved) icons.push('fa-info-circle');*/\n\n if (!duty.Shareable || isApproved) icons.push('fa-lock');\n if (duty.Shared && !isApproved) icons.push('fa-bitbucket');\n }\n return icons;\n }\n /**\r\n * Returns the title for the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {string} title - The title to display in the event tile.\r\n */\n\n\n function getEventTitle(duty, isOwnDuty) {\n var title = '';\n if (isOwnDuty) title += duty.Title;else title += 'Shared duties: ';\n return title;\n }\n /**\r\n * Returns the class for the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {string} className - The class(es) to use for displaying the event tile.\r\n */\n\n\n function getEventClassName(duty, isOwnDuty, isApproved) {\n var eventClass = {\n \"class\": 'fc-bucket ',\n color: ''\n };\n\n if (isOwnDuty) {\n eventClass[\"class\"] += 'fc-own ';\n var hasApprovedTrade = duty.HasApprovedProposals;\n\n if (isApproved == true) {\n eventClass[\"class\"] += 'fc-green-inverted ';\n eventClass.color = 'lv-green-inverted';\n } else if (hasApprovedTrade) {\n eventClass[\"class\"] += 'fc-green ';\n eventClass.color = 'lv-green';\n } else if (duty.Shared) {\n eventClass[\"class\"] += 'fc-primary-inverted ';\n eventClass.color = 'lv-blue';\n }\n /* else if (duty.Shareable && duty.PendingProposalsCount == 0) {\r\n eventClass.class += 'fc-blue ';\r\n eventClass.color = 'lv-blue';\r\n } else if (duty.PendingProposalsCount > 0) {\r\n eventClass.class += 'fc-orange ';\r\n eventClass.color = 'lv-orange';\r\n } else if (duty.Bookmarks != undefined && duty.Bookmarks.length > 0) {\r\n eventClass.class += 'fc-purple-inverted ';\r\n eventClass.color = 'lv-purple-inverted';\r\n } */\n else {\n eventClass[\"class\"] += 'fc-white ';\n eventClass.color = 'lv-white';\n }\n } else {\n eventClass[\"class\"] += 'fc-aluminum ';\n eventClass.color = 'lv-aluminum';\n }\n\n return eventClass;\n }\n /**\r\n * Returns an array of objects for infos (label, number) to display in the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {array} infos - The array of objects for infos (label, number) to display in the event tile.\r\n */\n\n\n function getOtherInfos(duty, isOwnDuty) {\n var infos = [];\n\n if (isOwnDuty) {\n var hasApprovedTrade = duty.HasApprovedProposals;\n\n if (!hasApprovedTrade) {\n if (duty.PendingProposalsCount > 0) infos.push({\n label: 'Proposals',\n num: duty.PendingProposalsCount\n });\n if (duty.BookmarksCount > 0) infos.push({\n label: 'Bookmarks',\n num: duty.BookmarksCount\n }); // var totalBookmarks = (duty.bookmarks == undefined ? 0 : duty.bookmarks.length);\n // if (totalBookmarks > 0) infos.push({ label: 'Bookmarks', num: totalBookmarks.toString() });\n }\n } // else {\n // if (duty.TotalSharedDuties > 0) infos.push({ label: 'Total', num: duty.TotalSharedDuties.toString() });\n // //if (duty.unclaimedShared > 0) infos.push({ label: 'Unclaimed', num: duty.unclaimedShared.toString() });\n // }\n\n\n return infos;\n }\n\n function calendar(events) {\n $('#calendar').fullCalendar('destroy');\n $(\"#calendar\").fullCalendar({\n defaultView: getDefaultView(),\n defaultDate: defaultCalendarDate,\n firstDay: 1,\n lang: 'en',\n editable: false,\n draggable: false,\n selectable: false,\n selectHelper: false,\n unselectAuto: false,\n disableResizing: false,\n droppable: false,\n fixedWeekCount: false,\n nextDayThreshold: \"00:00:00\",\n header: {\n left: 'title',\n center: '',\n right: 'month,listMonth today prev,next'\n },\n timeFormat: 'HH:mm',\n displayEventEnd: true,\n events: events,\n eventOrder: \"sortOrder\",\n eventRender: function eventRender(event, element, icon) {\n element.find('.fc-title').prepend(\"
\");\n\n if ($('#calendar').fullCalendar('getView').type === 'listMonth') {\n element.find('.fc-list-item-title').addClass('listview-icon');\n $.each(event.className, function (index, icon) {\n element.addClass(event.listViewColor);\n });\n $.each(event.icons, function (index, icon) {\n element.find('.listview-icon').prepend(\" \");\n });\n\n if (event.otherInfos != null && event.otherInfos.length > 0) {\n $.each(event.otherInfos, function (index, info) {\n if (info.label == 'Proposals') element.find('.fc-list-item-title').append(\"\" + info.num + \"\");\n });\n }\n } else {\n if (event.icons != null && event.icons.length > 0) {\n element.find('.fc-title').prepend(\"\");\n $.each(event.icons, function (index, icon) {\n element.find('.calendar-icon').append(\" \");\n });\n }\n\n if (event.otherInfos != null && event.otherInfos.length > 0) {\n $.each(event.otherInfos, function (index, info) {\n element.find('.fc-title').append(\"
\" + info.label + \": \" + info.num + \"
\");\n element.find('.fc-list-item-title').add(\"\" + info.num + \"\");\n });\n }\n }\n },\n eventResize: function eventResize(event, delta, revertFunc) {\n changeView(detectMobile(), '#calendar');\n },\n dayRender: function dayRender(date, cell) {},\n // dayClick: function(date, jsEvent, view) {\n // $timeout(function(){ gotoDayBucketView(date); })\n // },\n eventClick: function eventClick(calEvent, jsEvent, view) {\n if (calEvent.shareable == true && calEvent.isOwnDuty && (!calEvent.isApproved || calEvent.isOwnApproved)) {\n $timeout(function () {\n gotoDayBucketView(calEvent._id);\n });\n } else if (calEvent.shareable == false && calEvent.isOwnDuty) {\n if (!calEvent.isApproved) {\n //don't allow click for approved duty\n $timeout(function () {\n unableShare();\n });\n }\n }\n },\n height: 'auto'\n });\n $('.fc-listMonth-button').click(function () {\n SettingsMain.setCalendarViewStyle('listMonth');\n });\n $('.fc-month-button').click(function () {\n SettingsMain.setCalendarViewStyle('month');\n });\n\n if (selectedDate != null && selectedDate != undefined) {\n $(\"#calendar\").fullCalendar('gotoDate', selectedDate);\n }\n }\n\n function getDefaultView() {\n var calendarStyle = SettingsMain.getCalendarViewStyle();\n\n if (calendarStyle == null) {\n calendarStyle = detectMobile() ? \"listMonth\" : \"month\";\n }\n\n return calendarStyle;\n }\n\n function detectMobile() {\n var isMobile = window.innerWidth <= 800 && window.innerHeight <= 735;\n return isMobile;\n }\n /**\r\n * Redirects to bucket calendar day \r\n * @memberof BucketCtrl\r\n */\n\n\n function gotoDayBucketView(dutyId) {\n $location.path('/bucketDay/' + dutyId);\n }\n }\n\n function unableShare() {\n bootbox.dialog({\n message: \"
You can't share this duty, please try another shareable duty.
\",\n title: \"Warning\",\n buttons: {\n cancel: {\n label: \"Close\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n\n function progressBarBox(isOpen) {\n if (isOpen) {\n bootbox.dialog({\n closeButton: false,\n message: '
Please wait...
' //title: \"Please wait...\"\n\n });\n } else {\n bootbox.hideAll();\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('BucketFactory', BucketFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name BucketFactory\r\n * @description \r\n * Get Duties from API \r\n * @ngInject\r\n */\n\n function BucketFactory(GenericService, $http, $q, apiUrl, LogService) {\n /**\r\n * Initialize Bucket\r\n * @memberof BucketFactory\r\n */\n var service = {\n getDutyObject: getDutyObject,\n getDutyById: getDutyById,\n shareDuty: shareDuty,\n acknowledgeProposal: acknowledgeProposal,\n fetchProposal: fetchProposal,\n createProposal: createProposal,\n evaluateProposal: evaluateProposal,\n undoProposalStatus: undoProposalStatus,\n fetchSharedProposal: fetchSharedProposal\n };\n /**\r\n * Gets Bucket Calendar object\r\n * @memberof BucketFactory\r\n * @param {function} callback \r\n */\n\n function getDutyObject(callback) {\n return $http.get(apiUrl + '/bucket/', {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Gets duty object and shared duties object for the BucketDay View\r\n * @memberof BucketFactory\r\n * @param {number} dutyId \r\n * @param {function} callback \r\n */\n\n\n function getDutyById(dutyId, callback) {\n return $http.get(apiUrl + '/bucket/GetBucketDuty/' + dutyId, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Shares/Unshares duty\r\n * @memberof BucketFactory\r\n * @param {object} duty \r\n * @param {function} callback \r\n * @param {function} errorCallback \r\n */\n\n\n function shareDuty(duty, callback, errorCallback) {\n var dutyMinified = {\n Id: duty.Id,\n Shareable: duty.Shareable,\n Shared: duty.Shared,\n Comments: duty.Comments,\n CrewInformation: {\n Email: null,\n Phone: null,\n Comments: null\n }\n };\n return $http.post(apiUrl + '/bucket/ShareDuty/', dutyMinified, {\n 'Content-Type': 'application/json'\n }).then(callback)[\"catch\"](errorCallback);\n }\n /**\r\n * Makes proposal acknowledged \r\n * @memberof BucketFactory\r\n * @param {number} proposalId \r\n * @param {function} callback \r\n */\n\n\n function acknowledgeProposal(proposalId, callback) {\n return $http.get(apiUrl + '/bucket/AcknowledgeProposal?proposalId=' + proposalId, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Fetches proposal info \r\n * @memberof BucketFactory\r\n * @param {number} dutyId \r\n * @param {function} callback \r\n * @returns {object} - Promise containing Proposed and Requested duties alongside Crew and Route details for each one\r\n */\n\n\n function fetchProposal(dutyId, callback) {\n return $http.get(apiUrl + '/bucket/FetchProposal?id=' + dutyId, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Fetches shared proposal info\r\n * @param {number} dutyId \r\n * @param {number} sharedDutyId \r\n * @param {function} callback\r\n * @returns {object} - Promise containing Proposed and Requested duties alongside Crew and Route details for each one\r\n */\n\n\n function fetchSharedProposal(dutyId, sharedDutyId, callback) {\n return $http.get(apiUrl + '/bucket/FetchSharedProposal?dutyId=' + dutyId + '&sharedDutyId=' + sharedDutyId, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Creates/Sends Proposal\r\n * @memberof BucketFactory\r\n * @param {object} proposal - Containing proposedDutiesIdList and requestedDutiesIdList\r\n * @param {function} callback\r\n * @returns {object} - Promise containing updated proposal \r\n */\n\n\n function createProposal(proposal, callback) {\n return $http.post(apiUrl + '/bucket/CreateProposal', proposal, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Approves/Rejects proposal\r\n * @memberof BucketFactory\r\n * @param {object} proposal - Containing Id and isApproved\r\n * @param {function} callback\r\n * @returns {object} - Promise containing updated proposal \r\n */\n\n\n function evaluateProposal(proposal, callback) {\n return $http.put(apiUrl + '/bucket/EvaluateProposal/' + proposal.Id, proposal.isApproved, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Reverts proposal to previous status\r\n * @memberof BucketFactory\r\n * @param {number} proposalId \r\n * @param {function} callback \r\n * @returns {object} - Promise containing updated proposal\r\n */\n\n\n function undoProposalStatus(proposalId, callback) {\n return $http.put(apiUrl + '/bucket/UndoProposalStatus/' + proposalId, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('BucketDayCtrl', BucketDayCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name BucketDayCtrl\r\n * @description \r\n * Shows the Bucket Day informations\r\n * @ngInject\r\n */\n\n function BucketDayCtrl($scope, BucketFactory, $routeParams, $location, $uibModal, UserFactory, SettingsMain, $timeout) {\n var dutyId = $routeParams.dutyId;\n $scope.isSharedLate = false;\n /**\r\n * Checks if duty wont be approved in time because of the weekend \r\n * @memberof BucketDayCtrl\r\n */\n\n function checkLateShare() {\n var today = new Date();\n var dutyDay = new Date($scope.duty.DutyBegin); // how many days until duty date\n\n var trimmedToday = new Date(today);\n var trimmedDutyDay = new Date(dutyDay);\n var diffDays = Date.DifferenceInDays(trimmedToday.trimTime(), trimmedDutyDay.trimTime()); //friday saturday sunday\n\n var fss = [5, 6, 0]; //saturday sunday monday\n\n var ssm = [6, 0, 1]; // today is Fr,Sa,Su AND duty on Sa,Su,Mo AND same weekend\n\n if (fss.contains(today.getDay()) && ssm.contains(dutyDay.getDay()) && diffDays < 4) {\n //friday before 14:00 is not a late share\n if (!(today.getDay() == 5 && today.getUTCHours() < 14)) $scope.isSharedLate = true;\n }\n }\n\n $scope.currentDutyId = dutyId;\n $scope.initialized = false;\n $scope.displayMessage = displayMessage;\n $scope.confirmUnshare = confirmUnshare;\n $scope.shareDuty = shareDuty;\n $scope.isLoading = false;\n var dutyId = $routeParams.dutyId;\n $scope.currentDutyId = dutyId;\n var user = UserFactory.getUser();\n $scope.activeTab = 0;\n $scope.duty = null;\n $scope.Duties = [];\n $scope.proposals = [];\n $scope.toggle = {\n Accepted: true,\n Rejected: false,\n Pending: true,\n Bookmarks: true\n };\n $scope.getProposalBorderStyle = getProposalBorderStyle;\n\n function getProposalBorderStyle(proposal) {\n var textclass = \"\";\n\n if (proposal.Status == \"Bookmarked\" && proposal.State == 'Out') {\n textclass = \"border-left-amber\";\n } else if (proposal.Status == \"Pending\" && proposal.State == 'Out') {\n textclass = \"border-left-light-blue\";\n } else if (proposal.Status == \"Rejected\" || proposal.Status == \"RejectedBySTP\") {\n textclass = \"border-left-red\";\n } else if (proposal.Status == \"Pending\" && proposal.State == 'In') {\n textclass = \"border-left-orange\";\n } else if (proposal.Status == \"Approved\" || proposal.Status == \"ApprovedBySTP\") {\n textclass = \"border-left-green\";\n } else if (proposal.Status == \"Shared\") {\n textclass = \"border-left-blue-gray\";\n }\n\n return textclass;\n }\n\n $scope.logged_user_info = user.aimsId + ' - ' + user.name;\n $scope.hasTimeChange = false;\n $scope.approvedDuty = null;\n $scope.showMobileProposalCriteria = false;\n $scope.filterProposal = filterProposal;\n $scope.hasProposals = hasProposals;\n\n function hasProposals() {\n var value = false;\n\n if ($scope.duty && $scope.duty.Duties) {\n for (var i = 0; i < $scope.duty.Duties.length; i++) {\n if ($scope.duty.Duties[i].Id > 0) {\n value = true;\n break;\n }\n }\n\n if (!value && $scope.activeTab != 1) {\n $scope.activeTab = 1;\n }\n }\n\n return value;\n }\n\n function filterProposal(proposal) {\n var isShown = false;\n\n if (proposal.Id > 0) {\n if (proposal.Status == \"Approved\" || proposal.Status == \"ApprovedBySTP\") {\n $scope.approvedDuty = true;\n if ($scope.toggle.Accepted) isShown = true;\n } else if (proposal.Status == \"Pending\" && $scope.toggle.Pending) {\n isShown = true;\n } else if ((proposal.Status == \"Rejected\" || proposal.Status == \"RejectedBySTP\") && ($scope.toggle.Rejected || !proposal.isAcknowledged)) {\n console.log($scope.toggle.Rejected);\n console.log(proposal);\n isShown = true;\n } else if (proposal.Status == \"Bookmarked\" && $scope.toggle.Bookmarks) {\n isShown = true;\n }\n }\n\n return isShown;\n }\n\n $scope.returnToBucket = returnToBucket;\n $scope.refresh = getData;\n getData();\n\n function getData() {\n $scope.isLoading = true;\n BucketFactory.getDutyById(dutyId, function (responseData) {\n $scope.initialized = true;\n $scope.isLoading = false;\n $scope.duty = responseData.data.data.duty;\n $scope.currentDutyDate = $scope.duty.DutyDateS;\n $scope.Duties = responseData.data.data.duty.Duties;\n $scope.totalItems = $scope.Duties.length;\n $scope.currentPage = 1;\n SettingsMain.setCalendarSelectedDate($scope.currentDutyDate);\n checkLateShare();\n initProposalsView();\n })[\"catch\"](function (error) {\n $scope.isLoading = false;\n console.error('Wrong AimsId', error.status, error.statusText);\n returnToBucket();\n });\n }\n\n function initProposalsView() {\n $scope.approvedDuty = false;\n\n for (var i = 0; i < $scope.duty.Duties.length; i++) {\n if ($scope.duty.Duties[i].Status == \"Approved\" || $scope.duty.Duties[i].Status == \"ApprovedBySTP\") {\n $scope.approvedDuty = true;\n }\n }\n }\n /**\r\n * Opens a dialog with information on a duty, \r\n * Depending on the duty type (in proposal, out proposal or shared by other in bucket) different options are displayed:\r\n * 1. In proposal\r\n * - Approve (available when in proposal not reviewed, will set status to Approved)\r\n * - Reject (available when in proposal not reviewed, will set status to Rejected)\r\n * - Reset (available when in proposal has been reviewed, will set status to Pending)\r\n * - Close (available always, just closes dialog, no action performed)\r\n * 2. Out proposal\r\n * - Remove (available when out proposal not reviewed, will remove request from duty)\r\n * - Close (available always, just closes dialog, no action performed)\r\n * 3. Shared in bucket\r\n * - Request (available always, will send a request for duty, will be added in out proposals)\r\n * - Close (available always, just closes dialog, no action performed)\r\n * @memberof BucketCtrl\r\n */\n\n /**\r\n * Prompts user to confirm sharing duty, if user agrees then the duty dialog will open \r\n * @memberof BucketCtrl\r\n */\n\n\n function shareDuty(_duty) {\n //if (confirm('You are about to share into global bucket the selected duty. Do you wish to continue?')) {\n _duty.fromShareBtn = true;\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgDuty.html',\n controller: 'BucketModalCtrl',\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n duty: function duty() {\n return _duty;\n },\n currentDutyId: function currentDutyId() {\n return dutyId;\n }\n }\n });\n modalInstance.result.then(function (refresh) {\n if (refresh) {\n getData();\n }\n }); //}\n }\n /**\r\n * Prompts user to confirm removing duty from shared bucket, if user agrees then all proposal for the duty will be removed (will be displayed as N/A to other users) \r\n * @memberof BucketCtrl\r\n */\n\n\n function confirmUnshare() {\n bootbox.dialog({\n message: \"Please confirm that you wish to Un-share your duty.

\",\n title: \"Unshare\",\n buttons: {\n confirm: {\n label: ' Confirm',\n className: \"btn-warning\",\n callback: function callback() {\n BucketFactory.shareDuty($scope.duty, function (responseData) {\n $scope.responseText = responseData.data.data;\n getData();\n });\n }\n },\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n /**\r\n * Redirects to bucket' calendar\r\n * @memberof BucketCtrl\r\n */\n\n\n function returnToBucket() {\n SettingsMain.setEditingPage(null);\n $location.path(\"/bucket/\");\n }\n /**\r\n * Redirects to flights' calendar\r\n * @memberof BucketCtrl\r\n */\n\n\n function gotoFlightsCalendar() {\n SettingsMain.setEditingPage(null);\n $location.path(\"/\");\n } //Pagination\n\n\n $scope.pageOptions = [{\n name: '5',\n value: '5'\n }, {\n name: '8',\n value: '8'\n }, {\n name: '15',\n value: '15'\n }, {\n name: '30',\n value: '30'\n }, {\n name: '50',\n value: '50'\n }];\n $scope.viewby = $scope.pageOptions[1].value;\n $scope.currentPage = 1;\n $scope.itemsPerPage = $scope.viewby;\n $scope.maxSize = 5; //Number of pager buttons to show\n\n $scope.setPage = setPage;\n $scope.setItemsPerPage = setItemsPerPage;\n /**\r\n * Set pagination page number\r\n * @memberof BucketDayCtrl\r\n * @param {number} pageNo list page number\r\n */\n\n function setPage(pageNo) {\n $scope.currentPage = pageNo;\n }\n /**\r\n * Set items per page \r\n * @memberof BucketDayCtrl\r\n * @param {number} num the Number of items to show per page\r\n */\n\n\n function setItemsPerPage(num) {\n $scope.itemsPerPage = num;\n $scope.currentPage = 1; //reset to first page\n }\n\n function displayMessage(message, hasErrors) {\n $scope.showResponse = true;\n $scope.responseText = message;\n $scope.responseHasErrors = hasErrors;\n $timeout(function () {\n if (!hasErrors) {\n $scope.showResponse = false;\n }\n }, 1000);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('BucketModalCtrl', BucketModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name BucketModalCtrl\r\n * @description \r\n * Shows a Share/Unshare Modal \r\n * @ngInject\r\n */\n\n function BucketModalCtrl($scope, $timeout, $uibModalInstance, duty, currentDutyId, BucketFactory) {\n $scope.duty = duty;\n $scope.currentDutyId = currentDutyId;\n $scope.closeDuty = closeDuty;\n $scope.shareDuty = shareDuty;\n $scope.responseText = null;\n $scope.responseHasErrors = null;\n $scope.submitted = false;\n /**\r\n * Close the modal\r\n * @memberof BucketModalCtrl\r\n */\n\n function closeDuty(refresh) {\n $uibModalInstance.close(refresh);\n }\n /**\r\n * Adds/Removes duty to/from global bucket\r\n * @memberof BucketModalCtrl\r\n */\n\n\n function shareDuty() {\n $scope.submitted = true;\n duty.Comments = $scope.duty.Comments;\n BucketFactory.shareDuty(duty, function (responseData) {\n displayMessage(\"Duty shared.\", false);\n $timeout(function () {\n closeDuty(true);\n }, 5000);\n }, function () {\n displayMessage(\"Failed to share duty.\", true);\n });\n }\n /**\r\n * Displays message when share/unshare \r\n * @memberof BucketModalCtrl\r\n * @param {string} message \r\n * @param {boolean} hasErrors \r\n */\n\n\n function displayMessage(message, hasErrors) {\n $scope.responseText = message;\n $scope.responseHasErrors = hasErrors;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('proposal', proposal);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name proposal\r\n * @restrict E\r\n * @description\r\n * Implementation of proposal\r\n * Initialize the proposal element of bucket\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function proposal(BucketFactory, $uibModal, $filter) {\n function link(scope, element, attrs) {\n scope.isOpen = false;\n scope.successful = false;\n scope.error = false;\n scope.proposal.createDisabled = false;\n scope.duty = scope.proposal.Duty;\n scope.loading = false;\n scope.errorMessage = null;\n scope.ProposedDuties = new Array();\n scope.RequestedDuties = new Array();\n scope.AllDuties = new Array();\n scope.fetch = fetchInformation;\n scope.viewInfoModal = viewInfoModal;\n scope.createProposal = createProposal;\n scope.evaluateProposal = evaluateProposal;\n scope.undoProposalStatus = undoProposalStatus;\n scope.acknowledgeProposal = acknowledgeProposal;\n scope.confirmCreateProposal = confirmCreateProposal;\n scope.getFirstInfoIcon = getFirstInfoIcon;\n scope.getSecondInfoIcon = getSecondInfoIcon;\n scope.hasSecondInfoIcon = hasSecondInfoIcon;\n scope.getTextColor = getTextColor;\n scope.getFirstActionIcon = getFirstActionIcon;\n scope.hasFirstActionIcon = hasFirstActionIcon;\n scope.getSecondActionIcon = getSecondActionIcon;\n scope.hasSecondActionIcon = hasSecondActionIcon;\n scope.getFetchIcon = getFetchIcon;\n scope.getInfoMessage = getInfoMessage;\n scope.firstAction = firstAction;\n scope.secondaryAction = secondaryAction;\n scope.showEndDate = showEndDate;\n scope.showTime = showTime;\n\n if (scope.duty.Comments && scope.duty.Comments != \"\") {\n scope.dutyCommentElipsis = dutyCommentElipsis(110);\n scope.showFullComment = false;\n }\n\n scope.toggleFullCommentVisibility = toggleFullCommentVisibility;\n /**\r\n * Toggles proposal comment\r\n * @memberof proposal\r\n */\n\n function toggleFullCommentVisibility() {\n scope.showFullComment = !scope.showFullComment;\n }\n /**\r\n * Shows only the first charNo characters of the comment\r\n * @memberof proposal\r\n * @param {number} charNo \r\n */\n\n\n function dutyCommentElipsis(charNo) {\n var comments = scope.duty.Comments;\n\n if (scope.duty.Comments.length > charNo) {\n comments = scope.duty.Comments.substring(0, charNo) + \"...\";\n }\n\n return comments;\n }\n /**\r\n * Updates proposal when a change occurs (create, evaluate or undo)\r\n * @memberof proposal\r\n * @param {object} newProp - The updated proposal \r\n */\n\n\n function updateProposal(newProp) {\n if (newProp) {\n scope.proposal.Status = newProp.Status;\n scope.proposal.State = newProp.State;\n scope.proposal.Id = newProp.Id;\n scope.proposal.isAcknowledged = newProp.isAcknowledged;\n }\n }\n /**\r\n * Fetches proposal info (Proposed and Requested duties alongside Crew and Route details for each one) \r\n * @memberof proposal\r\n */\n\n\n function fetchInformation() {\n if (!(scope.actionDisabled && scope.proposal.Status == 'Shared')) {\n //only fetch the first time\n if (!(scope.proposal.AllDuties && scope.proposal.AllDuties.length > 0)) {\n scope.loading = true;\n\n if (scope.proposal.Status == \"Shared\" && !scope.actionDisabled) {\n BucketFactory.fetchSharedProposal(scope.currentDutyId, scope.duty.Id, insertInformation)[\"catch\"](errorCall);\n } else {\n BucketFactory.fetchProposal(scope.proposal.Id, insertInformation)[\"catch\"](errorCall);\n }\n } else {\n scope.isOpen = !scope.isOpen; //collapse\n }\n }\n }\n /**\r\n * Handles error from fetchSharedProposal() and fetchProposal() \r\n * @memberof proposal\r\n */\n\n\n function errorCall() {\n scope.isOpen = false;\n scope.loading = false;\n displayMessage(\"Failed to fetch information.\", true);\n }\n /**\r\n * Callback for handling the successful response of fetchSharedProposal() and fetchProposal()\r\n * @memberof proposal\r\n * @param {object} data \r\n */\n\n\n function insertInformation(data) {\n var success = data.data.success;\n var errorMessage = data.data.errorMessage; //always show duties even if success is false\n\n if (data.data.data.duty) {\n var ProposedDuties = data.data.data.duty.ProposedDuties;\n var RequestedDuties = data.data.data.duty.RequestedDuties;\n scope.proposal.HasMultiDuties = data.data.data.duty.HasMultiDuties;\n ProposedDuties = $filter('orderBy')(ProposedDuties, 'DutyDate');\n RequestedDuties = $filter('orderBy')(RequestedDuties, 'DutyDate');\n\n if (ProposedDuties && RequestedDuties) {\n scope.proposal.AllDuties = [];\n var tableMaxRowLength = ProposedDuties.length > RequestedDuties.length ? ProposedDuties.length : RequestedDuties.length;\n\n for (var i = 0; i < tableMaxRowLength; i++) {\n if (scope.proposal.Status == \"Shared\" || scope.proposal.State == \"Out\") {\n var matchedDuty = {\n Proposed: ProposedDuties[i],\n //you give\n Requested: RequestedDuties[i] //you take\n\n };\n } else {\n //scope.proposal.State == \"In\"\n var matchedDuty = {\n Proposed: RequestedDuties[i],\n //you give\n Requested: ProposedDuties[i] //you take\n\n };\n }\n\n scope.proposal.AllDuties.push(matchedDuty);\n }\n\n scope.proposal.ProposedDuties = ProposedDuties;\n scope.proposal.RequestedDuties = RequestedDuties;\n scope.isOpen = true;\n }\n }\n\n if (!success) {\n //if not enough rest time\n //if no available combinations\n scope.proposal.createDisabled = true;\n } else {\n scope.proposal.createDisabled = false;\n } //always show errorMessage even if success is true\n\n\n if (errorMessage && errorMessage.length > 0) {\n displayMessage(errorMessage, true);\n } else {\n scope.errorMessage = null;\n }\n\n scope.loading = false;\n }\n /**\r\n * Opens modal for a specific duty in the table - Shows route and crew info \r\n * @memberof proposal\r\n * @param {number} id \r\n */\n\n\n function viewInfoModal(id) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Bucket/dlgProposalInfo.html',\n controller: 'ProposalInfoModalCtr',\n size: 'lg',\n resolve: {\n ProposedDuties: function ProposedDuties() {\n return scope.proposal.ProposedDuties;\n },\n RequestedDuties: function RequestedDuties() {\n return scope.proposal.RequestedDuties;\n },\n Id: function Id() {\n return id;\n },\n Status: function Status() {\n return scope.proposal.Status;\n },\n State: function State() {\n return scope.proposal.State;\n }\n }\n });\n }\n /**\r\n * Creates/Sends proposal\r\n * @memberof proposal\r\n */\n\n\n function createProposal() {\n var proposedDutiesIdList = [];\n var requestedDutiesIdList = [];\n angular.forEach(scope.proposal.ProposedDuties, function (duty) {\n proposedDutiesIdList.push(duty.Id);\n });\n angular.forEach(scope.proposal.RequestedDuties, function (duty) {\n requestedDutiesIdList.push(duty.Id);\n }); //request body\n\n var proposal = {\n 'proposedDutiesIdList': proposedDutiesIdList,\n 'requestedDutiesIdList': requestedDutiesIdList\n };\n scope.loading = true;\n BucketFactory.createProposal(proposal, function (responseData) {\n displayMessage(\"Proposal has been sent\", false);\n scope.loading = false;\n updateProposal(responseData.data.data);\n\n if (scope.proposal.HasMultiDuties) {\n scope.refresh(); //needed in order to hide other duty from same proposal\n }\n })[\"catch\"](function () {\n displayMessage(\"Failed to sent proposal.\", true);\n scope.loading = false;\n });\n }\n /**\r\n * Approves/Rejects proposal\r\n * @memberof proposal\r\n * @param {boolean} isApproved\r\n */\n\n\n function evaluateProposal(isApproved) {\n var proposal = {};\n proposal.Id = scope.proposal.Id;\n proposal.isApproved = isApproved;\n var onSuccessMessage, onFailureMessage;\n\n if (isApproved) {\n proposal.Status = \"Approved\";\n var onSuccessMessage = \"Approved proposal.\";\n var onFailureMessage = \"Failed to approve proposal.\";\n } else {\n proposal.Status = \"Rejected\";\n var onSuccessMessage = \"Rejected proposal.\";\n var onFailureMessage = \"Failed to reject proposal.\";\n }\n\n scope.loading = true;\n BucketFactory.evaluateProposal(proposal).then(function (responseData) {\n var success = responseData.data.success;\n\n if (success) {\n var newProp = responseData.data.data;\n updateProposal(newProp);\n\n if (isApproved) {\n scope.refresh(); //needed in order to disable other proposals\n }\n\n displayMessage(onSuccessMessage, false);\n } else {\n displayMessage(onFailureMessage, true);\n }\n })[\"catch\"](function () {\n displayMessage(onFailureMessage, true);\n });\n scope.loading = false;\n }\n /**\r\n * Reverts proposal to previous status\r\n * @memberof proposal\r\n */\n\n\n function undoProposalStatus() {\n scope.loading = true;\n var proposal = {};\n proposal.Id = scope.proposal.Id;\n var onSuccessMessage, onFailureMessage;\n\n if (scope.proposal.Status == \"Approved\" || scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'In') {\n var onSuccessMessage = \"Proposal has been reset.\";\n var onFailureMessage = \"Failed to reset proposal.\";\n } else {\n //(scope.proposal.Status == \"Pending\" && scope.proposal.State=='Out')\n var onSuccessMessage = \"Withdrew proposal.\";\n var onFailureMessage = \"Failed to withraw proposal.\";\n }\n\n BucketFactory.undoProposalStatus(proposal.Id).then(function (responseData) {\n var previousStatus = scope.proposal.Status;\n var HasMultiDuties = scope.proposal.HasMultiDuties;\n var newProp = responseData.data.data;\n displayMessage(onSuccessMessage, false);\n scope.loading = false;\n updateProposal(newProp);\n\n if (previousStatus == \"Approved\") {\n scope.refresh(); //needed in order to enable other proposals again \n } else if (previousStatus == \"Pending\" && HasMultiDuties) {\n scope.refresh(); //needed in order to show other duties from same proposal \n }\n })[\"catch\"](function () {\n scope.loading = false;\n displayMessage(onFailureMessage, true);\n });\n }\n /**\r\n * Displays error or success message\r\n * @memberof proposal\r\n * @param {string} message \r\n * @param {boolean} hasErrors \r\n */\n\n\n function displayMessage(message, hasErrors) {\n if (hasErrors) {\n scope.errorMessage = message;\n } else {\n scope.errorMessage = null;\n }\n }\n /**\r\n * Makes proposal acknowledged \r\n * Available when status is 'RejectedBySTP' or status is 'Rejected' and state is 'Out'\r\n * @memberof proposal\r\n */\n\n\n function acknowledgeProposal() {\n scope.loading = true;\n var proposalId = scope.proposal.Id;\n var onFailureMessage = \"Failed to acknowledge proposal.\";\n BucketFactory.acknowledgeProposal(proposalId).then(function (responseData) {\n scope.proposal.isAcknowledged = true;\n scope.loading = false;\n })[\"catch\"](function () {\n scope.loading = false;\n displayMessage(onFailureMessage, true);\n });\n }\n /**\r\n * Changes proposal's first info icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\n\n\n function getFirstInfoIcon() {\n var icon = \"\";\n\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out') {\n icon = \"fa-thumbs-up\";\n } else if (scope.proposal.Status == \"Rejected\") {\n icon = \"fa-thumbs-down\";\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n icon = \"fa-thumbs-o-up\";\n } else if (scope.proposal.Status == \"Shared\") {\n icon = \"fa-bitbucket\";\n } else if (scope.proposal.Status == \"Approved\") {\n icon = \"fa fa-handshake-o\";\n } else if (scope.proposal.Status == \"ApprovedBySTP\") {\n icon = \"fa-thumbs-up\";\n } else if (scope.proposal.Status == \"RejectedBySTP\") {\n icon = \"fa-thumbs-o-down\";\n }\n\n return icon;\n }\n /**\r\n * Changes proposal's second info icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\n\n\n function getSecondInfoIcon() {\n var icon = \"\";\n\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out') {\n icon = \"fa-clock-o text-gray\";\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n icon = \"fa-question-circle-o\";\n }\n\n return icon;\n }\n /**\r\n * Determines second info icon's visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\n\n\n function hasSecondInfoIcon() {\n return scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In' || scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out';\n }\n /**\r\n * Changes column color depending on proposal's state and status\r\n * @memberof proposal\r\n * @returns {string} - Color's class\r\n */\n\n\n function getTextColor() {\n var textclass = \"\";\n\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out') {\n textclass = \"text-light-blue\";\n } else if (scope.proposal.Status == \"Rejected\") {\n textclass = \"text-red\";\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n textclass = \"text-orange\";\n } else if (scope.proposal.Status == \"Approved\") {\n textclass = \"text-green\";\n } else if (scope.proposal.Status == \"Shared\") {\n textclass = \"text-blue-gray\";\n } else if (scope.proposal.Status == \"ApprovedBySTP\") {\n textclass = \"text-green\";\n } else if (scope.proposal.Status == \"RejectedBySTP\") {\n textclass = \"text-red\";\n }\n\n return textclass;\n }\n /**\r\n * Changes proposal's first action icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\n\n\n function getFirstActionIcon() {\n var icon = \"\";\n\n if (scope.proposal.createDisabled) {\n icon = \"fa-ban text-red\"; //no action permitted\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' || scope.proposal.Status == \"Approved\") {\n icon = \" fa-times text-gray \"; //undo\n } else if (scope.proposal.Status == \"Rejected\" && scope.proposal.State == \"In\") {\n icon = \" fa-times text-gray \"; //undo\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In' && !scope.actionDisabled) {\n icon = \"fa-thumbs-o-up text-green\"; //approve\n } else if (scope.proposal.Status == \"Shared\" && !scope.actionDisabled) {\n icon = \"fa-thumbs-o-up text-light-blue\"; //create\n }\n\n return icon;\n }\n /**\r\n * Changes proposal's fetch icon if create action is disabled \r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\n\n\n function getFetchIcon() {\n var icon = \"\";\n\n if (scope.proposal.createDisabled) {\n icon = \"fa-ban text-red\";\n } else {\n icon = \"fa-search\";\n }\n\n return icon;\n }\n /**\r\n * Changes proposal's second action icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\n\n\n function getSecondActionIcon() {\n var icon = \"\";\n\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n icon = \"fa-thumbs-o-down text-red\"; //reject\n }\n\n return icon;\n }\n /**\r\n * Determines first action icon's visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\n\n\n function hasFirstActionIcon() {\n return !(scope.proposal.Status == \"ApprovedBySTP\" || scope.proposal.Status == \"RejectedBySTP\");\n }\n /**\r\n * Determines second action icon's visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\n\n\n function hasSecondActionIcon() {\n return scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In' || scope.proposal.Status == \"Shared\";\n }\n /**\r\n * Returns info message depending on proposal's state and status\r\n * @memberof proposal\r\n * @returns {string} - Message\r\n */\n\n\n function getInfoMessage() {\n var text = \"\";\n\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out') {\n text = \"your proposal is pending\";\n } else if (scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'Out') {\n text = \"your proposal has been rejected\";\n } else if (scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'In') {\n text = \"you have rejected the proposal\";\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n text = \"your response is pending\";\n } else if (scope.proposal.Status == \"Approved\" && scope.proposal.State == 'In') {\n text = \"you have accepted the proposal. Your request is sent for approval\";\n } else if (scope.proposal.Status == \"Approved\" && scope.proposal.State == 'Out') {\n text = \"your proposal has been accepted! Your request is sent for approval\";\n } else if (scope.proposal.Status == \"ApprovedBySTP\") {\n text = \"your request has been approved!\";\n } else if (scope.proposal.Status == \"RejectedBySTP\") {\n text = \"your request has been rejected by STP\";\n }\n\n return text;\n }\n /**\r\n * Determines duty's endDate visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\n\n\n function showEndDate(duty) {\n var show = false;\n var diffMin = Date.DifferenceInMinutes(duty.DutyBegin, duty.DutyEnd);\n var diffHours = diffMin / 60;\n\n if (diffHours >= 24) {\n //endDate will show if duty exceeds 24 hours\n show = true;\n }\n\n return show;\n }\n /**\r\n * Hides duty begin and end time if needed\r\n * @param {object} duty \r\n */\n\n\n function showTime(duty) {\n var show = true;\n var diffMin = Date.DifferenceInMinutes(duty.DutyBegin, duty.DutyEnd);\n\n if (!diffMin) {\n //Time will not show if duty lasts all day (ex. Day Off: 00:00 - 00:00)\n show = false;\n }\n\n return show;\n }\n /**\r\n * Chooses first icon's action depending on proposal's state and status\r\n * @memberof proposal\r\n */\n\n\n function firstAction() {\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out') {\n undoProposalStatus();\n } else if (scope.proposal.Status == \"Approved\") {\n confirmUndoApproved();\n } else if (scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'In') {\n undoProposalStatus();\n } else if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n evaluateProposal(true); //approve\n } else if (scope.proposal.Status == \"Shared\" && !scope.proposal.createDisabled) {\n if (scope.errorMessage && scope.errorMessage.length > 0) {\n confirmCreateProposal(); //fetch success with errorMessage\n } else {\n createProposal();\n }\n }\n }\n /**\r\n * Chooses second icon's action depending on proposal's state and status\r\n * @memberof proposal\r\n */\n\n\n function secondaryAction() {\n if (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') {\n evaluateProposal(false); // reject proposal\n }\n }\n /**\r\n * Opens confirmation modal when undo is requested on an approved proposal\r\n * @memberof proposal\r\n */\n\n\n function confirmUndoApproved() {\n bootbox.dialog({\n message: \"You are about to cancel your accepted proposal.

\",\n title: \"Caution!\",\n buttons: {\n confirm: {\n label: 'Confirm',\n className: \"btn-danger\",\n callback: function callback() {\n undoProposalStatus();\n }\n },\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n /**\r\n * Opens confirmation modal when create is requested on an alternate proposal\r\n * @memberof proposal\r\n */\n\n\n function confirmCreateProposal() {\n bootbox.dialog({\n message: \"Would you like to proceed with the alternate proposal?

\",\n title: \"Send request\",\n buttons: {\n confirm: {\n label: 'Confirm',\n className: \"btn-success\",\n callback: function callback() {\n createProposal();\n }\n },\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/bucket/proposal.tpl.html',\n scope: {\n proposal: '=',\n displayMessage: '&onDisplay',\n refresh: '&onRefresh',\n actionDisabled: '=',\n currentDutyDate: '=',\n currentDutyId: '=',\n sharedCount: '='\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ProposalInfoModalCtr', ProposalInfoModalCtr);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ProposalInfoModalCtr\r\n * @description \r\n * Shows duty crew and route info\r\n * @ngInject\r\n */\n\n function ProposalInfoModalCtr($scope, $uibModalInstance, ProposedDuties, RequestedDuties, Id, Status, State) {\n $scope.RequestedDuties = RequestedDuties;\n $scope.ProposedDuties = ProposedDuties;\n $scope.cancel = cancel;\n $scope.next = next;\n $scope.previous = previous;\n var allDuties = []; //\"You give\" items are put first in list\n\n if (Status == \"Shared\" || State == \"Out\") {\n allDuties = ProposedDuties.concat(RequestedDuties);\n } else {\n //State == \"In\"\n allDuties = RequestedDuties.concat(ProposedDuties);\n }\n\n for (var i = 0; i < allDuties.length; i++) {\n if (allDuties[i].Id == Id) {\n $scope.currentPage = i + 1;\n break;\n }\n }\n\n $scope.allDuties = allDuties;\n /**\r\n * Moves to next duty\r\n * @memberof ProposalInfoModalCtr\r\n */\n\n function next() {\n if ($scope.currentPage != allDuties.length) $scope.currentPage++;\n }\n /**\r\n * Moves to previous duty\r\n * @memberof ProposalInfoModalCtr\r\n */\n\n\n function previous() {\n if ($scope.currentPage != 1) $scope.currentPage--;\n }\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('cancel');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('DataCleanerFactory', DataCleanerFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name DataCleanerFactory\r\n * @description \r\n * Cleans the Data of the application\r\n * @ngInject\r\n */\n\n function DataCleanerFactory(localStorageMD5Service, IndexedDBService, GenericService) {\n var objCallbackRatings = objCallbackRatings;\n var service = {\n deleteAllReports: deleteAllReports,\n deleteAllServerData: deleteAllServerData,\n deleteAllData: deleteAllData,\n deleteOrphanedLocalFlights: deleteOrphanedLocalFlights,\n deleteOrphanedLocalReports: deleteOrphanedLocalReports,\n deleteSynchedLocalPilotReports: deleteSynchedLocalPilotReports,\n deleteOldCrewMealsRatings: deleteOldCrewMealsRatings\n };\n /**\r\n * Delete All Cabin Reports\r\n * @memberof DataCleanerFactory\r\n */\n\n function deleteAllReports() {\n localStorageMD5Service.remove('pilotReportLocalEdits');\n localStorageMD5Service.remove('pilotReportLocalEdit_TEMP');\n deleteOrphanedLocalFlights();\n }\n\n ;\n /**\r\n * Delete Basic Server data\r\n * @memberof DataCleanerFactory\r\n */\n\n function deleteAllServerData() {\n localStorageMD5Service.remove('flights');\n localStorageMD5Service.remove('reportGuids');\n localStorageMD5Service.remove('aircraftTypes');\n localStorageMD5Service.remove('pilotReportTemplate');\n localStorageMD5Service.remove('syncLog');\n localStorageMD5Service.remove('pilotReportSyncResults');\n localStorageMD5Service.remove('FAQItem');\n localStorageMD5Service.remove('PaxInfo');\n localStorageMD5Service.remove('aircaftpositions');\n localStorageMD5Service.remove('scheduleChanges');\n localStorageMD5Service.remove('CheckIn');\n localStorageMD5Service.remove('flightCheckIns');\n deleteOrphanedLocalFlights();\n }\n\n ;\n /**\r\n * Delete All Server data\r\n * @memberof DataCleanerFactory\r\n */\n\n function deleteAllData() {\n localStorageMD5Service.clearAll();\n IndexedDBService.deleteDatabase();\n }\n\n ;\n /**\r\n * Delete local flights that have no stored local reports\r\n * @memberof DataCleanerFactory\r\n */\n\n function deleteOrphanedLocalFlights() {\n var existingLocalFlights = localStorageMD5Service.get('localFlights');\n if (existingLocalFlights == null) return;\n var finalLocalFlights = new Array();\n var pilotReportLocalEdits = localStorageMD5Service.get('pilotReportLocalEdits');\n if (pilotReportLocalEdits == null) pilotReportLocalEdits = new Array(); // check every local flight that has a saved pilot report\n\n for (var i = 0; i < existingLocalFlights.length; i++) {\n var hasPilotReport = false;\n\n for (var j = 0; j < pilotReportLocalEdits.length; j++) {\n if (pilotReportLocalEdits[j].FlightId != null && pilotReportLocalEdits[j].FlightId == existingLocalFlights[i].FlightId || pilotReportLocalEdits[j].FlightAimsId != null && pilotReportLocalEdits[j].FlightAimsId == existingLocalFlights[i].FlightAimsId) {\n hasPilotReport = true;\n break;\n }\n } // if it has a pilot report, add it to the flights to save\n\n\n if (hasPilotReport) finalLocalFlights.push(existingLocalFlights[i]);\n } // save the resulting local flights\n\n\n localStorageMD5Service.set('localFlights', finalLocalFlights);\n }\n /**\r\n * Delete local reports that have no stored local flights\r\n * @memberof DataCleanerFactory\r\n */\n\n\n function deleteOrphanedLocalReports() {\n var existingLocalPilotReports = localStorageMD5Service.get('pilotReportLocalEdits');\n var flights = localStorageMD5Service.get('flights');\n if (existingLocalPilotReports == null || flights == null || existingLocalPilotReports.length == 0 || flights.length == 0) return 0;\n var finalLocalPilotReports = new Array();\n\n for (var i = 0; i < existingLocalPilotReports.length; i++) {\n var remove = false;\n\n if (existingLocalPilotReports[i].Status == 'synched') {\n remove = true;\n\n if (existingLocalPilotReports[i].FlightId != null || existingLocalPilotReports[i].FlightAimsId != null) {\n for (var j = 0; j < flights.length; j++) {\n if (existingLocalPilotReports[i].FlightId != null && existingLocalPilotReports[i].FlightId == flights[j].FlightId || existingLocalPilotReports[i].FlightAimsId != null && existingLocalPilotReports[i].FlightAimsId == flights[j].FlightAimsId) {\n remove = false;\n }\n }\n }\n }\n\n if (!remove) finalLocalPilotReports.push(existingLocalPilotReports[i]);\n } // save the resulting local reports\n\n\n localStorageMD5Service.set('pilotReportLocalEdits', finalLocalPilotReports);\n }\n /**\r\n * Delete Synched Local PilotReports\r\n * @memberof DataCleanerFactory\r\n */\n\n\n function deleteSynchedLocalPilotReports() {\n var existingLocalPilotReports = localStorageMD5Service.get('pilotReportLocalEdits');\n var flights = localStorageMD5Service.get('flights');\n if (existingLocalPilotReports == null || flights == null || existingLocalPilotReports.length == 0 || flights.length == 0) return 0;\n var finalLocalPilotReports = new Array();\n var deleted = 0;\n var flight = null;\n var user = localStorageMD5Service.get('user');\n ; // check every saved cabin report\n\n for (var i = 0; i < existingLocalPilotReports.length; i++) {\n var remove = false;\n\n if (existingLocalPilotReports[i].Status == 'synched') {\n if (existingLocalPilotReports[i].FlightId != null || existingLocalPilotReports[i].FlightAimsId != null) {\n for (var j = 0; j < flights.length; j++) {\n if (existingLocalPilotReports[i].FlightId != null && existingLocalPilotReports[i].FlightId == flights[j].FlightId || existingLocalPilotReports[i].FlightAimsId != null && existingLocalPilotReports[i].FlightAimsId == flights[j].FlightAimsId) {\n for (var h = 0; h < flights[j].pilotReports.length; h++) {\n if (flights[j].pilotReports[h].AuthorAimsId == user.aimsId) {\n remove = true;\n deleted++;\n }\n }\n }\n }\n }\n }\n\n if (!remove) finalLocalPilotReports.push(existingLocalPilotReports[i]);\n } // save the resulting local reports\n\n\n localStorageMD5Service.set('pilotReportLocalEdits', finalLocalPilotReports);\n return deleted;\n }\n /**\r\n * Deletes CrewMealRatings that are older than 20 days\r\n * @memberof DataCleanerFactory\r\n */\n\n\n function deleteOldCrewMealsRatings() {\n var res = GenericService.list(\"CrewMealRatings\", objCallbackRatings);\n var lastDate = new Date();\n lastDate.setDate(lastDate.getDate() - 20);\n var crewMealIdsFiltered = res.filter(function (r) {\n return new Date(r.TimeStamp) >= lastDate;\n });\n GenericService.saveOne(crewMealIdsFiltered, \"CrewMealRatings\");\n }\n\n function objCallbackRatings() {\n this.CrewMealId = null, this.TimeStamp = null;\n }\n\n return service;\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.filter('fltSplit', fltSplit);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name messageFilter\r\n * @description \r\n * Filters messages in order to show only the unread.\r\n * @ngInject\r\n */\n\n function fltSplit() {\n return function (fltSplit) {\n var formattedFltNo = fltSplit;\n\n if (typeof fltSplit === 'string' || fltSplit instanceof String) {\n formattedFltNo = fltSplit.replace(/(\\w{2})/, '$1 ');\n }\n\n return formattedFltNo;\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('GenericService', GenericService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GenericService\r\n * @description \r\n * Generic add, edit or remove\r\n * @ngInject\r\n */\n\n function GenericService(localStorageMD5Service) {\n var objectType = null;\n var objectCallback = null;\n var service = {\n initiate: initiate,\n get: get,\n getOne: getOne,\n list: list,\n save: save,\n saveOne: saveOne,\n saveAll: saveAll,\n remove: remove,\n removeAll: removeAll,\n add: add,\n constructor: constructor,\n fromObject: fromObject,\n fromObjectList: fromObjectList\n };\n /**\r\n * initiate type and callback\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @memberof GenericService\r\n */\n\n function initiate(type, callback) {\n objectType = type;\n objectCallback = callback;\n }\n /**\r\n * Get the requested object\r\n * @memberof GenericService\r\n * @param {number} id The unique identifier\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} result\r\n */\n\n\n function get(id, type, callback) {\n initiate(type, callback);\n var objects = list(type, callback);\n if (objects == null) return null;\n var result = null;\n var arrayLength = objects.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (objects[i].GetId() == id) {\n result = objects[i];\n break;\n }\n }\n\n return result;\n }\n /**\r\n * Get all the objects\r\n * @memberof GenericService\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {array} objectList\r\n */\n\n\n function list(type, callback) {\n initiate(type, callback);\n var objects = localStorageMD5Service.get(objectType);\n return fromObjectList(objects, callback);\n }\n /**\r\n * Get the unique object of this storage\r\n * @memberof GenericService\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @return {object} object\r\n */\n\n\n function getOne(type, callback) {\n initiate(type, callback);\n var object = localStorageMD5Service.get(objectType);\n return fromObject(object, callback);\n }\n\n function saveOne(obj, type, callback) {\n localStorageMD5Service.set(type, obj);\n }\n\n function save(object, type, callback) {\n initiate(type, callback);\n var objects = list(type, callback);\n var updatedobject = fromObject(object, callback);\n var arrayLength = objects.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (objects[i].GetId() == updatedobject.GetId()) {\n objects[i] = updatedobject;\n break;\n }\n }\n\n saveAll(objects, type, callback);\n }\n\n function saveAll(objects, type, callback) {\n initiate(type, callback);\n localStorageMD5Service.set(objectType, objects);\n }\n\n function remove(Id, type, callback) {\n initiate(type, callback);\n var objects = list(type, callback);\n var newObjects = [];\n var arrayLength = objects.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (objects[i].GetId() != Id) {\n newObjects.push(objects[i]);\n }\n }\n\n saveAll(newObjects, type, callback);\n }\n\n function removeAll(type, callback) {\n initiate(type, callback);\n localStorageMD5Service.remove(objectType);\n }\n\n function add(obj, type, callback) {\n var objects = list(type, callback);\n objects.push(obj);\n saveAll(objects, type, callback);\n }\n\n function constructor(callback) {\n var object = new callback();\n return object;\n }\n\n function fromObject(obj, callback) {\n if (obj == null) return null;\n var object = new callback();\n angular.extend(object, obj);\n return object;\n }\n\n function fromObjectList(objList, callback) {\n if (objList == null) return [];\n var arrayLength = objList.length;\n var objects = new Array();\n\n for (var i = 0; i < arrayLength; i++) {\n objects.push(fromObject(objList[i], callback));\n }\n\n return objects;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('GenericModalFactory', GenericModalFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GenericModalFactory\r\n * @description \r\n * Initialize generic Modals\r\n * @ngInject\r\n */\n\n function GenericModalFactory() {\n var service = {\n createNew: createNew,\n fromObject: fromObject,\n deleteFromList: deleteFromList,\n fromObjectList: fromObjectList\n };\n /**\r\n * Greate new Object based on given constructor\r\n * @memberof GenericModalFactory\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} result\r\n */\n\n function createNew(callback) {\n var result = new callback();\n result.Id = guid();\n return result;\n }\n /**\r\n * Extend given object \r\n * @memberof GenericModalFactory\r\n * @param {object} obj The object that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} object\r\n */\n\n\n function fromObject(obj, callback) {\n if (obj == null) return null;\n var object = new callback();\n angular.extend(object, obj);\n return object;\n }\n /**\r\n * Delete an object from given List\r\n * @memberof GenericModalFactory\r\n * @param {object} obj The object that will be removed\r\n * @param {array} objList A list that will be modified\r\n * @returns {array} objList\r\n */\n\n\n function deleteFromList(obj, objList) {\n // find the current item in the array (if present)\n var arrayLength = objList.length;\n var itemIndex = -1;\n\n for (var i = 0; i < arrayLength; i++) {\n if (objList[i].Id == obj.Id) {\n itemIndex = i;\n break;\n }\n }\n\n if (itemIndex >= 0) objList.splice(itemIndex, 1);\n return objList;\n }\n /**\r\n * Extend given object list\r\n * @memberof GenericModalFactory\r\n * @param {array} objList The list of objects that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} objList\r\n */\n\n\n function fromObjectList(objList, callback) {\n if (objList == null) return [];\n var arrayLength = objList.length;\n var newobjList = [];\n\n for (var i = 0; i < arrayLength; i++) {\n var obj = new callback();\n angular.extend(obj, objList[i]);\n newobjList.push(obj);\n }\n\n return newobjList;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('GenericValuesFactory', GenericValuesFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GenericValuesFactory\r\n * @description \r\n * Generic add, edit or remove for list of values\r\n * @ngInject\r\n */\n\n function GenericValuesFactory(localStorageMD5Service) {\n var service = {\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n objList: objList,\n getValuesFromStorage: getValuesFromStorage,\n setValuesToStorage: setValuesToStorage,\n clearValuesFromStorage: clearValuesFromStorage,\n getValuesFromStorageAsStrings: getValuesFromStorageAsStrings\n };\n /**\r\n * Extend given object \r\n * @memberof GenericValuesFactory\r\n * @param {object} obj The object that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} object\r\n */\n\n function fromObject(obj, callback) {\n if (obj == null) return null;\n var newObj = new callback();\n newObj.Code = obj;\n return newObj;\n }\n /**\r\n * Extend given object list\r\n * @memberof GenericValuesFactory\r\n * @param {array} objList The list of objects that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} objList\r\n */\n\n\n function fromObjectList(objList, callback) {\n if (objList == null) return null;\n var arrayLength = objList.length;\n var newObjList = [];\n\n for (var i = 0; i < arrayLength; i++) {\n var newObj = new callback();\n newObj.Code = objList[i];\n newObjList.push(newObj);\n }\n\n return newObjList;\n }\n /**\r\n * Get all the object's Code from given list\r\n * @memberof GenericValuesFactory\r\n * @param {array} objectList An object list\r\n * @returns {array} objectList\r\n */\n\n\n function objList(objList) {\n if (objList == null) return [];\n var arrayLength = objList.length;\n var newObjList = [];\n\n for (var i = 0; i < arrayLength; i++) {\n newObjList.push(objList[i].Code);\n }\n\n return newObjList;\n }\n /**\r\n * Get all the objects\r\n * @memberof GenericValuesFactory\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {array} objectList\r\n */\n\n\n function getValuesFromStorage(callback, type) {\n var objects = localStorageMD5Service.get(type);\n return fromObjectList(objects, callback);\n }\n /**\r\n * Set all the objects\r\n * @memberof GenericValuesFactory\r\n * @param {array} objects A list of objects.\r\n * @param {string} type A string which identifies the local storage name\r\n */\n\n\n function setValuesToStorage(objects, type) {\n localStorageMD5Service.set(type, objects);\n }\n /**\r\n * Remove all the objects\r\n * @memberof GenericValuesFactory\r\n * @param {string} type A string which identifies the local storage name\r\n */\n\n\n function clearValuesFromStorage(type) {\n localStorageMD5Service.remove(type);\n }\n /**\r\n * Get all the objects codes from local storage\r\n * @memberof GenericValuesFactory\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {array} objectList\r\n */\n\n\n function getValuesFromStorageAsStrings(callback, type) {\n var result = [];\n var objs = getValuesFromStorage(callback, type);\n\n if (objs != null || objs != undefined) {\n for (var i = 0; i < objs.length; i++) {\n result.push(objs[i].Code);\n }\n }\n\n return result;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('IndexedDBService', IndexedDBService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name IndexedDBService\r\n * @description \r\n * Generic add, edit or remove for IndexedDB\r\n * @ngInject\r\n */\n\n function IndexedDBService($q, LogService) {\n var idbSupported = (\"indexedDB\" in window);\n\n if (!idbSupported) {\n LogService.debug(\"No IndexedDb is supported for this browser's version\");\n }\n\n return {\n /**\r\n * initiate or update indexedDB storage\r\n * @memberof IndexedDBService\r\n * @returns {object} promise\r\n */\n init: function init() {\n var deferred = $q.defer();\n var request = indexedDB.open(\"a3.pilot.reports\", 5);\n\n request.onupgradeneeded = function (e) {\n // The database did not previously exist, so create object stores and indexes.\n var db = request.result;\n\n if (e.oldVersion < 1) {\n var gameStore = db.createObjectStore(\"Memos\", {\n keyPath: \"Id\"\n });\n gameStore.createIndex(\"id_idx\", \"Id\", {\n unique: true\n });\n }\n\n if (e.oldVersion < 2) {\n var gameStore1 = db.createObjectStore(\"MemoImages\", {\n keyPath: \"imageId\"\n });\n gameStore1.createIndex(\"id_idx\", \"imageId\", {\n unique: true\n });\n gameStore1.createIndex(\"memoId\", \"memoId\", {\n unique: false\n });\n }\n\n if (e.oldVersion <= 3 && !db.objectStoreNames.contains('Courses')) {\n var gameStore3 = db.createObjectStore(\"Courses\", {\n keyPath: \"Id\"\n });\n gameStore3.createIndex(\"id_idx\", \"Id\", {\n unique: true\n });\n var store4 = db.createObjectStore(\"TrainingSessions\", {\n keyPath: ['day', 'courseId', 'dutyId']\n });\n store4.createIndex(\"id_idx\", ['day', 'courseId', 'dutyId'], {\n unique: true\n });\n store4.createIndex(\"day_idx\", \"day\", {\n unique: false\n });\n store4.createIndex(\"courseId_idx\", \"courseId\", {\n unique: false\n });\n }\n\n if (e.oldVersion <= 4 && !db.objectStoreNames.contains('FlightSessions')) {\n var store = db.createObjectStore(\"FlightSessions\", {\n keyPath: ['day', 'courseId', 'dutyNo', 'dutyDay']\n });\n store.createIndex(\"id_idx\", ['day', 'courseId', 'dutyNo', 'dutyDay'], {\n unique: true\n });\n store.createIndex(\"day_idx\", \"day\", {\n unique: false\n });\n store.createIndex(\"courseId_idx\", \"courseId\", {\n unique: false\n });\n }\n };\n\n request.onsuccess = function () {\n deferred.resolve(request.result);\n };\n\n request.onerror = function () {\n deferred.reject(request.error);\n };\n\n return deferred.promise;\n },\n deleteDatabase: function deleteDatabase() {\n indexedDB.deleteDatabase(\"a3.pilot.reports\");\n },\n\n /**\r\n * Add the object\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {object} entity The object to add\r\n * @returns {object} promise\r\n */\n add: function add(storeName, entity) {\n var deferred = $q.defer();\n\n var add = function add(db) {\n var tx = db.transaction([storeName], \"readwrite\");\n var store = tx.objectStore(storeName);\n store.add(entity);\n\n tx.oncomplete = function (e) {\n // All requests have succeeded and the transaction has committed.\n deferred.resolve(entity.id);\n };\n\n tx.onerror = function (ex) {\n deferred.reject(ex);\n };\n\n tx.onabort = function (ex) {\n deferred.reject(ex);\n };\n };\n\n if (idbSupported) {\n this.init().then(add);\n } else {\n deferred.resolve();\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Add all the objects\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {array} entity The objects to add\r\n * @returns {object} promise\r\n */\n addAll: function addAll(storeName, entity) {\n var deferred = $q.defer();\n\n var add = function add(db) {\n var tx = db.transaction([storeName], \"readwrite\");\n var store = tx.objectStore(storeName);\n var count = 0; //Insert several objects: [{obj},{obj},{obj}]\n\n for (var i = 0; i < entity.length; i++) {\n store.add(entity[i]);\n count++;\n }\n\n tx.oncomplete = function (e) {\n // All requests have succeeded and the transaction has committed.\n deferred.resolve(count);\n };\n\n tx.onerror = function (ex) {\n deferred.reject(ex);\n };\n\n tx.onabort = function (ex) {\n deferred.reject(ex);\n }; //db.close();\n\n };\n\n if (idbSupported) {\n this.init().then(add);\n } else {\n deferred.resolve();\n }\n\n return deferred.promise;\n },\n\n /**\r\n * update object\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {array} entity The object to update\r\n * @returns {object} promise\r\n */\n put: function put(storeName, entity) {\n var deferred = $q.defer();\n\n var put = function put(db) {\n var tx = db.transaction([storeName], \"readwrite\");\n var store = tx.objectStore(storeName);\n store.put(entity);\n\n tx.oncomplete = function () {\n // All requests have succeeded and the transaction has committed.\n deferred.resolve(tx.result);\n };\n\n tx.onerror = function () {\n deferred.reject(tx);\n };\n\n tx.onabort = function () {\n deferred.reject(tx);\n };\n };\n\n if (idbSupported) {\n this.init().then(put);\n } else {\n deferred.resolve();\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Get the requested object by the default index\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\n getById: function getById(storeName, id) {\n var deferred = $q.defer();\n\n var getById = function getById(db) {\n var tx = db.transaction([storeName], \"readonly\");\n var store = tx.objectStore(storeName);\n var index = store.index(\"id_idx\");\n var request = index.get(id);\n\n request.onsuccess = function () {\n deferred.resolve(request.result);\n };\n\n request.onerror = function () {\n deferred.reject(request.error);\n };\n\n tx.onabort = function () {\n deferred.reject(tx.error);\n };\n };\n\n if (idbSupported) {\n this.init().then(getById);\n } else {\n deferred.resolve(null);\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Get the requested object by the selected index\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\n getByIndex: function getByIndex(storeName, indexName, value) {\n var deferred = $q.defer();\n\n var getByIndex = function getByIndex(db) {\n var tx = db.transaction([storeName], \"readonly\");\n var store = tx.objectStore(storeName);\n var index = store.index(indexName);\n var request = index.openCursor(IDBKeyRange.only(value)); //IDBKeyRange.only(value)\n\n var results = [];\n\n request.onsuccess = function () {\n var cursor = request.result;\n\n if (cursor) {\n results.push(cursor.value);\n cursor[\"continue\"]();\n } else {\n deferred.resolve(results);\n }\n };\n\n request.onerror = function (r) {\n deferred.reject(r.error);\n };\n\n tx.onabort = function (r) {\n deferred.reject(r.error);\n };\n };\n\n if (idbSupported) {\n this.init().then(getByIndex);\n } else {\n deferred.resolve(null);\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Get the all objects of the selected store\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name (optional)\r\n * @returns {object} promise\r\n */\n getAll: function getAll(storeName, indexName) {\n var deferred = $q.defer();\n if (indexName === undefined) indexName = 'id_idx';\n\n var all = function all(db) {\n var tx = db.transaction([storeName], \"readonly\");\n var store = tx.objectStore(storeName); //var index = store.index(indexName);\n\n var request = store.openCursor(); //IDBKeyRange.only(\"Fred\")\n\n var results = [];\n\n request.onsuccess = function () {\n var cursor = request.result;\n\n if (cursor) {\n results.push(cursor.value);\n cursor[\"continue\"]();\n } else {\n deferred.resolve(results);\n }\n };\n\n request.onerror = function () {\n deferred.reject(request.error);\n };\n\n tx.onabort = function () {\n deferred.reject(tx.error);\n };\n };\n\n if (idbSupported) {\n this.init().then(all);\n } else {\n deferred.resolve([]);\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Count all objects of the selected store\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name (optional)\r\n * @returns {object} promise\r\n */\n count: function count(storeName, indexName) {\n var deferred = $q.defer();\n if (indexName === undefined) indexName = 'id_idx';\n\n var count = function count(db) {\n var tx = db.transaction([storeName], \"readonly\");\n var store = tx.objectStore(storeName);\n var index = store.index(indexName);\n var request = index.count();\n\n request.onsuccess = function () {\n deferred.resolve(request.result);\n };\n\n request.onerror = function () {\n deferred.reject(request.error);\n };\n\n tx.onabort = function () {\n deferred.reject(tx.error);\n };\n };\n\n if (idbSupported) {\n this.init().then(count);\n } else {\n deferred.resolve(0);\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Delete the requested object\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\n remove: function remove(storeName, id) {\n var deferred = $q.defer();\n\n var remove = function remove(db) {\n var tx = db.transaction([storeName], \"readwrite\");\n var store = tx.objectStore(storeName);\n store[\"delete\"](id);\n\n tx.oncomplete = function (e) {\n // All requests have succeeded and the transaction has committed.\n deferred.resolve(id);\n };\n\n tx.onerror = function (r) {\n deferred.reject(r.error);\n };\n\n tx.onabort = function (r) {\n deferred.reject(r.error);\n };\n };\n\n if (idbSupported) {\n this.init().then(remove);\n } else {\n deferred.resolve();\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Delete the requested object by the selected index\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name (optional)\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\n removeByIndex: function removeByIndex(storeName, indexName, value) {\n var deferred = $q.defer();\n\n var removeByIndex = function removeByIndex(db) {\n var tx = db.transaction([storeName], \"readwrite\");\n var store = tx.objectStore(storeName);\n var index = store.index(indexName);\n var request = index.openKeyCursor(IDBKeyRange.only(value)); //IDBKeyRange.only(value)\n\n var results = [];\n\n request.onsuccess = function () {\n var cursor = request.result;\n\n if (cursor) {\n store[\"delete\"](cursor.primaryKey);\n cursor[\"continue\"]();\n } else {\n deferred.resolve(results);\n }\n };\n\n request.onerror = function (r) {\n deferred.reject(r.error);\n };\n\n tx.onabort = function (r) {\n deferred.reject(r.error);\n };\n };\n\n if (idbSupported) {\n this.init().then(removeByIndex);\n } else {\n deferred.resolve();\n }\n\n return deferred.promise;\n },\n\n /**\r\n * Delete all the objects\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @returns {object} promise\r\n */\n removeAll: function removeAll(storeName) {\n var deferred = $q.defer();\n\n var remove = function remove(db) {\n var tx = db.transaction([storeName], \"readwrite\");\n var store = tx.objectStore(storeName);\n store.clear();\n\n tx.oncomplete = function (e) {\n // All requests have succeeded and the transaction has committed.\n deferred.resolve('success');\n };\n\n tx.onerror = function (r) {\n deferred.reject(r.error);\n };\n\n tx.onabort = function (r) {\n deferred.reject(r.error);\n }; //db.close();\n\n };\n\n if (idbSupported) {\n this.init().then(remove);\n } else {\n deferred.resolve();\n }\n\n return deferred.promise;\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"PushNotifier\", PushNotifier);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name PushNotifier\r\n * @description \r\n * Push notification functionality\r\n * @ngInject\r\n */\n\n function PushNotifier($q, FlightFactory, PaxInfoFactory) {\n var service = {\n Generate: Generate,\n formatInfoToCompare: formatInfoToCompare,\n compareAndExtractChanges: compareAndExtractChanges,\n MessageGenerator: BodyGenerator,\n CheckForPermissionsAndSupport: CheckForPermissionsAndSupport\n };\n var browserSupportsNotifications = (\"Notification\" in window);\n\n function CheckForPermissionsAndSupport() {\n var deferred = $q.defer(); // Let's check if the browser supports notifications\n\n if (!browserSupportsNotifications) {\n console.debug(\"This browser does not support system notifications\");\n deferred.resolve(false);\n } // Otherwise, we need to ask the user for permission\n\n\n if (browserSupportsNotifications && Notification.permission !== 'denied') {\n var permissionQ = Notification.requestPermission();\n\n if (permissionQ) {\n permissionQ.then(function (result) {\n var value = result === \"granted\";\n deferred.resolve(value);\n }), function (reason) {\n LogService.error(reason);\n deferred.reject(reason);\n };\n } else {\n deferred.resolve(false);\n }\n } else {\n deferred.resolve(false);\n }\n\n return deferred.promise;\n }\n\n function Generate(title, body) {\n // Let's check whether notification permissions have already been granted\n if (browserSupportsNotifications && Notification.permission === \"granted\") {\n // If it's okay let's create a notification\n var notification = new Notification(title, {\n body: body,\n icon: './img/a3_logo.png'\n });\n setTimeout(function () {\n notification.close();\n }, 5000);\n }\n }\n\n function formatInfoToCompare(flightId) {\n var flightInfo = FlightFactory.getFlightFromStorage(flightId);\n var paxinfo = PaxInfoFactory.getPaxInfoFromStorage(flightId);\n var data = {\n CTOT: flightInfo.CTOT,\n ATD: flightInfo.ATD,\n ETA: flightInfo.ETA,\n ETD: flightInfo.ETD\n };\n data['Departure Gate'] = flightInfo.DepartureGate;\n data['Departure Stand'] = flightInfo.DepartureStand;\n data['Scheduled Departure Time UTC'] = flightInfo.ScheduledDepartureTimeUTC;\n data['Passenger Info'] = paxinfo ? new Date(paxinfo.LastRun).toString('dd-MM-yyyy HH:mm') : null;\n return data;\n }\n\n function compareAndExtractChanges(currentData, updatedData) {\n var changes = [];\n\n for (var key in currentData) {\n if (currentData[key] != updatedData[key]) {\n var ovalue = currentData[key];\n var nvalue = updatedData[key];\n\n if (key === \"CTOT\" || key === \"ATD\" || key === \"ETA\" || key === \"ETD\" || key === \"Scheduled Departure Time UTC\") {\n if (currentData[key] != null) {\n ovalue = moment.utc(currentData[key]).format('HH:mm');\n }\n\n if (updatedData[key] != null) {\n nvalue = moment.utc(updatedData[key]).format('HH:mm');\n }\n }\n\n changes.push({\n type: key,\n oldValue: ovalue,\n newValue: nvalue\n });\n }\n }\n\n return changes;\n }\n\n function BodyGenerator(changes) {\n var message = '';\n changes.forEach(function (x) {\n var phrase = null;\n\n if (x.type == 'Passenger Info') {\n phrase = \"Passenger Info have been updated. \\n\";\n } else if (!x.oldValue) {\n phrase = x.type + \": \" + x.newValue + \" \\n\";\n } else if (x.oldValue && x.newValue) {\n phrase = x.type + \": \" + x.oldValue + \"\\u2192\" + x.newValue + \" \\n\";\n } else {\n phrase = x.type + \" has no value\\n\";\n }\n\n message = message + phrase;\n });\n return message;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('SettingsMain', SettingsMain);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name SettingsMain\r\n * @description \r\n * Generic add, edit or remove\r\n * @ngInject\r\n */\n\n function SettingsMain(localStorageMD5Service) {\n /**\r\n * Initialize the PageMainSettings\r\n * @memberof SettingsMain\r\n */\n function PageMainSettings() {\n this.EditingPage = null;\n this.selectedDate = null;\n }\n\n var service = {\n getSettings: getSettings,\n setSettings: setSettings,\n getEditingPage: getEditingPage,\n setEditingPage: setEditingPage,\n setCalendarViewStyle: setCalendarViewStyle,\n getCalendarViewStyle: getCalendarViewStyle,\n getCalendarSelectedDate: getCalendarSelectedDate,\n setCalendarSelectedDate: setCalendarSelectedDate\n };\n /**\r\n * Get Application Settings\r\n * @memberof SettingsMain\r\n * @returns {object} settings \r\n */\n\n function getSettings() {\n var settings = new PageMainSettings();\n var settingsStored = localStorageMD5Service.get('settingsMain');\n\n if (settingsStored) {\n if (settingsStored.EditingPage) settings.EditingPage = settingsStored.EditingPage;\n settings.calendarViewStyle = settingsStored.calendarViewStyle;\n settings.selectedDate = settingsStored.selectedDate;\n }\n\n return settings;\n }\n /**\r\n * Set Application Settings\r\n * @param {object} settings\r\n * @memberof SettingsMain\r\n */\n\n\n function setSettings(settings) {\n localStorageMD5Service.set('settingsMain', settings);\n }\n /**\r\n * Get editing page\r\n * @memberof SettingsMain\r\n * @returns {string} EditingPage\r\n */\n\n\n function getEditingPage() {\n var settings = getSettings();\n return settings.EditingPage;\n }\n /**\r\n * Set editing page\r\n * @param {string} value\r\n * @memberof SettingsMain\r\n */\n\n\n function setEditingPage(value) {\n var settings = getSettings();\n settings.EditingPage = value;\n setSettings(settings);\n }\n /**\r\n * Get prefered calendar view style\r\n * @memberof SettingsMain\r\n * @returns {string} viewStyle\r\n */\n\n\n function getCalendarViewStyle() {\n var settings = getSettings();\n var viewStyle = settings.calendarViewStyle;\n return viewStyle;\n }\n /**\r\n * Set prefered calendar view style\r\n * @param {string} value\r\n * @memberof SettingsMain\r\n */\n\n\n function setCalendarViewStyle(value) {\n var settings = getSettings();\n settings.calendarViewStyle = value;\n setSettings(settings);\n }\n /**\r\n * Get selected calendar date\r\n * @memberof SettingsMain\r\n * @returns {string} selectedDate\r\n */\n\n\n function getCalendarSelectedDate() {\n var settings = getSettings();\n var selectedDate = settings.selectedDate;\n return selectedDate;\n }\n /**\r\n * Set selected calendar date\r\n * @param {string} value\r\n * @memberof SettingsMain\r\n */\n\n\n function setCalendarSelectedDate(value) {\n var settings = getSettings();\n settings.selectedDate = value;\n setSettings(settings);\n }\n\n return service;\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"UpdateService\", UpdateService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name UpdateService\r\n * @description \r\n * Update functionality\r\n * @ngInject\r\n */\n\n function UpdateService(SyncLogFactory) {\n /**\r\n * Version patcher\r\n * @memberof UpdateService\r\n * @returns {string} NeedsSync \r\n */\n function patcher(version) {\n var NeedsSync = false;\n\n if (version == \"1.0\") {\n SyncLogFactory.updateSyncVersion(\"1.1\"); //patching to next version \n // patcher(\"1.1\"); \n\n NeedsSync = true;\n }\n\n return NeedsSync;\n }\n\n return {\n /**\r\n * updates application \r\n * @memberof UpdateService\r\n * @returns {string} NeedsSync \r\n */\n updater: function updater() {\n var synclog = SyncLogFactory.getSyncLog();\n\n if (synclog == undefined || synclog == null) {\n return false;\n } else if (synclog.isUpdated) {\n return true;\n } else {\n var NeedsSync = patcher(synclog.version);\n return NeedsSync;\n }\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"UtilsService\", UtilsService);\n /* @ngInject */\n\n function UtilsService() {\n return {\n /**\r\n * Convert content length to fixed string\r\n * @static\r\n * @param {Number} n - number of byte kibibyte or mibi..., cannot not be NaN, indefinite or negative\r\n * @param {Number} [f=0] - max fraction digits in range of 0..20\r\n * @param {Number} [e=0] - exponent based 1024, Math.pow(1024,e) stands for the unit of n\r\n * @return {String}\r\n * @throws {RangeError}\r\n */\n toSizeString: function toSizeString(n, f, e) {\n n = parseFloat(n);\n f >>>= 0;\n e >>>= 0;\n\n if (n !== n || 1 / n < 0 || 1 / n === -1 / n || f < 0 || f > 20 || e < 0) {\n throw new RangeError(\"One of the three argument (number, fraction, exponent) is out of range\");\n }\n\n var kibi = 1024,\n mibi = 1048576,\n gibi = 1073741824,\n tebi = 1099511627776;\n var v, u;\n n *= Math.pow(1024, e);\n\n if (n < kibi) {\n v = n.toFixed(0);\n u = \"B\";\n } else if (n < mibi) {\n v = (n / kibi).toFixed(f);\n u = \"KB\";\n } else if (n < gibi) {\n v = (n / mibi).toFixed(f);\n u = \"MB\";\n } else if (n < tebi) {\n v = (n / gibi).toFixed(f);\n u = \"GB\";\n } else {\n v = (n / tebi).toFixed(f);\n u = \"TB\";\n }\n\n return v + \"\" + u;\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('AutolandFactory', AutolandFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AutolandFactory\r\n * @description \r\n * Get and Update Crew Meals \r\n * @ngInject\r\n */\n\n function AutolandFactory(GenericService, autolandSupportingAcTypes) {\n /**\r\n * Initialize the Autoland\r\n * @memberof AutolandFactory\r\n */\n function Autoland() {\n this.autolandCount = null;\n this.flightsLeft = 0;\n this.totalAEFlights = 0;\n this.showAutolandModal = false;\n }\n\n var objType = 'autoland';\n var objCallback = Autoland;\n var service = {\n getAutolandFromStorage: getAutolandFromStorage,\n setAutolandToStorage: setAutolandToStorage,\n showAutolandModal: showAutolandModal,\n canShowAutolandModal: canShowAutolandModal\n };\n /**\r\n * Get Autoland object from storage\r\n * @memberof AutolandFactory\r\n */\n\n function getAutolandFromStorage() {\n return GenericService.getOne(objType, objCallback);\n }\n /**\r\n * Save autolandRelated Data to storage\r\n * @memberof AutolandFactory\r\n * @param {number} AutolandOperations the number of autoland operations of current month\r\n * @param {object} flights the flight object of sync response\r\n */\n\n\n function setAutolandToStorage(AutolandOperations, flights) {\n var flightsLeft = 0;\n var totalAegeanFlights = 0;\n\n if (flights.length > 0) {\n var aegeanFlights = getAEFlightsForCurrentMonth(flights);\n flightsLeft = getFlightsLeftForCurrentMonth(aegeanFlights);\n totalAegeanFlights = aegeanFlights.length;\n }\n\n var autoland = {\n autolandCount: AutolandOperations,\n totalAEFlights: totalAegeanFlights,\n flightsLeft: flightsLeft,\n showAutolandModal: true\n };\n GenericService.saveOne(autoland, objType, objCallback);\n }\n /**\r\n * Update autoland object to storage\r\n * @memberof AutolandFactory\r\n * @param {bool} canShowModal whether the modal can be display\r\n */\n\n\n function showAutolandModal(canShowModal) {\n var autoland = GenericService.getOne(objType, objCallback);\n autoland.showAutolandModal = canShowModal;\n GenericService.saveOne(autoland, objType, objCallback);\n }\n /**\r\n * Gets the value of showAutolandModal property\r\n * @memberof AutolandFactory\r\n * @returns {bool} returns the value of showAutolandModal property\r\n */\n\n\n function canShowAutolandModal() {\n var autoland = GenericService.getOne(objType, objCallback);\n return autoland && autoland.showAutolandModal;\n }\n /**\r\n * Get the count of fligths after the current time\r\n * @memberof AutolandFactory\r\n * @param {object} flights the flight object of sync response\r\n * @returns {number} returns the count of fligths after the current time\r\n */\n\n\n function getFlightsLeftForCurrentMonth(flights) {\n var flightDates = flights.map(function (a) {\n return a.ScheduledArrival;\n });\n var date = new Date(); //uncomment for testig purposes\n //var date = new Date(2016, 1, 8);\n\n var filteredDays = flightDates.filter(function (x) {\n return moment.utc(x) >= moment.utc(date);\n });\n return filteredDays.length;\n }\n /**\r\n * Get Aegean Flights For Current Month\r\n * @memberof AutolandFactory\r\n * @param {object} flights the flight object of sync response\r\n * @returns {Array} returns array of fligths that the user is not DHC the flight is for aegean and the userposition is CP\r\n */\n\n\n function getAEFlightsForCurrentMonth(flights) {\n var date = new Date();\n var firstDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1);\n var lastDayOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0); //Uncomment for testing purposes\n // var firstDayOfMonth = new Date(2016, 1, 1);\n // var lastDayOfMonth = new Date(2016, 1, 30);\n\n return flights.filter(function (x) {\n return x.Position == \"CP\" && x.IsDHC == false && autolandSupportingAcTypes.includes(x.AcType) && moment.utc(x.DutyDate) >= moment.utc(firstDayOfMonth) && moment.utc(x.DutyDate) <= moment.utc(lastDayOfMonth);\n });\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('calendarNotifications', calendarNotifications);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name calendarNotifications\r\n * @restrict E\r\n * @description\r\n * Implementation of crew meals\r\n *\r\n * Display the notifications\r\n * @attr {String} draftReport \r\n * @attr {String} completedReports \r\n * @example\r\n * Usage:\r\n * \r\n * \r\n * @ngInject\r\n */\n\n function calendarNotifications($location, MessageFactory, MemoFactory, AutolandFactory, ScheduleAcknowledgeFactory, LeaveRequestFactory, $uibModal, CheckInFactory, GroundDutyFactory, $route) {\n function link($scope, attrs) {\n $scope.gotoUnreadMemos = gotoUnreadMemos;\n $scope.gotoMessages = gotoMessages;\n $scope.gotoLeaves = gotoLeaves;\n $scope.reportsCounter = getReportsCounter();\n $scope.acknowledge = acknowledge;\n $scope.showPanel = false;\n $scope.showAutolandReminder = false;\n $scope.showScheduleChangesReminder = false;\n $scope.hasScheduleChanges = false;\n $scope.openCheckIn = openCheckInModal;\n $scope.showCheckInAction = false;\n $scope.hasManualEntry = false;\n $scope.gotoGroundDutyInfo = gotoGroundDutyInfo;\n $scope.removeManualEntry = removeManualEntry;\n setupView();\n\n function setupView() {\n $scope.number_of_messages = MessageFactory.getMessagesFromStorage().length;\n $scope.number_of_messages_not_readen = MessageFactory.getCountOfUnreadMessages();\n $scope.leaveRequest = LeaveRequestFactory.getLeaveRequestInformation();\n $scope.leaveRequestCloseDate = $scope.leaveRequest ? moment($scope.leaveRequest.CloseDate).format('Do of MMMM') : null; //Get count of unread memos but remove the ones that belong in 'Training Surveys' Category\n\n var unreadMemosCount = 0;\n MemoFactory.getUnreadMemos(function (memos) {\n //remove memos that belong in \"Training Surveys\" category\n for (var i = 0; i < memos.length; i++) {\n if (memos[i].Category != \"Training Surveys\") {\n unreadMemosCount++;\n }\n }\n\n $scope.unreadMemosCount = unreadMemosCount;\n $scope.hasScheduleChanges = ScheduleAcknowledgeFactory.hasScheduleChanges();\n $scope.showCheckInAction = showCheckInAction();\n prepareAutolandData();\n $scope.showPanel = showNotificationPanel();\n $scope.showScheduleChangesReminder = showScheduleChangesReminder();\n showReminderModal();\n }); // Used for pending trainings notification \n\n $scope.manualGroundDuties = GroundDutyFactory.getManualGroundDutiesFromStorage();\n findManualEntries($scope.manualGroundDuties);\n }\n\n function prepareAutolandData() {\n //Get autoland procedures\n var autoland = AutolandFactory.getAutolandFromStorage();\n $scope.autolandCount = 0;\n $scope.flightsLeft = 0;\n $scope.hasAEFlights = false;\n var totalAEFlights = 0;\n\n if (autoland != null) {\n $scope.autolandCount = autoland.autolandCount;\n $scope.flightsLeft = autoland.flightsLeft;\n totalAEFlights = autoland.totalAEFlights;\n $scope.hasAEFlights = autoland.totalAEFlights > 0;\n }\n\n if (AutolandFactory.canShowAutolandModal() && $scope.autolandCount == 0 && $scope.hasAEFlights && totalAEFlights > 4 && $scope.flightsLeft > 0 && $scope.flightsLeft < 10) {\n $scope.showAutolandReminder = true;\n } else {\n $scope.showAutolandReminder = false;\n }\n }\n\n function showScheduleChangesReminder() {\n return ScheduleAcknowledgeFactory.showScheduleChangesModal();\n }\n\n function showCheckInAction() {\n var retVal = false;\n var checkInInfo = CheckInFactory.getCheckInInfoFromStorage();\n\n if (checkInInfo && checkInInfo.AimsId > 0) {\n var now = moment.utc(); //Fetch FROM\n //Convert from Date UTC to Moment UTC\n\n var std = moment.utc(checkInInfo.STD);\n var minFetchTime = moment(std).add(-2, 'hours'); //Fetch UNTIL \n\n var maxFetchTime = moment(std).add(10, 'minutes');\n var isAfter = now.isAfter(minFetchTime);\n var isBefore = now.isBefore(maxFetchTime);\n\n if (isAfter && isBefore) {\n retVal = true;\n } //console.log({\"isAfter\":isAfter, \"isBefore\": isBefore, \"now\":now, \"std\":std, \"minFetchTime\":minFetchTime,\"maxFetchTime\":maxFetchTime});\n\n }\n\n return retVal;\n }\n\n function showNotificationPanel() {\n var showPanel = false;\n\n if ($scope.draftReports + $scope.completedReports > 9 || !$scope.$root.idbSupported || $scope.unreadMemosCount > 0 || $scope.number_of_messages_not_readen > 0 || $scope.hasAEFlights || $scope.leaveRequest && $scope.leaveRequest.GroupStatus == 'OPEN' || $scope.hasScheduleChanges || $scope.showCheckInAction) {\n showPanel = true;\n }\n\n return showPanel;\n }\n /**\r\n * Finds the dates with manual pending training entries on their schedule\r\n * @memberof CalendarCtrl \r\n */\n\n\n function findManualEntries(manualDuties) {\n for (var i = 0; i < manualDuties.length; i++) {\n if (manualDuties[i].hasPendingCourse) {\n $scope.hasManualEntry = true;\n break;\n }\n }\n }\n\n function getReportsCounter() {\n return parseInt($scope.draftReports) + parseInt($scope.completedReports);\n }\n /**\r\n * Redirect to Library Info with filter enabled\r\n * @memberof calendarNotifications\r\n */\n\n\n function gotoUnreadMemos() {\n $location.path('/memos/unread');\n }\n /**\r\n * Redirect to messages\r\n * @memberof calendarNotifications\r\n */\n\n\n function gotoMessages() {\n $location.path('/messages/');\n }\n /**\r\n * Redirect to leaves\r\n * @memberof CalendarCtrl\r\n */\n\n\n function gotoLeaves() {\n $location.path('/leaverequest/');\n }\n /**\r\n * Redirect to groundDuty Info\r\n * @memberof CalendarCtrl\r\n */\n\n\n function gotoGroundDutyInfo(GroundDutyId) {\n $location.path('/groundDuty/' + GroundDutyId);\n }\n /** Removes manual training entry */\n\n\n function removeManualEntry(groundDuty) {\n GroundDutyFactory.removeGroundDuty(groundDuty);\n $route.reload();\n }\n /**\r\n * Shows the bootbox for autoland and schedule acknowledge reminder\r\n * @memberof calendarNotifications\r\n */\n\n\n function showReminderModal() {\n if ($scope.showAutolandReminder || $scope.showScheduleChangesReminder) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/CalendarNotifications/dlgReminderModal.html',\n controller: 'ReminderModalCtrl',\n size: 'md',\n backdrop: 'static',\n keyboard: false,\n resolve: {\n showAutolandReminder: function showAutolandReminder() {\n return $scope.showAutolandReminder;\n },\n showScheduleChangesReminder: function showScheduleChangesReminder() {\n return $scope.showScheduleChangesReminder;\n }\n }\n }); // bootbox.dialog({\n // message: `
Autoland for this Month is pending.
`,\n // title: \"Autoland Reminder\",\n // buttons: {\n // confirm: {\n // label: ' I understand',\n // className: \"btn-success\",\n // callback: function () { \n // AutolandFactory.showAutolandModal(false);\n // }\n // }\n // }\n // })\n }\n }\n /**\r\n * Open the \"Acknowledge schedule changes\" Modal\r\n * @memberof CalendarCtrl\r\n */\n\n\n function acknowledge() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/CalendarNotifications/dlgAcknowledgeChanges.html',\n controller: 'AcknowledgeModalCtrl',\n size: 'lg',\n backdrop: 'static',\n keyboard: false\n });\n }\n /**\r\n * Open Check in Modal\r\n * @memberof CalendarCtrl\r\n */\n\n\n function openCheckInModal() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgCheckIn.html',\n controller: 'CheckInModalCtrl',\n size: 'lg',\n backdrop: 'static',\n keyboard: false\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/CalendarNotifications/calendarNotifications.tpl.html',\n scope: {\n draftReports: '@',\n completedReports: '@',\n hasUnsetTraining: '@'\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ReminderModalCtrl', ReminderModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ReminderModalCtrl\r\n * @description \r\n * Warning Modal about autoland and acknowledge schedule changes\r\n * @ngInject\r\n */\n\n function ReminderModalCtrl(showAutolandReminder, showScheduleChangesReminder, AutolandFactory, ScheduleAcknowledgeFactory, $scope, $uibModalInstance) {\n $scope.cancel = cancel; //from parent view:\n\n $scope.showAutolandReminder = showAutolandReminder;\n $scope.showScheduleChangesReminder = showScheduleChangesReminder;\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\n\n function cancel() {\n if ($scope.showAutolandReminder) {\n AutolandFactory.showAutolandModal(false);\n }\n\n if ($scope.showScheduleChangesReminder) {\n ScheduleAcknowledgeFactory.updateShowScheduleChangesModal(false);\n }\n\n $uibModalInstance.close('cancel');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('CheckInFactory', CheckInFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CheckInFactory\r\n * @description \r\n * Get list, Update list & Acknowledge schedule changes\r\n * @ngInject\r\n */\n\n function CheckInFactory(GenericService, $http, apiUrl) {\n /**\r\n * Initialize the ScheduleChanges\r\n * @memberof CheckInFactory\r\n */\n function CheckIn() {}\n\n var objType = 'CheckIn';\n var objCallback = CheckIn;\n var response = {\n success: false,\n message: '',\n checkInInfo: null\n };\n var service = {\n setCheckInInfoToStorage: setCheckInInfoToStorage,\n getCheckInInfoFromStorage: getCheckInInfoFromStorage,\n checkIn: checkIn,\n saveCheckInDelay: saveCheckInDelay\n };\n /**\r\n * Save check in info\r\n * @param {array} checkInInfo \r\n */\n\n function setCheckInInfoToStorage(checkInInfo) {\n if (checkInInfo == undefined || checkInInfo == null) {\n GenericService.removeAll(objType);\n } else {\n GenericService.saveOne(checkInInfo, objType, objCallback);\n }\n }\n /**\r\n * Get check in info\r\n */\n\n\n function getCheckInInfoFromStorage() {\n return GenericService.getOne(objType, objCallback);\n ;\n }\n /**\r\n * Check In\r\n * @returns {promise} response\r\n */\n\n\n function checkIn(confirmed) {\n return $http.get(apiUrl + '/CrewCheckIn/CheckIn?confirmed=' + confirmed, {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return updateCheckInCallBack(res);\n })[\"catch\"](function (res) {\n return checkInFailedCallBack(res);\n });\n }\n /**\r\n * Update Schedule changes dates\r\n * @param {object} res \r\n * @param {object} objectToAdd \r\n * @returns {object} response\r\n */\n\n\n function updateCheckInCallBack(res) {\n response.success = res.data.success;\n\n if (res.data.success) {\n //update local storage\n setCheckInInfoToStorage(res.data.data);\n response.checkInInfo = res.data.data;\n\n if (response.checkInInfo && response.checkInInfo.Confirmed && response.checkInInfo.ErrorExplanation === \"\") {\n response.message = \"Success! Check In Confirmed.\";\n } else if (response.checkInInfo && !response.checkInInfo.Confirmed && response.checkInInfo.ErrorExplanation === \"\") {\n response.message = \"Ready for Check In.\";\n } else if (response.checkInInfo) {\n response.message = response.checkInInfo.ErrorExplanation;\n } else {\n response.message = \"You have not pending Check In.\";\n }\n } else {\n response.message = res.data.errorMessage;\n }\n\n return response;\n }\n /**\r\n * The callback function upon failure on submit\r\n * @returns {object} response\r\n */\n\n\n function checkInFailedCallBack(res) {\n response.success = false;\n response.message = \"Oops! Something went wrong\"; //TODO::Check status=500 error: returns res = {data: {…}, status: 500, config: {…}, statusText: \"Internal Server Error\", headers: ƒ}\n // res.data.data is null\n\n if (res.data.data) {\n response.checkInInfo = res.data.data;\n } else {\n //log results\n console.log(res);\n }\n\n return response;\n }\n /**\r\n * Save Check In Delay\r\n * @returns {promise} response\r\n */\n\n\n function saveCheckInDelay(delayMinutes) {\n var checkInInfo = getCheckInInfoFromStorage();\n checkInInfo.DelayMinutes = +delayMinutes;\n return $http.post(apiUrl + '/CrewCheckIn/SaveCheckInDelay', checkInInfo, {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return updateCheckInDelayCallBack(res);\n })[\"catch\"](function (res) {\n return checkInFailedCallBack(res);\n });\n }\n\n function updateCheckInDelayCallBack(res) {\n response.success = res.data.success;\n\n if (res.data.success) {\n response.message = \"Success! Delay message was sent.\";\n } else {\n response.message = res.data.errorMessage;\n }\n\n return response;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CheckInModalCtrl', CheckInModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CheckInModalCtrl\r\n * @description \r\n * Check in Modal\r\n * @ngInject\r\n */\n\n function CheckInModalCtrl($scope, CheckInFactory, $route, $uibModalInstance) {\n $scope.showContent = 'actions';\n $scope.cancel = cancel;\n $scope.checkInInfo = null;\n $scope.CheckInAction = CheckInAction;\n $scope.BackToActions = BackToActions;\n $scope.ConfirmCheckIn = ConfirmCheckIn;\n $scope.SendDelayMessage = SendDelayMessage;\n $scope.GetCheckInInfoFromServer = GetCheckInInfoFromServer;\n $scope.responseObj = {\n success: false,\n message: '',\n checkInInfo: null\n };\n $scope.results = [];\n $scope.selectedDelayMinutes = 10;\n $scope.onMinutesChange = onMinutesChange;\n $scope.numberDown = numberDown;\n $scope.numberUp = numberUp;\n GetCheckInInfoFromServer();\n\n function GetCheckInInfoFromServer() {\n $scope.showContent = 'loading';\n var confirmCheckIn = false;\n CheckInFactory.checkIn(confirmCheckIn).then(function (res) {\n return handleRefreshResponse(res);\n })[\"catch\"](function (res) {\n return handleRefreshResponse(res);\n });\n }\n\n function handleRefreshResponse(res) {\n $scope.showContent = 'actions';\n $scope.responseObj = res;\n }\n\n function CheckInAction() {\n $scope.showContent = 'confirm';\n }\n\n function BackToActions() {\n $scope.showContent = 'actions';\n }\n\n function ConfirmCheckIn() {\n $scope.showContent = 'loading';\n var confirmCheckIn = true;\n CheckInFactory.checkIn(confirmCheckIn).then(function (res) {\n return handleSubmitResponse(res);\n })[\"catch\"](function (res) {\n return handleSubmitResponse(res);\n });\n }\n\n function handleSubmitResponse(res) {\n $scope.showContent = 'results';\n $scope.responseObj = res;\n }\n\n function onMinutesChange(minutes) {\n $scope.selectedDelayMinutes = minutes;\n }\n\n function SendDelayMessage() {\n $scope.showContent = 'loading';\n CheckInFactory.saveCheckInDelay($scope.selectedDelayMinutes).then(function (res) {\n return handleDelayMessageResponse(res);\n })[\"catch\"](function (res) {\n return handleDelayMessageResponse(res);\n });\n }\n\n function handleDelayMessageResponse(res) {\n $scope.showContent = 'results';\n $scope.responseObj.success = res.success;\n $scope.responseObj.message = res.message;\n }\n /**\r\n * Decrease field value by 5\r\n */\n\n\n function numberDown(selectedDelayMinutes) {\n if (selectedDelayMinutes > 0) {\n $scope.selectedDelayMinutes = selectedDelayMinutes - 5;\n }\n }\n /**\r\n * Increase field value by 5\r\n */\n\n\n function numberUp(selectedDelayMinutes) {\n $scope.selectedDelayMinutes = selectedDelayMinutes + 5;\n }\n /**\r\n * Closes modal\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('cancel'); // if($scope.responseObj.success){\n // $route.reload();\n // }\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CrewCallCtrl', CrewCallCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CrewCallCtrl\r\n * @description \r\n * View confirmation warning when clicking on a crew member's telephone - Monitor call requests\r\n * @ngInject\r\n */\n\n function CrewCallCtrl($scope, $uibModalInstance, crew, flightId, CrewCallFactory, UserFactory, LogCallFactory) {\n $scope.close = close;\n $scope.call = call;\n $scope.beforeCall = true;\n $scope.crew = crew;\n /**\r\n * Close the modal\r\n */\n\n function close() {\n $uibModalInstance.close(false);\n }\n /**\r\n * Confirm Call\r\n * @param {number} crewId Requested user \r\n */\n\n\n function call(crewId) {\n $scope.beforeCall = false;\n var user = UserFactory.getUser();\n var logData = {\n Requester: user.id,\n Requestee: crewId,\n FlightId: flightId,\n Date: moment.utc()\n };\n\n if ($scope.isOffline) {\n //Offline: save audit to local storage, send later on sync\n LogCallFactory.saveLogCall(logData);\n } else {\n //Online : API call to save audit right now\n CrewCallFactory.LogCall(logData, function (responseData) {});\n }\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('CrewCallFactory', CrewCallFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewCallFactory\r\n * @ngInject\r\n */\n\n function CrewCallFactory(GenericService, $http, apiUrl) {\n function CrewCall() {\n this.FlightId = null;\n this.CrewId = null;\n this.phoneNumber = null;\n }\n\n var objType = 'crewCall';\n var objCallback = CrewCall;\n var service = {\n getCrewCallsFromStorage: getCrewCallsFromStorage,\n setCrewCallsToStorage: setCrewCallsToStorage,\n getCrewCallFromStorage: getCrewCallFromStorage,\n getFlightCrewCallsFromStorage: getFlightCrewCallsFromStorage,\n saveCrewCall: saveCrewCall,\n cleanOldData: cleanOldData,\n LogCall: LogCall,\n cleanFlightCrewNumbers: cleanFlightCrewNumbers,\n saveFlightPhoneNumbers: saveFlightPhoneNumbers\n };\n /**\r\n * Get Crew Phone Numbers.\r\n * @memberof CrewCallFactory\r\n * @returns {Array} CrewPhoneNumbers \r\n */\n\n function getCrewCallsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Get Crew Phone Numbers for specified flight\r\n * @memberof CrewCallFactory\r\n * @param {number} flightId\r\n * @returns {Array} CrewPhoneNumbers \r\n */\n\n\n function getFlightCrewCallsFromStorage(flightId) {\n var phoneNumbers = GenericService.list(objType, objCallback);\n return phoneNumbers.filter(function (x) {\n return x.FlightId == flightId;\n });\n }\n /**\r\n * Save Crew Phone Numbers to storage\r\n * @memberof CrewCallFactory\r\n * @param {Array} CrewPhoneNumbers\r\n */\n\n\n function setCrewCallsToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Get Crew Phone Number from storage \r\n * @memberof CrewCallFactory\r\n * @param {number} crewId\r\n * @param {number} flightId\r\n * @return {object} crew phone number\r\n */\n\n\n function getCrewCallFromStorage(crewId, flightId) {\n var phoneNumbers = getCrewCallsFromStorage();\n return phoneNumbers.find(function (x) {\n return x.FlightId == flightId && x.CrewId == crewId;\n });\n }\n /**\r\n * Save a fetched crew phone number\r\n * @memberof CrewCallFactory\r\n * @param {object} crewCall \r\n */\n\n\n function saveCrewCall(crewCall) {\n GenericService.add(crewCall, objType, objCallback);\n }\n /**\r\n * Clean ls from old flight phone numbers\r\n * @param {array} flights Synced flights\r\n */\n\n\n function cleanOldData(flights) {\n var flightIds = flights.map(function (x) {\n return x.FlightId;\n });\n var phoneNumbers = getCrewCallsFromStorage(); //Filter out phone numbers of old flights\n\n phoneNumbers = phoneNumbers.filter(function (x) {\n return flightIds.includes(x.FlightId);\n });\n var now = moment.utc();\n var keepingPhoneNumbers = [];\n phoneNumbers.forEach(function (item) {\n //Fetch FROM\n //Convert from Date UTC to Moment UTC\n var dateSTD = new Date(item.STD).fromUTC();\n var std = moment(dateSTD).utc();\n var minFetchTime = moment(std).add(-24, 'hours'); //Fetch UNTIL\n //Convert from Date UTC to Moment UTC\n\n var dateSTA = new Date(item.STA).fromUTC();\n var sta = moment(dateSTA).utc();\n var maxFetchTime = moment(sta).add(2, 'hours');\n var isAfter = now.isAfter(minFetchTime);\n var isBefore = now.isBefore(maxFetchTime);\n\n if (isAfter && isBefore) {\n keepingPhoneNumbers.push(item);\n }\n });\n setCrewCallsToStorage(keepingPhoneNumbers);\n }\n /**\r\n * Log call request\r\n * @param {string} logData Requester, Requestee, FlightId\r\n * @param {function} callback \r\n * @param {function} errorCallback \r\n */\n\n\n function LogCall(logData, callback, errorCallback) {\n return $http.post(apiUrl + '/Info/LogCrewMemberCall', logData, {\n 'Content-Type': 'application/json'\n }).then(callback)[\"catch\"](errorCallback);\n }\n /**\r\n * Clean all stored phone numbers for selected flight\r\n * @param {number} flightId \r\n */\n\n\n function cleanFlightCrewNumbers(flightId) {\n var phoneNumbers = getCrewCallsFromStorage();\n phoneNumbers = phoneNumbers.filter(function (x) {\n return x.FlightId != flightId;\n });\n setCrewCallsToStorage(phoneNumbers);\n }\n /**\r\n * Save any found crew phone numbers for specified flight\r\n * @param {number} flightId \r\n * @param {array} crew \r\n * @param {datetime} sta \r\n * @param {datetime} std \r\n */\n\n\n function saveFlightPhoneNumbers(flightId, crew, sta, std) {\n crew.forEach(function (user) {\n if (user.PhoneNumber) {\n var crewPhone = {\n FlightId: flightId,\n CrewId: user.id,\n PhoneNumber: user.PhoneNumber,\n STA: sta,\n //sta & std values will be used during sync to check timerange eligibility (-24h sta / +2h std)\n STD: std\n };\n saveCrewCall(crewPhone);\n }\n });\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('FlightCheckInsFactory', FlightCheckInsFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightCheckInsFactory\r\n * @ngInject\r\n */\n\n function FlightCheckInsFactory(GenericService) {\n function FlightCheckIn() {\n this.FlightId = null;\n this.CrewId = null;\n this.CheckIn - null;\n this.WillBeThereAt = null;\n }\n\n var objType = 'flightCheckIns';\n var objCallback = FlightCheckIn;\n var service = {\n updateFlightCrewCheckInToStorage: updateFlightCrewCheckInToStorage,\n getFlightCrewCheckInFromStorage: getFlightCrewCheckInFromStorage,\n cleanOldData: cleanOldData\n };\n /**\r\n * Get Crew Check-Ins.\r\n * @memberof CrewCallFactory\r\n * @returns {Array} CrewPhoneNumbers \r\n */\n\n function getCrewCheckInFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save crew checkIns to storage\r\n * @memberof CrewCallFactory\r\n * @param {Array} CrewPhoneNumbers\r\n */\n\n\n function setCrewCheckInToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Update Crew CheckIns for specified flight\r\n * @memberof CrewCallFactory\r\n * @param {} flight duty\r\n * @returns {Array} CrewFlightCrewCheckIns \r\n */\n\n\n function updateFlightCrewCheckInToStorage(duty) {\n //Get all checkIns exept current flight from storage\n var storedCheckIns = getCrewCheckInFromStorage();\n var storedCheckInsFiltered = storedCheckIns.filter(function (f) {\n return f.FlightId != duty.FlightId;\n }); //Get checkIns from duty and add new crew checkIns to list\n\n if (duty && duty.FlightInfo && duty.FlightInfo.crew) {\n duty.FlightInfo.crew.forEach(function (item) {\n storedCheckInsFiltered.push({\n \"FlightId\": duty.FlightId,\n \"CrewId\": item.id,\n \"CheckIn\": item.CheckIn,\n \"WillBeThereAt\": item.WillBeThereAt\n });\n }); //save checkIns\n\n setCrewCheckInToStorage(storedCheckInsFiltered);\n }\n }\n /**\r\n * Get Crew CheckIns for specified flight\r\n * @memberof CrewCallFactory\r\n * @param {number} flightId\r\n * @returns {Array} CrewFlightCrewCheckIns \r\n */\n\n\n function getFlightCrewCheckInFromStorage(flightId) {\n var storedCheckIns = getCrewCheckInFromStorage();\n return storedCheckIns.filter(function (x) {\n return x.FlightId == flightId;\n });\n }\n /**\r\n * Clean ls from old flights crew check-ins\r\n * @param {array} flights Synced flights\r\n */\n\n\n function cleanOldData(flights) {\n var flightIds = flights.map(function (x) {\n return x.FlightId;\n });\n var previousCheckIns = getCrewCheckInFromStorage(); //Filter out crew check-ins of old flights\n\n previousCheckIns = previousCheckIns.filter(function (x) {\n return flightIds.includes(x.FlightId);\n });\n setCrewCheckInToStorage(previousCheckIns);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('crewInfo', crewInfo);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name crewInfo\r\n * @restrict E\r\n * @description\r\n * Crew Table with a double row per crew member\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function crewInfo($uibModal, UserFactory) {\n function link(scope, element, attrs) {\n scope.user = UserFactory.getUser();\n scope.openPhoneConfirmation = openPhoneConfirmation;\n scope.showInfoRow = showInfoRow;\n\n if (scope.type == \"flight\") {\n scope.crewMembers = scope.crew.filter(function (x) {\n return (x.position == 'CP' || x.position == \"FO\") && !x.isDHC;\n });\n } else if (scope.type == \"cabin\") {\n scope.crewMembers = scope.crew.filter(function (x) {\n return (x.position == 'SA' || x.position == \"FA\") && !x.isDHC;\n });\n } else {\n scope.crewMembers = scope.crew.filter(function (x) {\n return x.isDHC;\n });\n }\n\n function openPhoneConfirmation(_crew) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/CrewInfo/dlgConfirmCrewCall.html',\n controller: 'CrewCallCtrl',\n size: 'md',\n resolve: {\n crew: function crew() {\n return _crew;\n },\n flightId: function flightId() {\n return scope.flightId;\n }\n }\n });\n modalInstance.result.then(function (confirm) {});\n }\n\n function showInfoRow(item) {\n var differentUser = scope.user.aimsId != item.aimsId;\n var phoneAvailable = item.PhoneNumber && item.PhoneNumber != '';\n var previousDutyAvailable = item.PreviousDuty && item.PreviousDuty.isDifferent;\n var phonesAvailable = scope.crew.filter(function (x) {\n return x.PhoneNumber && x.PhoneNumber != '';\n }).length > 0;\n var checkInStatusAvailable = scope.crew.filter(function (x) {\n return x.CheckIn || x.WillBeThereAt;\n }).length > 0;\n return differentUser && (phoneAvailable || previousDutyAvailable || phonesAvailable || checkInStatusAvailable);\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/CrewInfo/crewInfo.tpl.html',\n scope: {\n crew: \"=\",\n type: \"=\",\n flightId: \"=\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('crewPreviousInfo', crewPreviousInfo);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name crewPreviousInfo\r\n * @restrict E\r\n * @description\r\n * Crew Table with a double row per crew member showing previous duty info\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function crewPreviousInfo($uibModal, UserFactory) {\n function link(scope, element, attrs) {\n scope.user = UserFactory.getUser();\n scope.filterByPreviousDuty = filterByPreviousDuty;\n\n if (scope.type == \"flight\") {\n scope.crewMembers = scope.crew.filter(function (x) {\n return (x.position == 'CP' || x.position == \"FO\") && !x.isDHC;\n });\n } else if (scope.type == \"cabin\") {\n scope.crewMembers = scope.crew.filter(function (x) {\n return (x.position == 'SA' || x.position == \"FA\") && !x.isDHC;\n });\n } else {\n scope.crewMembers = scope.crew.filter(function (x) {\n return x.isDHC;\n });\n }\n\n function filterByPreviousDuty() {\n return function (crew) {\n return crew.PreviousDuty && crew.PreviousDuty.isDifferent;\n };\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/CrewInfo/crewPreviousInfo.tpl.html',\n scope: {\n crew: \"=\",\n type: \"=\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('LogCallFactory', LogCallFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name LogCallFactory\r\n * @ngInject\r\n */\n\n function LogCallFactory(GenericService, $http, apiUrl) {\n function LogCall() {\n this.Requester = null;\n this.Requestee = null;\n this.FlightId = null;\n this.Date = null;\n }\n\n var objType = 'logCall';\n var objCallback = LogCall;\n var service = {\n getLogCallsFromStorage: getLogCallsFromStorage,\n cleanLogsFromStorage: cleanLogsFromStorage,\n saveLogCall: saveLogCall\n };\n /**\r\n * Get Offline Logged Calls.\r\n * @memberof LogCallFactory\r\n */\n\n function getLogCallsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Clean local storage\r\n * @memberof CrewCallFactory\r\n */\n\n\n function cleanLogsFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Save an offline call request\r\n * @memberof CrewCallFactory\r\n * @param {object} logData \r\n */\n\n\n function saveLogCall(logData) {\n GenericService.add(logData, objType, objCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PreviousDutyFactory', PreviousDutyFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PreviousDutyFactory\r\n * @ngInject\r\n */\n\n function PreviousDutyFactory(GenericService, $http, apiUrl) {\n function PreviousDuty() {\n this.FlightId = null;\n this.CrewId = null;\n this.PreviousDuty = null;\n }\n\n var objType = 'previousDuty';\n var objCallback = PreviousDuty;\n var service = {\n getPreviousDutiesFromStorage: getPreviousDutiesFromStorage,\n setPreviousDutiesToStorage: setPreviousDutiesToStorage,\n getPreviousDutyFromStorage: getPreviousDutyFromStorage,\n getFlightPreviousDutiesFromStorage: getFlightPreviousDutiesFromStorage,\n savePreviousDuty: savePreviousDuty,\n cleanOldData: cleanOldData,\n cleanFlightPreviousDuties: cleanFlightPreviousDuties,\n saveFlightPreviousDuties: saveFlightPreviousDuties\n };\n /**\r\n * Get Crew Phone Numbers.\r\n * @memberof PreviousDutyFactory\r\n * @returns {Array} PreviousDuties \r\n */\n\n function getPreviousDutiesFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Get Crew Phone Numbers for specified flight\r\n * @memberof PreviousDutyFactory\r\n * @param {number} flightId\r\n * @returns {Array} PreviousDuties \r\n */\n\n\n function getFlightPreviousDutiesFromStorage(flightId) {\n var previousDuties = GenericService.list(objType, objCallback);\n return previousDuties.filter(function (x) {\n return x.FlightId == flightId;\n });\n }\n /**\r\n * Save Crew Phone Numbers to storage\r\n * @memberof PreviousDutyFactory\r\n * @param {Array} PreviousDuties\r\n */\n\n\n function setPreviousDutiesToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Get Previous Duty from storage \r\n * @memberof PreviousDutyFactory\r\n * @param {number} crewId\r\n * @param {number} flightId\r\n * @return {object} previous duty info\r\n */\n\n\n function getPreviousDutyFromStorage(crewId, flightId) {\n var previousDuties = getPreviousDutiesFromStorage();\n return previousDuties.find(function (x) {\n return x.FlightId == flightId && x.CrewId == crewId;\n });\n }\n /**\r\n * Save a fetched previous duty\r\n * @memberof PreviousDutyFactory\r\n * @param {object} previousDuty \r\n */\n\n\n function savePreviousDuty(previousDuty) {\n GenericService.add(previousDuty, objType, objCallback);\n }\n /**\r\n * Clean ls from old flight previous duties\r\n * @param {array} flights Synced flights\r\n */\n\n\n function cleanOldData(flights) {\n var flightIds = flights.map(function (x) {\n return x.FlightId;\n });\n var previousDuties = getPreviousDutiesFromStorage(); //Filter out previous duties of old flights\n\n previousDuties = previousDuties.filter(function (x) {\n return flightIds.includes(x.FlightId);\n });\n setPreviousDutiesToStorage(previousDuties);\n }\n /**\r\n * Clean all stored previous duties for selected flight\r\n * @param {number} flightId \r\n */\n\n\n function cleanFlightPreviousDuties(flightId) {\n var previousDuties = getPreviousDutiesFromStorage();\n previousDuties = previousDuties.filter(function (x) {\n return x.FlightId != flightId;\n });\n setPreviousDutiesToStorage(previousDuties);\n }\n /**\r\n * Save previous duty info for each flight crew member that has one \r\n * @param {number} flightId \r\n * @param {array} crew \r\n */\n\n\n function saveFlightPreviousDuties(flightId, crew) {\n crew.forEach(function (user) {\n if (user.PreviousDuty) {\n var previousDuty = {\n FlightId: flightId,\n CrewId: user.id,\n PreviousDuty: user.PreviousDuty\n };\n savePreviousDuty(previousDuty);\n }\n });\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('CrewHotelFactory', CrewHotelFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewHotelFactory\r\n * @description \r\n * Get hotels\r\n * @ngInject\r\n */\n\n function CrewHotelFactory(GenericService, showHotelsAcTypes) {\n var objType = 'crewHotel';\n var objCallback = CrewHotel;\n var service = {\n getCrewHotelsFromStorage: getCrewHotelsFromStorage,\n setCrewHotelsToStorage: setCrewHotelsToStorage,\n showHotelsInCalendar: showHotelsInCalendar\n };\n /**\r\n * Initialize the CrewHotel\r\n * @memberof CrewHotelFactory\r\n */\n\n function CrewHotel() {\n this.AimsId = null;\n this.CrewName = null;\n this.DutyDate = null;\n this.Base = null;\n this.Airport = null;\n this.HotelNo = null;\n this.HotelName = null;\n this.GroundTime = null;\n }\n /**\r\n * Get Crew Hotels\r\n * @memberof CrewHotelFactory\r\n * @returns {Array} CrewHotels \r\n */\n\n\n function getCrewHotelsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save Crew Hotels to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} objList A list of Crew Hotels\r\n */\n\n\n function setCrewHotelsToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Get flights for a specific duty date. Show hotels check depend on ac types\r\n * @memberof AutolandFactory\r\n * @param {object} flights the flight object of sync response\r\n * @returns {bool} showHotelsInCalendar\r\n */\n\n\n function showHotelsInCalendar(flights) {\n var oaFlights = flights.filter(function (x) {\n return x.IsDHC == false && showHotelsAcTypes.includes(x.AcType);\n });\n return oaFlights.length > 0;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('CrewMealFactory', CrewMealFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewMealFactory\r\n * @description \r\n * Get and Update Crew Meals \r\n * @ngInject\r\n */\n\n function CrewMealFactory(GenericService, $http, apiUrl) {\n var objType = 'crewMeal';\n var objCallback = CrewMeal;\n var objCallbackRatings = RatingObj;\n var ratingSubmitResponseObj = {\n success: false,\n message: ''\n };\n var service = {\n getCrewMealsFromStorage: getCrewMealsFromStorage,\n setCrewMealsToStorage: setCrewMealsToStorage,\n getCrewMealFromStorage: getCrewMealFromStorage,\n sendCrewMealsRatingReport: sendCrewMealsRatingReport,\n hasRating: hasRating,\n getCrewMealsDidNotEatReasons: getCrewMealsDidNotEatReasons\n };\n /**\r\n * Initialize the CrewMeal\r\n * @memberof CrewMealFactory\r\n */\n\n function CrewMeal() {\n this.CateringMealId = null;\n this.Title = null;\n this.Description = null;\n }\n\n function RatingObj() {\n this.CrewMealId = null, this.TimeStamp = null;\n }\n /**\r\n * Get Crew Meals\r\n * @memberof CrewMealFactory\r\n * @returns {Array} CrewMeals \r\n */\n\n\n function getCrewMealsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save Crew Meals to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} objList A list of Crew Meals\r\n */\n\n\n function setCrewMealsToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Get a specific Crew Meal\r\n * @memberof CrewMealFactory\r\n * @returns {object} CrewMeal\r\n */\n\n\n function getCrewMealFromStorage(cateringMealId) {\n var crewMeals = getCrewMealsFromStorage();\n if (crewMeals == null) return [];\n var arrayLength = crewMeals.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (crewMeals[i].CateringMealId == cateringMealId) {\n return crewMeals[i];\n }\n }\n }\n /**\r\n * Checks if the specified crew meal has rating\r\n * @memberof CrewMealFactory\r\n * @returns {boolean} response\r\n */\n\n\n function hasRating(crewMealId) {\n var res = GenericService.list(\"CrewMealRatings\", objCallbackRatings);\n return res.some(function (e) {\n return e.CrewMealId === crewMealId.toString();\n });\n }\n /**\r\n * Sends the crew meals rating report\r\n * @memberof CrewMealFactory\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\n\n\n function sendCrewMealsRatingReport(ratingForm) {\n var objectToAdd = {\n CrewMealId: ratingForm.CrewMealId,\n TimeStamp: new Date()\n };\n return $http.post(apiUrl + '/CrewMealsRating/SaveReport', ratingForm, {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return saveReportSuccessCallBack(res, objectToAdd);\n })[\"catch\"](function (res) {\n return saveReportFailedCallBack(res);\n });\n }\n /**\r\n * The callback function if the seve report succeed\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\n\n\n function saveReportSuccessCallBack(res, objectToAdd) {\n ratingSubmitResponseObj.success = res.data.success;\n\n if (res.data.success) {\n GenericService.add(objectToAdd, \"CrewMealRatings\", objCallbackRatings);\n ratingSubmitResponseObj.message = \"Thank you for your feedback\";\n } else {\n ratingSubmitResponseObj.message = res.data.errorMessage;\n }\n\n return ratingSubmitResponseObj;\n }\n /**\r\n * Gets the choices for the dropdown if a crew member did not eat their meal\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\n\n\n function getCrewMealsDidNotEatReasons() {\n return $http.get(apiUrl + '/CrewMealsRating/GetCrewMealsDidNotEatReasons', {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return res.data;\n });\n }\n /**\r\n * The callback function if the seve report fail\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\n\n\n function saveReportFailedCallBack(res) {\n ratingSubmitResponseObj.success = false;\n ratingSubmitResponseObj.message = \"Something went wrong!\";\n return ratingSubmitResponseObj;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CrewRouteCtrl', CrewRouteCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CrewRouteCtrl\r\n * @description \r\n * Shows the crew route information\r\n * @ngInject\r\n */\n\n function CrewRouteCtrl($scope, $filter, $routeParams, $route, FlightFactory, GroundDutyFactory, CrewRouteFactory, $location, $uibModal, SyncLogFactory) {\n var dutyNo = $routeParams.dutyNo;\n var dutyDay = $routeParams.dutyDay;\n $scope.crewRouteDuty = CrewRouteFactory.getCrewRouteFromStorage(dutyNo, dutyDay);\n var groundDuties = GroundDutyFactory.getGroundDutiesByDutyNo(dutyNo, dutyDay);\n\n if (groundDuties.length > 0) {\n //there are ground duties in this crew route\n angular.forEach(groundDuties, function (groundDuty) {\n groundDuty.DutyType = \"Ground\";\n groundDuty.Start = groundDuty.DutyBegin;\n });\n }\n\n var flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay);\n\n if (flights.length > 0) {\n //there are flights in this crew route\n angular.forEach(flights, function (flight) {\n flight.DutyType = \"Flight\";\n flight.Start = flight.ScheduledDeparture;\n });\n }\n\n var crewRoute = groundDuties.concat(flights);\n crewRoute = $filter('orderBy')(crewRoute, 'Start', false);\n $scope.crewRoute = crewRoute;\n $scope.currentDutyDay = null;\n $scope.differentDay = differentDay;\n $scope.currentPage = 1;\n $scope.previous = previous;\n $scope.next = next;\n $scope.openRefresh = openRefresh;\n $scope.dutyNo = dutyNo;\n $scope.dutyDay = dutyDay;\n /**\r\n * Checks if two dates have the same day\r\n * @param {string} day1 \r\n * @param {string} day2 \r\n */\n\n function differentDay(day1, day2) {\n day1 = new Date(day1).trimTime().getDay();\n day2 = new Date(day2).trimTime().getDay();\n return !(day1 == day2);\n }\n /**\r\n * Moves pager to previous page\r\n */\n\n\n function previous() {\n if ($scope.currentPage != 1) $scope.currentPage--;\n }\n /**\r\n * Moves pager to next page\r\n */\n\n\n function next() {\n if ($scope.currentPage != crewRoute.length) $scope.currentPage++;\n }\n /**\r\n * Opens refresh modal\r\n */\n\n\n function openRefresh() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/CrewRoute/dlgCrewRouteRefresh.html',\n controller: 'CrewRouteRefreshModalCtrl',\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n crewroute: function crewroute() {\n return $scope.crewRoute;\n },\n crewRouteDuty: function crewRouteDuty() {\n return $scope.crewRouteDuty;\n }\n }\n });\n modalInstance.result.then(function (transferData) {\n if (transferData.sync) {\n SyncLogFactory.forceSync();\n $location.path(\"/\"); //crew route has significantly changed\n } else if (transferData.refresh) {\n $route.reload(); //crew route was updated\n }\n });\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('CrewRouteFactory', CrewRouteFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewRouteFactory\r\n * @description \r\n * Get and Update Crew Routes \r\n * @ngInject\r\n */\n\n function CrewRouteFactory(GenericService, FlightFactory) {\n var objType = 'crewRoute';\n var objCallback = CrewRoute;\n var service = {\n getCrewRoutesFromStorage: getCrewRoutesFromStorage,\n setCrewRoutesToStorage: setCrewRoutesToStorage,\n getCrewRouteFromStorage: getCrewRouteFromStorage,\n setCourseCompleted: setCourseCompleted,\n setCoursePending: setCoursePending\n };\n /**\r\n * Initialize the CrewRoute\r\n * @memberof CrewRouteFactory\r\n */\n\n function CrewRoute() {\n this.DutyDay = null;\n this.DutyNo = null;\n this.Route = null;\n this.DutyBegin = null;\n this.DutyEnd = null;\n this.CrewMeals = [];\n }\n /**\r\n * Get Crew Routes\r\n * @memberof CrewRouteFactory\r\n * @returns {Array} CrewRoutes \r\n */\n\n\n function getCrewRoutesFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save Crew Routes to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} objList A list of Crew Routes\r\n */\n\n\n function setCrewRoutesToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Get a specific Crew Route\r\n * @memberof CrewRouteFactory\r\n * @returns {object} CrewRoute\r\n */\n\n\n function getCrewRouteFromStorage(dutyNo, dutyDay) {\n var crewRoutes = getCrewRoutesFromStorage();\n if (crewRoutes == null) return [];\n var arrayLength = crewRoutes.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (crewRoutes[i].DutyNo == dutyNo && crewRoutes[i].DutyDay == dutyDay) {\n return crewRoutes[i];\n }\n }\n }\n\n function setCourseCompleted(dutyNo, dutyDay, courseId, date) {\n var crewRoutes = getCrewRoutesFromStorage();\n var crewRoute = crewRoutes.find(function (cr) {\n return cr.DutyNo == dutyNo && cr.DutyDay == dutyDay;\n });\n var flightIds = crewRoute.FlightIds;\n var flights = FlightFactory.getFlightsFromStorage().filter(function (x) {\n return flightIds.includes(x.FlightId);\n });\n var crewRouteCourse = crewRoute.Courses.find(function (x) {\n return x.CourseId == courseId && new moment(x.Date).isSame(date);\n });\n if (crewRouteCourse) crewRouteCourse.Status = \"Completed\";\n flights.forEach(function (flight) {\n var flightCourse = flight.Courses.find(function (x) {\n return x.CourseId == courseId && new moment(x.Date).isSame(date);\n });\n\n if (flightCourse) {\n flightCourse.Status = \"Completed\";\n FlightFactory.updateFlight(flight);\n }\n });\n GenericService.saveAll(crewRoutes, objType, objCallback);\n }\n\n function setCoursePending(dutyNo, dutyDay, courseId, date) {\n var crewRoutes = getCrewRoutesFromStorage();\n var crewRoute = crewRoutes.find(function (cr) {\n return cr.DutyNo == dutyNo && cr.DutyDay == dutyDay;\n });\n var crewRouteCourse = crewRoute.Courses.find(function (x) {\n return x.CourseId == courseId && new moment(x.Date).isSame(date);\n });\n if (crewRouteCourse) crewRouteCourse.Status = \"Pending\";\n GenericService.saveAll(crewRoutes, objType, objCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CrewRouteRefreshModalCtrl', CrewRouteRefreshModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CrewRouteRefreshModalCtrl\r\n * @description \r\n * \r\n * @ngInject\r\n */\n\n function CrewRouteRefreshModalCtrl($scope, FlightFactory, GroundDutyFactory, $timeout, $uibModalInstance, crewroute, crewRouteDuty, InfoAPIService, SyncAPIService, $filter, FlightSessionFactory, CourseFactory, $routeParams) {\n $scope.crewroute = crewroute;\n $scope.crewRouteDuty = crewRouteDuty;\n $scope.isRefreshing = true;\n $scope.refreshResultsVisible = false;\n $scope.error = false;\n $scope.sync = false;\n $scope.collapse = collapse;\n $scope.close = close;\n var dutyNo = Number($routeParams.dutyNo);\n var dutyDay = Number($routeParams.dutyDay); //add DataStatus to each duty\n\n for (var i = 0; i < crewroute.length; i++) {\n if (crewroute[i].DutyType == 'Flight') {\n crewroute[i].DataStatus = [{\n datatype: \"Flight Status\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Aircraft Movement\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Crew Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Pax Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Meals\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Connections\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Training Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }];\n } else if (crewroute[i].DutyType == 'Ground') {\n if (crewroute[i].isTraining) {\n crewroute[i].DataStatus = [{\n datatype: \"Duty Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Instructors\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Trainees\",\n status: \"PENDING\",\n text: \"Pending...\"\n }];\n } else {\n crewroute[i].DataStatus = [{\n datatype: \"Duty Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }];\n }\n }\n } //separate flights and groundDuties \n\n\n var currentFlights = [];\n var currentGroundDuties = [];\n\n for (var i = 0; i < crewroute.length; i++) {\n if (crewroute[i].DutyType == 'Flight') currentFlights.push(crewroute[i]);else if (crewroute[i].DutyType == 'Ground') currentGroundDuties.push(crewroute[i]);\n crewroute[i].isCollapsed = false;\n } //get latest info\n\n\n InfoAPIService.refreshCrewRoute(crewRouteDuty, function (responseData) {\n $scope.isRefreshing = false;\n var newFlights = responseData.data.data.flights;\n var newGroundDuties = responseData.data.data.groundDuties; //if there are significant changes in crew route user should sync\n\n if (needsSynch(currentFlights, newFlights, currentGroundDuties, newGroundDuties)) {\n $scope.sync = true;\n } else {\n //Manage details info and Update local storage\n if (newFlights.length) {\n setupFlightInfo(newFlights);\n updateFlights(newFlights); //Save training\n\n newFlights.forEach(function (flight) {\n var trainingCourses = flight.TrainingCourses;\n\n if (trainingCourses && trainingCourses.length && flight.FlightInfo) {\n trainingCourses.forEach(function (trainingCourse) {\n CourseFactory.upsertCourse(trainingCourse, function (course) {\n FlightSessionFactory.applyTraineeInfoToSession(course, course.Id, new moment(flight.FlightInfo.FlightDate).format(\"YYYY-MM-DD\"), dutyNo, dutyDay, function (session) {});\n });\n });\n }\n });\n }\n\n if (newGroundDuties.length) {\n setupGroundInfo(newGroundDuties);\n updateGroundDuties(newGroundDuties);\n }\n\n $scope.refreshResultsVisible = true;\n }\n })[\"catch\"](function () {\n $scope.error = true;\n $scope.isRefreshing = false;\n });\n /**\r\n * Checks if crew route has significantly changed and needs sync\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} currentFlights Array of current flights\r\n * @param {array} newFlights Array of newly fetched flights\r\n * @param {array} currentGroundDuties Array of current ground duties\r\n * @param {array} newGroundDuties Array of newly fetched ground duties\r\n */\n\n function needsSynch(currentFlights, newFlights, currentGroundDuties, newGroundDuties) {\n var sync = false; //1.Crew Route may not exist any more\n\n if (!newFlights.length && !newGroundDuties.length) {\n sync = true;\n } //2.Duties may have been added/removed \n else if (newFlights.length != currentFlights.length || newGroundDuties.length != currentGroundDuties.length) {\n sync = true; //different size arrays\n } else {\n //same size arrays\n if (currentFlights.length && newFlights.length) {\n //compare current with new flights\n currentFlights = $filter('orderBy')(currentFlights, 'FlightId');\n newFlights = $filter('orderBy')(newFlights, 'FlightInfo.FlightId');\n\n for (var i = 0; i < currentFlights.length; i++) {\n if (newFlights[i].FlightInfo && currentFlights[i].FlightId != newFlights[i].FlightInfo.FlightId) {\n sync = true;\n break;\n }\n }\n }\n\n if (currentGroundDuties.length && newGroundDuties.length) {\n //compare current with new ground duties\n currentGroundDuties = $filter('orderBy')(currentGroundDuties, 'Id');\n newGroundDuties = $filter('orderBy')(newGroundDuties, 'Id');\n\n for (var i = 0; i < currentGroundDuties.length; i++) {\n if (currentGroundDuties[i].Id != newGroundDuties[i].Id) {\n sync = true;\n break;\n }\n }\n }\n }\n\n return sync;\n }\n /**\r\n * Updates Flight in Local Storage\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newFlights \r\n */\n\n\n function updateFlights(newFlights) {\n for (var i = 0; i < newFlights.length; i++) {\n InfoAPIService.updateFlightLocalStorage(newFlights[i]);\n }\n }\n /**\r\n * Updates Flight's Data Status\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newFlights \r\n */\n\n\n function setupFlightInfo(newFlights) {\n newFlights = $filter('orderBy')(newFlights, 'Start', false);\n currentFlights = $filter('orderBy')(currentFlights, 'Start', false);\n\n for (var i = 0; i < newFlights.length; i++) {\n InfoAPIService.updateFlightStatusSetter(newFlights[i], currentFlights[i].DataStatus);\n }\n }\n /**\r\n * Updates Ground Duty's Data Status\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newGroundDuties \r\n */\n\n\n function setupGroundInfo(newGroundDuties) {\n newGroundDuties = $filter('orderBy')(newGroundDuties, 'Start', false);\n currentGroundDuties = $filter('orderBy')(currentGroundDuties, 'Start', false);\n\n for (var i = 0; i < newGroundDuties.length; i++) {\n InfoAPIService.updateGroundStatusSetter(newGroundDuties[i], currentGroundDuties[i].DataStatus);\n }\n }\n /**\r\n * Updates Ground Duty in Local Storage\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newFlights \r\n */\n\n\n function updateGroundDuties(newGroundDuties) {\n for (var i = 0; i < newGroundDuties.length; i++) {\n InfoAPIService.updateGroundDutyLocalStorage(newGroundDuties[i]);\n }\n }\n /**\r\n * Shows Details \r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {object} duty \r\n */\n\n\n function collapse(duty) {\n if (!$scope.isRefreshing && $scope.refreshResultsVisible) duty.isCollapsed = !duty.isCollapsed;\n }\n /**\r\n * Closes the modal\r\n * @memberof CrewRouteRefreshModalCtrl\r\n */\n\n\n function close() {\n $uibModalInstance.close({\n sync: $scope.sync,\n refresh: $scope.refreshResultsVisible\n });\n }\n }\n})();\n\"use strict\";\n\n// array functions\nArray.prototype.dynamicSort = function (property, orderByAsc) {\n function dynamicSortComparator(property, orderByAsc) {\n var sortOrder = orderByAsc ? 1 : -1;\n return function (a, b) {\n var result = a[property] < b[property] ? -1 : a[property] > b[property] ? 1 : 0;\n return result * sortOrder;\n };\n }\n\n var sortedArray = this;\n\n if (property != null && property != undefined) {\n orderByAsc = orderByAsc == null || orderByAsc == undefined ? true : orderByAsc;\n sortedArray = this.sort(dynamicSortComparator(property, orderByAsc));\n }\n\n return sortedArray;\n};\n\nArray.prototype.unique = function () {\n var arr = [];\n\n for (var i = 0; i < this.length; i++) {\n if (!arr.contains(this[i])) {\n arr.push(this[i]);\n }\n }\n\n return arr;\n};\n\nArray.prototype.contains = function (v) {\n for (var i = 0; i < this.length; i++) {\n if (this[i] === v) return true;\n }\n\n return false;\n};\n\"use strict\";\n\n// date functions\nDate.prototype.toUTC = function () {\n return new Date(this.getTime() + this.getTimezoneOffset() * 60 * 1000);\n};\n\nDate.prototype.fromUTC = function () {\n return new Date(this.getTime() - this.getTimezoneOffset() * 60 * 1000);\n};\n\nDate.prototype.trimTime = function () {\n this.setHours(0, 0, 0, 0);\n return this;\n};\n\nvar _DatetoJSON = Date.prototype.toJSON;\n\nDate.prototype.toJSON = function () {\n try {\n return _DatetoJSON.call(this);\n } catch (e) {\n if (e instanceof RangeError) {\n return null;\n }\n\n throw e;\n }\n};\n\nDate.DifferenceInMinutes = function (firstDate, secondDate) {\n var diffInMins = null;\n\n if (firstDate && secondDate) {\n var _MS_TO_MINUTES = 1000 * 60;\n\n var date1 = new Date(firstDate);\n var date2 = new Date(secondDate);\n diffInMins = Math.floor((date2.getTime() - date1.getTime()) / _MS_TO_MINUTES);\n }\n\n return diffInMins;\n};\n\nDate.DifferenceInDays = function (firstDate, secondDate) {\n var diffInDays = null;\n\n if (firstDate && secondDate) {\n var _MS_TO_DAYS = 1000 * 3600 * 24;\n\n diffInDays = Math.floor((secondDate.getTime() - firstDate.getTime()) / _MS_TO_DAYS);\n }\n\n return diffInDays;\n};\n\nDate.MinutesToString = function (minutes) {\n var hours = Math.floor(minutes / 60);\n var mins = minutes % 60;\n return (hours > 0 ? hours + (hours == 1 ? \"hr \" : \"hrs \") : \"\") + (mins > 0 ? mins + (mins == 1 ? \"min\" : \"mins\") : \"\");\n};\n\nDate.prototype.AddDays = function (days) {\n var date = new Date(this.valueOf());\n date.setDate(date.getDate() + days);\n return date;\n};\n\"use strict\";\n\n// generic string functions\nString.prototype.endsWith = function (suffix) {\n return this.indexOf(suffix, this.length - suffix.length) !== -1;\n};\n\nif (typeof String.prototype.startsWith != 'function') {\n // see below for better implementation!\n String.prototype.startsWith = function (str) {\n return this.indexOf(str) == 0;\n };\n}\n\nString.prototype.reverse = function () {\n return this.split(\"\").reverse().join(\"\");\n};\n\nString.prototype.getHash = function () {\n var shaObj = new jsSHA(\"SHA-512\", \"TEXT\");\n shaObj.update(this);\n var hash = shaObj.getHash(\"HEX\");\n return hash;\n};\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('autorefresh', autorefresh);\n\n function autorefresh($interval, $timeout, PushNotifier, InfoAPIService, FlightFactory, PaxInfoFactory, AircaftPositionsFactory, CrewCallFactory, PreviousDutyFactory) {\n function link($scope, element, attrs) {\n var flight = $scope.flight; //Auto refresh functionality start\n\n var browserNotificationsEnabled = false;\n var autoUpdateInterval = null;\n var autoUpdateIntervalTimeOffset = null;\n $scope.showAlternativeNotifications = false;\n $scope.showAutoUpdatePanel = false; //Check if push notification are enabled\n\n PushNotifier.CheckForPermissionsAndSupport().then(function (res) {\n browserNotificationsEnabled = res;\n });\n var ScheduledDepartureTimeStamp = 0;\n\n if (flight) {\n ScheduledDepartureTimeStamp = moment.utc(flight.ScheduledDeparture).valueOf();\n }\n\n var now = moment().valueOf();\n $scope.showAutoUpdatePanel = ScheduledDepartureTimeStamp - 70 * 60000 <= now && ScheduledDepartureTimeStamp + 30 * 60000 >= now && flight.DepartureEU;\n $scope.radioModel = false;\n $scope.$watch('radioModel', function (value) {\n if (value == true) autoflightInfoInterval();\n\n if (value == false) {\n $interval.cancel(autoUpdateInterval);\n autoUpdateInterval = null;\n }\n });\n\n function autoflightInfoInterval() {\n var currentInfo = null;\n currentInfo = PushNotifier.formatInfoToCompare(flight.FlightId);\n var intervalTime = timerDelayGenerator(flight.ScheduledDeparture);\n\n if (intervalTime > 0) {\n InfoAPIService.getPax(flight.FlightId).then(function (responseData) {\n $scope.flight = FlightFactory.getFlightFromTotalFlights(flight.FlightId);\n $scope.paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flight.FlightId);\n $scope.aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId(flight.FlightId);\n $scope.flightETA = $scope.flight.ETA ? moment(flight.ETA).valueOf() : new Date(flight.ScheduledArrival).getTime();\n var updatedInfo = PushNotifier.formatInfoToCompare(flight.FlightId);\n var changes = PushNotifier.compareAndExtractChanges(currentInfo, updatedInfo);\n var message = PushNotifier.MessageGenerator(changes); //UPDATE CREW INFO\n //1. First remove all additional info (phone numbers & previous duties) for this flight\n\n CrewCallFactory.cleanFlightCrewNumbers(flight.FlightId);\n PreviousDutyFactory.cleanFlightPreviousDuties(flight.FlightId); //2. Then save any fetched info\n\n if (responseData.data.data.FlightInfo) {\n var crew = responseData.data.data.FlightInfo.crew;\n CrewCallFactory.saveFlightPhoneNumbers(flight.FlightId, crew, flight.ScheduledArrival, flight.ScheduledDeparture);\n PreviousDutyFactory.saveFlightPreviousDuties(flight.FlightId, crew);\n }\n\n if (changes && changes.length > 0) {\n if (browserNotificationsEnabled) {\n try {\n PushNotifier.Generate('Changes', message);\n } catch (e) {\n $scope.changes = changes;\n $scope.showAlternativeNotifications = true;\n }\n } else {\n $scope.changes = changes;\n $scope.showAlternativeNotifications = true;\n }\n }\n\n flight = $scope.flight;\n $scope.flight = false;\n $timeout(function () {\n $scope.flight = flight;\n }, 100);\n }, function (responseData) {\n if (browserNotificationsEnabled && window.navigator.onLine) {\n try {\n PushNotifier.Generate('Changes', 'Update failed');\n } catch (ex) {//TODO: add related messagge KVEN,EPAP\n }\n }\n });\n\n if (intervalTime != autoUpdateIntervalTimeOffset) {\n autoUpdateIntervalTimeOffset = intervalTime;\n $interval.cancel(autoUpdateInterval);\n autoUpdateInterval = $interval(autoflightInfoInterval, autoUpdateIntervalTimeOffset);\n }\n } else {\n $interval.cancel(autoUpdateInterval);\n $scope.showAutoUpdatePanel = false;\n }\n }\n\n function timerDelayGenerator(departureTime) {\n var intervalTime = -1;\n var depTimestamp = moment.utc(departureTime).valueOf();\n var nowTimeStamp = moment().valueOf();\n var minutes = 60000;\n\n if (depTimestamp - 70 * minutes <= nowTimeStamp && depTimestamp + 30 * minutes >= nowTimeStamp) {\n var absoluteMinuteDiff = Math.abs(depTimestamp - nowTimeStamp);\n\n if (absoluteMinuteDiff <= 10 * minutes) {\n intervalTime = 2 * minutes;\n } else if (absoluteMinuteDiff <= 15 * minutes) {\n intervalTime = 3 * minutes;\n } else {\n intervalTime = 5 * minutes;\n }\n }\n\n return intervalTime;\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: 'views/directives/autofresh.tpl.html',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('basicFooter', basicFooter);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name basicFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of basicFooter (appears in groundDuty-info view)\r\n *\r\n * Initialize a basic Footer Template and its Navigation Functionality\r\n * Used in groundDuty and crewRoute view\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function basicFooter($location, SettingsMain, UserFactory, DataCleanerFactory) {\n /**\r\n * Initialize basicFooter and events\r\n * @memberof basicFooter\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attrs attribute of this element\r\n */\n function link(scope, element, attrs) {\n if (scope.groundDuty || scope.crewRoute) {\n /**\r\n * Open a modal from which u can Logout from the application\r\n * @memberof groundFooter \r\n */\n var logout = function logout() {\n var isSecure = UserFactory.isSecure();\n bootbox.dialog({\n message: (isSecure ? \"Due to the fact that you are working over a public computer, all stored data will be deleted on logout!

\" : \"You will be able to login again into the same account, even if there is no internet access.

\") + \"Please confirm that you wish to log out.\",\n title: \"User Logout\",\n buttons: {\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n },\n logout: {\n label: \"Logout\",\n className: \"btn-warning\",\n callback: function callback() {\n UserFactory.clearActiveUser();\n if (isSecure) DataCleanerFactory.deleteAllData();\n location.reload(true); // need to reload, in order for the\n // browser to check the cache.manifest\n // and discover any changes\n }\n }\n }\n });\n };\n /**\r\n * Navigate to Calendar View\r\n * @memberof groundFooter \r\n */\n\n\n var gotoCalendar = function gotoCalendar() {\n // handleIfReport(state, flightId, report);\n SettingsMain.setEditingPage(null); // go to dashboard\n\n $location.path(\"/\");\n };\n /**\r\n * Navigate to Bucket Calendar View\r\n * @memberof groundFooter \r\n */\n\n\n var gotoBucketCalendar = function gotoBucketCalendar() {\n SettingsMain.setEditingPage(null);\n $location.path('/bucket');\n };\n /**\r\n * Navigate to FAQs View\r\n * @memberof groundFooter \r\n */\n\n\n var gotoFAQs = function gotoFAQs() {\n SettingsMain.setEditingPage(null);\n $location.path('/faqs');\n };\n /**\r\n * Navigate to Messages View\r\n * @memberof groundFooter \r\n */\n\n\n var gotoMessageLibrary = function gotoMessageLibrary() {\n $location.path('/messages');\n };\n\n var state = scope.state;\n var user = UserFactory.getUser();\n var delay = 60000;\n scope.gotoMessageLibrary = gotoMessageLibrary;\n scope.gotoFAQs = gotoFAQs;\n scope.gotoBucketCalendar = gotoBucketCalendar;\n scope.gotoCalendar = gotoCalendar;\n scope.logout = logout;\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/Main/basic-footer.tpl.html\",\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('chart', chart);\n\n function chart() {\n var baseWidth = 600;\n var baseHeight = 400;\n return {\n restrict: 'E',\n template: '',\n scope: {\n chartObject: \"=value\"\n },\n link: function link(scope, element, attrs) {\n var canvas = element.find('canvas')[0];\n var context = canvas.getContext('2d');\n var chart;\n var options = {\n type: attrs.type || \"Line\",\n width: attrs.width || baseWidth,\n height: attrs.height || baseHeight\n };\n canvas.width = options.width;\n canvas.height = options.height;\n chart = new Chart(context);\n scope.$watch(function () {\n return element.attr('type');\n }, function (value) {\n if (!value) return;\n options.type = value;\n var chartType = options.type;\n\n if (scope.chartObject) {\n chart[chartType](scope.chartObject.data, scope.chartObject.options);\n }\n }); //Update when charts data changes\n\n scope.$watch(function () {\n return scope.chartObject;\n }, function (value) {\n if (!value) return;\n var chartType = options.type;\n chart[chartType](scope.chartObject.data, scope.chartObject.options);\n if (scope.chartInstance) scope.chartInstance.destroy();\n scope.chartInstance = chart[chartType](scope.chartObject.data, scope.chartObject.options);\n }, true);\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('crewMeals', crewMeals);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name crewMeals\r\n * @restrict E\r\n * @description\r\n * Implementation of crew meals\r\n *\r\n * Display the crew meals\r\n * @attr {String} dutyNo \r\n * @attr {String} dutyDay \r\n * @attr {String} flight-id\r\n * @example\r\n * Usage:\r\n * \r\n * \r\n * @ngInject\r\n */\n\n function crewMeals(CrewRouteFactory, CrewMealFactory, FlightFactory, $sce, $timeout) {\n /**\r\n * Initialize crewMeals\r\n * @memberof crewMeals\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attributes attributes of this element\r\n */\n function link(scope, element, attributes) {\n scope.togglePanel = togglePanel;\n scope.route = CrewRouteFactory.getCrewRouteFromStorage(scope.dutyNo, scope.dutyDay);\n scope.HasRegChanged = false;\n scope.noClicked = noClicked;\n scope.yesClicked = yesClicked;\n scope.submitRatingClicked = submitRatingClicked;\n scope.canceClicked = canceClicked;\n scope.clearFormData = clearFormData; //for flight page\n\n scope.isFlightPanel = scope.flightId !== \"\";\n scope.flightCrewMeals = null; //for route page\n\n scope.isRoutePanel = scope.flightId == null || scope.flightId === \"\";\n scope.routeCrewMeals = [];\n scope.showCrewMealsPanel = false; //Rating Form\n\n scope.ratingForm = {\n CateringMealId: '',\n FlightId: '',\n Rating: '',\n Comments: '',\n DidNotEatReasonId: ''\n };\n scope.submitRatingMessage = '';\n scope.showPanel = \"meals\";\n scope.DidNotEatReasons = [];\n scope.isOffline = !window.navigator.onLine;\n scope.popoverInfo = {\n title: $sce.trustAsHtml(' Attention'),\n contentHtml: $sce.trustAsHtml('
' + 'There is an aircraft change on your route. Please arrange to take your assigned meal with you.' + '
')\n };\n window.addEventListener('offline', function (e) {\n $timeout(scope.isOffline = !window.navigator.onLine);\n });\n window.addEventListener('online', function (e) {\n $timeout(scope.isOffline = !window.navigator.onLine);\n }); //Get scope values\n\n if (scope.isFlightPanel && scope.route) {\n var crewMeals = scope.route.CrewMeals;\n\n for (var i = 0; i < crewMeals.length; i++) {\n if (crewMeals[i].FlightId == scope.flightId) {\n scope.flightCrewMeals = new FlightCrewMeal(crewMeals[i]);\n scope.showCrewMealsPanel = true;\n break;\n }\n }\n\n scope.HasRegChanged = hasRegChanged(scope.flightId);\n }\n\n if (scope.isRoutePanel && scope.route && scope.route.CrewMeals.length > 0) {\n var crewMeals = scope.route.CrewMeals;\n\n for (var i = 0; i < crewMeals.length; i++) {\n scope.routeCrewMeals.push(new FlightCrewMeal(crewMeals[i]));\n scope.showCrewMealsPanel = true;\n }\n\n scope.HasRegChanged = hasRegChanged(crewMeals[0].FlightId);\n }\n\n if (!scope.isOffline && scope.showCrewMealsPanel) {\n CrewMealFactory.getCrewMealsDidNotEatReasons().then(function (res) {\n return scope.DidNotEatReasons = res;\n });\n } //FlightCrewMeal Constructor\n\n\n function FlightCrewMeal(flight) {\n this.FlightDate = moment(flight.FlightDate).format(\"DD/MM\");\n this.FlightNo = flight.FlightNo;\n this.FlightDeparture = flight.FlightDeparture;\n this.CrewMeals = \"\";\n this.CrewMealsDescriptions = [];\n\n for (var i = 0; i < Object.values(flight.CrewMealsCateringIds).length; i++) {\n if (i != 0) {\n this.CrewMeals += \" & \";\n }\n\n var crewMealDetails = CrewMealFactory.getCrewMealFromStorage(Object.values(flight.CrewMealsCateringIds)[i]);\n var hasRating = CrewMealFactory.hasRating(Object.keys(flight.CrewMealsCateringIds)[i]);\n this.CrewMeals += crewMealDetails.Title;\n this.CrewMealsDescriptions.push({\n CrewMealId: Object.keys(flight.CrewMealsCateringIds)[i],\n CateringMealId: crewMealDetails.CateringMealId,\n Title: crewMealDetails.Title,\n Description: crewMealDetails.Description,\n HasRating: hasRating\n });\n }\n } //Change Registration check\n\n\n function hasRegChanged(flightId) {\n var retVal = false;\n var flights = FlightFactory.getFlightsByFlightId(flightId);\n\n if (flights.length > 0) {\n var acTailNo = flights[0].AcTailNo;\n\n for (var i = 0; i < flights.length; i++) {\n if (flights[i].AcTailNo != acTailNo) {\n retVal = true;\n break;\n }\n }\n }\n\n return retVal;\n }\n /**\r\n * toggle Panel\r\n * @memberof crewMeals\r\n * @param {number} panelId\r\n */\n\n\n function togglePanel(panelId) {\n $('#' + panelId).toggle();\n }\n\n function noClicked(cateringMealId, crewMealId) {\n clearFormData(cateringMealId, crewMealId);\n scope.showPanel = \"didNotEatMeal\";\n }\n\n function yesClicked(cateringMealId, crewMealId) {\n clearFormData(cateringMealId, crewMealId);\n scope.showPanel = \"mealRating\";\n } //function checkConnection\n\n\n function clearFormData(cateringMealId, crewMealId) {\n scope.ratingForm.CateringMealId = cateringMealId;\n scope.ratingForm.FlightId = scope.flightId;\n scope.ratingForm.CrewMealId = crewMealId;\n scope.ratingForm.Rating = '';\n scope.ratingForm.DidNotEatReasonId = '';\n scope.ratingForm.Comments = '';\n scope.isOffline = !window.navigator.onLine;\n }\n\n function canceClicked() {\n scope.showPanel = \"meals\";\n }\n\n function submitRatingClicked() {\n scope.showPanel = \"loading\";\n CrewMealFactory.sendCrewMealsRatingReport(this.ratingForm).then(function (res) {\n return handleSubmitResponse(res);\n });\n }\n\n function handleSubmitResponse(res) {\n if (res.success) {\n var index = scope.flightCrewMeals.CrewMealsDescriptions.findIndex(function (x) {\n return x.CateringMealId == scope.ratingForm.CateringMealId;\n });\n scope.flightCrewMeals.CrewMealsDescriptions[index].HasRating = true;\n manageResponseMessage(\"success\", res.message);\n } else {\n manageResponseMessage(\"failure\", res.message);\n }\n }\n\n function manageResponseMessage(panelToShow, message) {\n scope.submitRatingMessage = message;\n scope.showPanel = panelToShow;\n $timeout(function () {\n scope.showPanel = \"meals\";\n }, 3000);\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/directives/crewMeals.tpl.html',\n scope: {\n dutyNo: '@',\n dutyDay: '@',\n flightId: '@'\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('flightCrew', flightCrew);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightCrew\r\n * @restrict E\r\n * @description\r\n * Initialize Flight Crew Information\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function flightCrew() {\n function link(scope, element, attrs) {}\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/directives/flightCrew.tpl.html\",\n scope: {\n flight: '='\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('flightFooter', flightFooter);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of FlightFooter\r\n *\r\n * Initialize The flights Footer Template and its Navigation, Sync, Footer Functionality\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function flightFooter(FlightFactory, orderByFilter, $location, SettingsMain, PilotReportLocalEditFactory, ReportGuidFactory, UserFactory, apiUrl, $uibModal, MessageFactory, DataCleanerFactory, $route, MemoFactory, $sce, $timeout, $interval) {\n /**\r\n * Initialize flightFooter and events\r\n * @memberof flightFooter\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attrs attribute of this element\r\n */\n function link(scope, element, attrs) {\n if (scope.flight) {\n /**\r\n * Get the latest Pax and Gate Informations\r\n * @memberof flightFooter \r\n */\n var SynchPaxAndGates = function SynchPaxAndGates() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgLightSync.html',\n controller: 'SyncPaxCtrl',\n size: 'md',\n backdrop: 'static',\n keyboard: false,\n resolve: {\n flightId: function flightId() {\n return _flightId;\n }\n }\n });\n modalInstance.result.then(function () {\n scope.lastSync = new Date().getTime();\n }, function () {});\n };\n /**\r\n * Find previous,next and current flight of the Route of the selected flight\r\n * @memberof flightFooter\r\n * @param {number} flightId input the Id of a Flight \r\n * @returns {Object} previous,next and current flight\r\n */\n\n\n var getPreviousAndNextFlights = function getPreviousAndNextFlights(flightId) {\n var nextFlight, previousFlight, currentFlight; // also load the flights created by the user\n\n var flights = FlightFactory.getFlightsByRoute(scope.flight.Route, scope.flight.DutyDate);\n flights = orderByFilter(flights, orderByDate, false);\n\n function orderByDate(item) {\n var date = new Date(item.ScheduledDeparture);\n return date;\n }\n\n for (var i = 0; i < flights.length; i++) {\n if (flights[i].FlightId == flightId) {\n if (i >= 1) {\n previousFlight = flights[i - 1];\n }\n\n if (i + 1 < flights.length) {\n nextFlight = flights[i + 1];\n }\n\n currentFlight = flights[i];\n }\n } //alert(flights.currentFlight.flightId + \" \" + flights.nextFlight.flightId+ \" \" + flights.previousFlight.flightId);\n\n\n return {\n nextFlight: nextFlight,\n previousFlight: previousFlight,\n currentFlight: currentFlight\n };\n };\n /**\r\n * It handles the pilot report when u want to navigate to another view\r\n * @memberof flightFooter\r\n * @param {String} state input the current state (view) \r\n * @param {number} flightId input the Id of a Flight \r\n * @param {Object} report input the pilot report \r\n */\n\n\n var handleIfReport = function handleIfReport(state, flightId, report) {\n if (state == 'report') {\n if (report == null) {\n report = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\n }\n\n var guid = report.ReportGuid;\n var status = report.Status; // delete the temp report\n\n PilotReportLocalEditFactory.deleteTempReport(); //reuse guid if this was a new report\n\n if (status == 'pending') ReportGuidFactory.restoreGuid(report.ReportGuid);\n }\n };\n /**\r\n * Open the pilot Report for the selected Flight\r\n * @memberof flightFooter \r\n * @param {number} flightId input the Id of a Flight\r\n */\n\n\n var openReport = function openReport(flightId) {\n var user = UserFactory.getUser();\n var token = '';\n\n if (user != null) {\n token = user.token;\n token = encodeURIComponent(token);\n } // load the flight\n\n\n var flight = FlightFactory.getFlightFromStorage(flightId);\n\n if (flight == null) {\n // if not found, also check the local flights\n var flight = FlightFactory.getLocalFlightFromStorage(flightId);\n if (flight == null) return;\n } // load the reports\n\n\n var serverReportForThisUser = flight.getServerPilotReportForUser(user.aimsId);\n var serverReportsByAnotherUser = flight.getServerPilotReportsByAnotherUser(user.aimsId);\n var localReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId); // no stored local report\n\n if (localReport == null) {\n // has server report from this user and from other users\n if (serverReportForThisUser != null && serverReportsByAnotherUser.length > 0) {\n // show selection dialog\n openReportDialog(flightId);\n } // has server report only from this user\n else if (serverReportForThisUser != null && serverReportsByAnotherUser.length == 0) {\n $location.path(\"reportsHistory/\" + serverReportForThisUser.ReportId + \"/\" + flightId + \"/Pilot\");\n } // has server report only from other users\n else if (serverReportForThisUser == null && serverReportsByAnotherUser.length > 0) {\n // show selection dialog\n openReportDialog(flightId);\n } // no server reports, create a new local report directly\n else {\n $location.path(\"report/new:\" + -1 + \"/\" + flightId);\n }\n } // has stored local report\n else {\n // special case: has server report from this user, and not from\n // other users\n if (serverReportForThisUser != null && serverReportsByAnotherUser.length == 0) {\n // open the local report for editing\n $location.path(\"report/\" + localReport.ReportGuid);\n } // general case: has server report from this user or from other\n // users\n else if (serverReportForThisUser != null || serverReportsByAnotherUser.length > 0) {\n // show selection dialog\n openReportDialog(flightId);\n } // no server reports, open the local report directly\n else {\n // open the existing report for editing\n $location.path(\"report/\" + localReport.ReportGuid);\n }\n }\n };\n /**\r\n * Open a modal to choose an action when there is already a pilot report from another user\r\n * @memberof flightFooter \r\n * @param {number} flightId input the Id of a Flight\r\n */\n\n\n var openReportDialog = function openReportDialog(_flightId2) {\n var modalInstance = $uibModal.open({\n templateUrl: './views/Dialogs/dlgOpenReport.html',\n controller: 'OpenReportDialogCtrl',\n size: 'md',\n resolve: {\n flightId: function flightId() {\n return _flightId2;\n }\n }\n });\n modalInstance.result.then(function () {}, function () {});\n };\n /**\r\n * Open a modal from which u can Logout from the application\r\n * @memberof flightFooter \r\n */\n\n\n var logout = function logout() {\n var isSecure = UserFactory.isSecure();\n bootbox.dialog({\n message: (isSecure ? \"Due to the fact that you are working over a public computer, all stored data will be deleted on logout!

\" : \"You will be able to login again into the same account, even if there is no internet access.

\") + \"Please confirm that you wish to log out.\",\n title: \"User Logout\",\n buttons: {\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n },\n logout: {\n label: \"Logout\",\n className: \"btn-warning\",\n callback: function callback() {\n UserFactory.clearActiveUser();\n if (isSecure) DataCleanerFactory.deleteAllData();\n location.reload(true); // need to reload, in order for the\n // browser to check the cache.manifest\n // and discover any changes\n }\n }\n }\n });\n };\n /**\r\n * Redirects to Reset Device View\r\n * @memberof flightFooter \r\n */\n\n\n var resetDevice = function resetDevice() {\n $location.path(\"/reset\");\n };\n /**\r\n * Open a modal from which you can delete all available reports\r\n * @memberof flightFooter \r\n * @method\r\n */\n\n\n var deleteAllReports = function deleteAllReports() {\n bootbox.dialog({\n message: \"Use this process to clear your device from all locally stored Pilot Reports, in order to save up space, when available storage space is not sufficient for the application to function properly.

\" + \"

ATTENTION

\" + \"This action will delete all Pilot Reports from your device, including draft and completed ones not sent to the server.\",\n title: \"Application Logs Reset\",\n buttons: {\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n },\n danger: {\n label: \"Delete All Pilot Reports\",\n className: \"btn-danger\",\n callback: function callback() {\n DataCleanerFactory.deleteAllReports();\n $route.reload();\n bootbox.alert(\"All Pilot Reports have been successfully deleted.\", function () {});\n }\n }\n }\n });\n };\n /**\r\n * Navigate to Calendar View\r\n * @memberof flightFooter \r\n */\n\n\n var gotoCalendar = function gotoCalendar() {\n handleIfReport(state, _flightId, report);\n SettingsMain.setEditingPage(null); // go to dashboard\n\n $location.path(\"/\");\n };\n /**\r\n * Navigate to Messages View\r\n * @memberof flightFooter \r\n */\n\n\n var gotoMessages = function gotoMessages() {\n handleIfReport(state, _flightId, report);\n $location.path('/messages/' + _flightId);\n };\n /**\r\n * Navigate to Selected Flight Information View\r\n * @param {number} flightId input the Id of a Flight\r\n * @memberof flightFooter \r\n */\n\n\n var gotoFlight = function gotoFlight(flightId) {\n handleIfReport(state, flightId, report);\n $location.path('/flightinfo/' + flightId);\n };\n /**\r\n * Navigate to Messages View\r\n * @memberof flightFooter \r\n */\n\n\n var gotoMessageLibrary = function gotoMessageLibrary() {\n handleIfReport(state, _flightId, report);\n $location.path('/messages');\n };\n /**\r\n * Navigate to the Current Flight's Information View\r\n * @memberof flightFooter \r\n */\n\n\n var gotoFlightInfo = function gotoFlightInfo() {\n gotoFlight(_flightId);\n };\n /**\r\n * Open current's Flight Pilot Report\r\n * @memberof flightFooter \r\n */\n\n\n var openPilotReport = function openPilotReport() {\n openReport(_flightId);\n };\n /**\r\n * Navigate to Memos Library\r\n * @memberof flightFooter \r\n */\n\n\n var gotoMemosLibrary = function gotoMemosLibrary() {\n handleIfReport(state, _flightId, report);\n $location.path('/memos');\n };\n\n var goToSafetyReport = function goToSafetyReport(flightId) {\n $location.path('/safetyreport/flightcrewreport/' + flightId);\n };\n\n var goToFatigueReport = function goToFatigueReport(flightId) {\n $location.path('/safetyreport/fatiguereport/' + flightId);\n };\n\n /**\r\n * Show Popover that advices User to sync so he can get the latest Pax and Gate Informations\r\n * @memberof flightFooter \r\n */\n var showSyncPopover = function showSyncPopover() {\n var firstSyncWarning = departure - 4500000; //75 mintes before takeoff\n\n var secondSyncWarning = departure - 600000; //10 minutes before takeoff\n\n var now = new Date().getTime();\n var lastSync = scope.lastSync;\n\n if (now > firstSyncWarning && now < secondSyncWarning && (!lastSync || lastSync < firstSyncWarning) || now > secondSyncWarning && now < departure && (!lastSync || lastSync < secondSyncWarning)) {\n scope.enableSyncPopover = true;\n }\n };\n\n var returnTimeDiff = function returnTimeDiff() {\n //time difference in minutes from: now and pax info list date\n scope.paxTimeDiffInMins = Math.round((new Date().getTime() - new Date(scope.paxInfo.LastRun).getTime()) / 60000);\n };\n\n /**\r\n * Navigate to Submit ticket view\r\n * @memberof filghtFooter \r\n */\n var gotoTicket = function gotoTicket() {\n // go to Submit ticket view\n $location.path(\"/ticket\");\n };\n /**\r\n * Navigate to the Current Flight's Pax Information View\r\n * @memberof flightFooter \r\n */\n\n\n var gotoPaxInfo = function gotoPaxInfo() {\n SettingsMain.setEditingPage(null);\n handleIfReport(state, _flightId, report);\n $location.path('/pax/' + _flightId);\n };\n\n var _flightId = scope.flight.FlightId;\n var state = scope.state;\n var report = scope.report;\n var flights = getPreviousAndNextFlights(_flightId);\n var messagesCount = 0;\n var unreadMessagesCount = 0;\n var memosForCurrentFlight = 0;\n var user = UserFactory.getUser();\n var messages = [];\n var memos = [];\n var delay = 60000;\n\n if (state != \"memos\" && flights && flights.currentFlight) {\n MemoFactory.getMemosForFlight(_flightId, function (results) {\n memos = results;\n scope.memosForCurrentFlight = memos.length;\n });\n }\n\n if (state != \"messages\" && flights && flights.currentFlight) {\n messages = MessageFactory.getMessagesFromIds(flights.currentFlight.messages);\n messagesCount = messages.length;\n\n for (var i = 0; i < messages.length; i++) {\n if (messages[i].ReadDt == null) {\n unreadMessagesCount++;\n }\n }\n }\n\n if (state == 'pax' || state == 'flight' && scope.paxInfo) {\n var now = new Date().getTime();\n var departure = new Date(scope.flight.ScheduledDeparture).getTime();\n\n if (departure < now) {\n var openSyncPopover = $interval(showSyncPopover, delay);\n }\n }\n\n if (state == 'pax' || state == 'flight') {\n if (scope.paxInfo && new Date(scope.flight.ScheduledDeparture).getTime() > new Date().getTime()) {\n returnTimeDiff();\n var showTimeDiff = $interval(returnTimeDiff, delay);\n }\n }\n\n scope.gotoFlight = gotoFlight;\n scope.previousFlight = flights.previousFlight;\n scope.nextFlight = flights.nextFlight;\n scope.gotoCalendar = gotoCalendar;\n scope.gotoFlightInfo = gotoFlightInfo;\n scope.openPilotReport = openPilotReport;\n scope.gotoMessages = gotoMessages;\n scope.messagesCount = messagesCount;\n scope.unreadMessagesCount = unreadMessagesCount;\n scope.logout = logout;\n scope.resetDevice = resetDevice;\n scope.deleteAllReports = deleteAllReports;\n scope.gotoMessageLibrary = gotoMessageLibrary;\n scope.gotoMemosLibrary = gotoMemosLibrary;\n scope.gotoPaxInfo = gotoPaxInfo;\n scope.showMobileMenu = false;\n scope.userPosition = user.position;\n scope.SynchPaxAndGates = SynchPaxAndGates;\n scope.gotoTicket = gotoTicket;\n scope.goToSafetyReport = goToSafetyReport;\n scope.goToFatigueReport = goToFatigueReport;\n scope.syncWarning = $sce.trustAsHtml('
You are strongly advised to sync your device.
');\n scope.enableSyncPopover = false;\n scope.lastSync = null;\n element.on('$destroy', function () {\n $interval.cancel(openSyncPopover);\n $interval.cancel(showTimeDiff);\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/Flight/footer.tpl.html\",\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('flightHeader', flightHeader);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightHeader\r\n * @restrict E\r\n * @description\r\n * Implementation of flightHeader\r\n * Initialize the template of the header while you are in the Flight Level\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function flightHeader() {\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/Flight/header.tpl.html\",\n scope: false\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('groundCrew', groundCrew);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundCrew\r\n * @restrict E\r\n * @description\r\n * Initialize Trainer and Trainee Info\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function groundCrew() {\n function link(scope, element, attrs) {\n scope.groundDuty = scope.duty;\n scope.toggleCrewList = toggleCrewList;\n scope.groundDuty.Trainees.forEach(function (relatedTrainees) {\n relatedTrainees.isCollapsed = false;\n relatedTrainees.dynamicSize = 10;\n });\n /**\r\n * @memberof GroundDutyCtrl\r\n * @name toggleCrewList\r\n * @description \r\n * Οnly show the first 10 trainees - if more then toggle\r\n */\n\n function toggleCrewList(relatedTrainees) {\n relatedTrainees.isCollapsed = !relatedTrainees.isCollapsed;\n if (relatedTrainees.isCollapsed) relatedTrainees.dynamicSize = relatedTrainees.CrewMembers.length;else relatedTrainees.dynamicSize = 10;\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/directives/groundCrew.tpl.html\",\n scope: {\n duty: '='\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('groundHeader', groundHeader);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundHeader\r\n * @restrict E\r\n * @description\r\n * Implementation of groundHeader (appears in groundDuty-info view)\r\n * Initialize the template of the header while you are in the Ground Duty Level\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function groundHeader() {\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/GroundDuty/header.tpl.html\",\n scope: false\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('groundServices', groundServices);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundServices\r\n * @restrict E\r\n * @description\r\n * Implementation of ground services \r\n *\r\n * Display the ground services\r\n * @attr {String} arrival The flight arrival station.\r\n * @attr {String} departure The flight departure station.\r\n * @attr {String} flight-id The flight id.\r\n * @example\r\n * Usage:\r\n * \r\n * \r\n * @ngInject\r\n */\n\n function groundServices(GroundServicesFactory, PilotReportLocalEditFactory, PilotReportLocalEditCreatorFactory, FlightFactory, $sce) {\n /**\r\n * Initialize groundServices\r\n * @memberof groundServices\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attributes attributes of this element\r\n */\n function link(scope, element, attributes) {\n scope.togglePanel = togglePanel;\n scope.flight = FlightFactory.getFlightFromTotalFlights(scope.flightId);\n scope.isInFinalState = isInFinalState;\n scope.saveNewUsedState = saveNewUsedState;\n scope.DepartureGroundServices = [];\n scope.ArrivalGroundServices = [];\n scope.popoverInfo = {\n title: $sce.trustAsHtml(' Info'),\n contentHtml: $sce.trustAsHtml('
Contracted Services' + '
Non Contracted Services' + '
')\n };\n var report = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(scope.flightId);\n\n if (report == null) {\n if (scope.departure) {\n scope.DepartureGroundServices = GroundServicesFactory.getGroundServicesByStation(scope.departure);\n }\n\n if (scope.arrival) {\n scope.ArrivalGroundServices = GroundServicesFactory.getGroundServicesByStation(scope.arrival);\n }\n } else {\n report = PilotReportLocalEditFactory.checkForNewGroundServices(report);\n\n if (scope.departure) {\n scope.DepartureGroundServices = report.DepartureGroundServices;\n }\n\n if (scope.arrival) {\n scope.ArrivalGroundServices = report.ArrivalGroundServices;\n }\n }\n /**\r\n * Check if the report is in a final state so that we cant edit any more\r\n * @memberof groundServices\r\n * @returns {boolean} true if final, false otherwise\r\n */\n\n\n function isInFinalState() {\n var isInFinalState = scope.flight.LineStatus === 'na' || scope.flight.LineStatus === 'stored' || scope.flight.LineStatus === 'storedotheruser' || scope.flight.LineStatus === 'stored+otheruser' || scope.flight.LineStatus === 'synched' || scope.flight.LineStatus === 'synchedotheruser';\n return isInFinalState;\n }\n /**\r\n * When a ground service usage is toggled on or off,\r\n * create the report if it doesnt exist\r\n * or just save the changes\r\n * @memberof groundServices\r\n */\n\n\n function saveNewUsedState() {\n //if report is pending, it doesnt exist yet. create it\n if (scope.flight.LineStatus === 'pending' || scope.flight.LineStatus === 'pendingoverdue') {\n report = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight(scope.flightId);\n\n if (scope.departure) {\n report.DepartureGroundServices = scope.DepartureGroundServices;\n } else {\n report.DepartureGroundServices = [];\n }\n\n if (scope.arrival) {\n report.ArrivalGroundServices = scope.ArrivalGroundServices;\n } else {\n report.ArrivalGroundServices = [];\n }\n\n report.Status = 'draft';\n report.saveReport();\n FlightFactory.updateFlightFromReport(report);\n }\n\n PilotReportLocalEditFactory.setPilotReportToStorage(report);\n } //TODO : find a more angular way (EPAP)\n\n /**\r\n * toggle Panel\r\n * @memberof groundServices\r\n * @param {number} panelId\r\n */\n\n\n function togglePanel(panelId) {\n $('#' + panelId).toggle();\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/directives/groundServices.tpl.html',\n scope: {\n arrival: '@',\n departure: '@',\n flightId: '@'\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('mainFooter', mainFooter);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name mainFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of mainFooter\r\n * Initialize The main Footer Template and its Navigation, Sync, Footer Functionality\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function mainFooter($location, SettingsMain, UserFactory, $uibModal, MessageFactory, DataCleanerFactory, $route, MemoFactory, $sce, $timeout, LeaveRequestFactory) {\n /**\r\n * Initialize mainFooter and events\r\n * @memberof mainFooter\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attrs attribute of this element\r\n */\n function link(scope, element, attrs) {\n var messagesCount = 0;\n var unreadMessagesCount = 0;\n var memosCount = 0;\n var messages = [];\n var memos = [];\n /**\r\n * Open a modal from which u can Logout from the application\r\n * @memberof mainFooter \r\n */\n\n function logout() {\n var isSecure = UserFactory.isSecure();\n bootbox.dialog({\n message: (isSecure ? \"Due to the fact that you are working over a public computer, all stored data will be deleted on logout!

\" : \"You will be able to login again into the same account, even if there is no internet access.

\") + \"Please confirm that you wish to log out.\",\n title: \"User Logout\",\n buttons: {\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n },\n logout: {\n label: \"Logout\",\n className: \"btn-warning\",\n callback: function callback() {\n UserFactory.clearActiveUser();\n if (isSecure) DataCleanerFactory.deleteAllData();\n location.reload(true); // need to reload, in order for the\n // browser to check the cache.manifest\n // and discover any changes\n }\n }\n }\n });\n }\n /**\r\n * Redirects to Reset Device View\r\n * @memberof mainFooter \r\n */\n\n\n function resetDevice() {\n $location.path(\"/reset\");\n }\n /**\r\n * Open a modal from which you can delete all available reports\r\n * @memberof mainFooter \r\n * @method\r\n */\n\n\n function deleteAllReports() {\n bootbox.dialog({\n message: \"Use this process to clear your device from all locally stored Pilot Reports, in order to save up space, when available storage space is not sufficient for the application to function properly.

\" + \"

ATTENTION

\" + \"This action will delete all Pilot Reports from your device, including draft and completed ones not sent to the server.\",\n title: \"Application Logs Reset\",\n buttons: {\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n },\n danger: {\n label: \"Delete All Pilot Reports\",\n className: \"btn-danger\",\n callback: function callback() {\n DataCleanerFactory.deleteAllReports();\n $route.reload();\n bootbox.alert(\"All Pilot Reports have been successfully deleted.\", function () {});\n }\n }\n }\n });\n }\n /**\r\n * Navigate to Calendar View\r\n * @memberof mainFooter \r\n */\n\n\n function gotoCalendar() {\n SettingsMain.setEditingPage(null); // go to dashboard\n\n $location.path(\"/\");\n }\n /**\r\n * Navigate to Bucket Calendar View\r\n * @memberof flightFooter \r\n */\n\n\n function gotoBucketCalendar() {\n SettingsMain.setEditingPage(null);\n $location.path('/bucket');\n }\n /**\r\n * Navigate to Messages View\r\n * @memberof mainFooter \r\n */\n\n\n function gotoMessageLibrary() {\n $location.path('/messages');\n }\n /**\r\n * Navigate to Memos Library\r\n * @memberof mainFooter \r\n */\n\n\n function gotoMemos() {\n $location.path('/memos');\n }\n /**\r\n * Navigate to leave request View\r\n * @memberof mainFooter \r\n */\n\n\n function gotoLeaveRequests() {\n $location.path('/leaverequest');\n }\n /**\r\n * Navigate to Submit ticket view\r\n * @memberof mainFooter \r\n */\n\n\n function gotoTicket() {\n // go to Submit ticket view\n $location.path(\"/ticket\");\n }\n\n messages = MessageFactory.getMessagesFromStorage();\n messagesCount = messages.length;\n\n for (var i = 0; i < messages.length; i++) {\n if (messages[i].ReadDt == null) {\n unreadMessagesCount++;\n }\n }\n\n MemoFactory.getMemosFromStorage(function (results) {\n var memosCount = 0; //remove memos that belong to \"Training Surveys\" category\n\n for (var i = 0; i < results.length; i++) {\n if (results[i].Category != \"Training Surveys\") {\n memosCount++;\n }\n }\n\n scope.memosCount = memosCount;\n });\n scope.messagesCount = messagesCount;\n scope.unreadMessagesCount = unreadMessagesCount;\n scope.logout = logout;\n scope.resetDevice = resetDevice;\n scope.deleteAllReports = deleteAllReports;\n scope.gotoMessageLibrary = gotoMessageLibrary;\n scope.gotoMemos = gotoMemos;\n scope.memosCount = memosCount;\n scope.gotoCalendar = gotoCalendar;\n scope.gotoBucketCalendar = gotoBucketCalendar;\n scope.gotoTicket = gotoTicket;\n scope.leaveRequestInformation = LeaveRequestFactory.getLeaveRequestInformation();\n scope.gotoLeaveRequests = gotoLeaveRequests;\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/Main/footer.tpl.html\",\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('memosByCategory', memosByCategory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name memosByCategory\r\n * @restrict E\r\n * @description\r\n * Implementation of memosByCategory\r\n * Initialize the panels with memos group by category.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function memosByCategory(MemoFactory, MemoImagesFactory, $uibModal, DataCleanerFactory, GroundDutyFactory, FlightFactory) {\n function link($scope, attrs) {\n $scope.togglePanel = togglePanel;\n var Id = $scope.id;\n /**\r\n * toggle Panel\r\n * @memberof memosByCategory\r\n * @param {number} panelId\r\n */\n\n function togglePanel(panelId) {\n $('#' + panelId).toggle();\n } //Initialize Memos\n\n\n if ($scope.type == \"duty\" || $scope.type == \"d\") {\n MemoFactory.getMemosForCrewRoute(Id, $scope.day, function (results) {\n $scope.memos = filterMemos(results);\n });\n } else if ($scope.type == \"ground\" || $scope.type == \"g\") {\n MemoFactory.getMemosForGroundDuty(Id, function (results) {\n $scope.memos = filterMemos(results);\n });\n } //(attrs.type == \"flight\" || attrs.type == \"f\") default Flight type\n else {\n MemoFactory.getMemosForFlight(Id, function (results) {\n $scope.memos = filterMemos(results);\n });\n }\n /**\r\n * filter memos\r\n * @memberof memosByCategory\r\n * @param {object} data\r\n */\n\n\n function filterMemos(data) {\n //normalize memos\n var distinctMemos = normalizeMemos(data);\n\n if (distinctMemos.length != data.length) {\n MemoFactory.getMemosFromStorage(function (allMemos) {\n var distinctMemosAll = normalizeMemos(allMemos);\n MemoImagesFactory.getMemoImagesFromStorage(function (allMemoImages) {\n var distinctMemoImagesAll = normalizeMemoImages(allMemoImages);\n recreateIndexedDB(distinctMemosAll, allMemoImages);\n });\n });\n }\n\n var memosByCategory = [];\n\n for (var i = 0; i < distinctMemos.length; i++) {\n var memo = distinctMemos[i];\n\n if (!memosByCategory.filter(function (e) {\n return e.Category == memo.Category;\n }).length > 0 && memo.Category != \"None\") {\n memosByCategory.push({\n Category: memo.Category,\n memoList: [memo]\n });\n } else if (memosByCategory.filter(function (e) {\n return e.Category == memo.Category;\n }).length > 0 && memo.Category != \"None\") {\n memosByCategory.filter(function (object) {\n if (object.Category == memo.Category) {\n return object;\n }\n\n ;\n })[0].memoList.push(memo);\n }\n }\n\n return memosByCategory;\n }\n\n function recreateIndexedDB(distinctMemosAll, distinctMemosImagesAll) {\n //delete indexdb\n var q = DataCleanerFactory.deleteIndexedDB();\n q.then(function () {\n MemoFactory.setMemosToStorage(distinctMemosAll);\n MemoImagesFactory.setMemoImagesToStorage(distinctMemosImagesAll); //save normalize data to indexedDB\n\n LogService.debug(\"Recreated IndexedDB\");\n });\n q[\"catch\"](function (ex) {\n console.log(ex);\n });\n }\n\n function normalizeMemos(data) {\n var distinctData = [];\n\n if (data && data.length > 1) {\n var sortData = data.dynamicSort(\"Id\");\n\n for (var i = 0; i < sortData.length - 1; i++) {\n if (sortData[i + 1].Id == sortData[i].Id) {\n //swap rows in list - check lastUpdated property, latest at the end\n if (sortData[i].LastUpdated && sortData[i + 1].LastUpdated) {\n var memoDateA = new Date(sortData[i].LastUpdated);\n var memoDateB = new Date(sortData[i + 1].LastUpdated);\n\n if (memoDateA.getTime() > memoDateB.getTime()) {\n var temp = sortData[i + 1];\n sortData[i + 1] = sortData[i];\n sortData[i] = temp;\n }\n }\n } else {\n distinctData.push(sortData[i]);\n }\n }\n\n distinctData.push(sortData[sortData.length - 1]);\n } else {\n distinctData = data;\n }\n\n return distinctData;\n }\n\n function normalizeMemoImages(data) {\n var distinctData = [];\n\n if (data && data.length > 1) {\n var sortData = data.dynamicSort(\"imageId\");\n\n for (var i = 0; i < sortData.length - 1; i++) {\n if (!(sortData[i + 1].imageId == sortData[i].imageId)) {\n distinctData.push(sortData[i]);\n }\n }\n\n distinctData.push(sortData[sortData.length - 1]);\n } else {\n distinctData = data;\n }\n\n return distinctData;\n }\n\n $scope.openMemo = openMemo;\n /**\r\n * Open modal to see information for the selected Memo\r\n * @memberof memosByCategory\r\n * @param {object} memo A memo object\r\n */\n\n function openMemo(_memo) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Memos/dlgMemo.html',\n controller: 'MemoModalCtrl',\n size: 'lg',\n keyboard: false,\n resolve: {\n memo: function memo() {\n return _memo;\n }\n }\n });\n modalInstance.result.then(function () {\n if (_memo.ReadDt == null) {\n _memo.ReadDt = new Date();\n MemoFactory.saveOneMemoToStorage(_memo);\n\n if ($scope.type == \"ground\") {\n MemoFactory.markGroundDutiesUnread();\n }\n }\n });\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/directives/memosByCategoryPanel.tpl.html\",\n scope: {\n type: '@',\n id: '=',\n day: '='\n },\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('securitySearch', securitySearch);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name securitySearch\r\n * @restrict E\r\n * @description\r\n * Implementation of securitySearch\r\n * Initialize the panel with previous flight info.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function securitySearch(AircaftPositionsFactory, FlightFactory) {\n function link($scope) {\n var showSecurityMsg = false;\n var securitySearchRequired = null;\n var DepartureUK = null;\n var DepartureEU = null;\n var DepartureCDG = null;\n var PreviousEU = null;\n var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId($scope.id);\n var flightInfo = FlightFactory.getFlightFromStorage($scope.id);\n\n if (flightInfo) {\n DepartureUK = flightInfo.DepartureCountry == \"UNITED KINGDOM\";\n DepartureEU = flightInfo.DepartureEU;\n DepartureCDG = flightInfo.Departure == \"CDG\"; // RULE 1: Current Departure Airport is UK\n // RULE 2: Current Departure Airport is Non EU\n // RULE 3: Current Departure Airport is CDG Airport\n\n if (DepartureUK || !DepartureEU || DepartureCDG) {\n securitySearchRequired = true;\n } else {\n securitySearchRequired = false;\n }\n }\n\n if (aircaftPositions) {\n // RULE 4: Previous Origin Airport is Non EU\n PreviousEU = aircaftPositions.PreviousEU;\n\n if (!PreviousEU) {\n securitySearchRequired = true;\n } else {\n securitySearchRequired = false;\n }\n }\n\n if (securitySearchRequired != null) {\n showSecurityMsg = true;\n }\n\n $scope.showSecurityMsg = showSecurityMsg;\n $scope.securitySearchRequired = securitySearchRequired;\n $scope.aircaftPositions = aircaftPositions;\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/directives/securitySearch.tpl.html\",\n scope: {\n id: '='\n },\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('showerrormessage', showerrormessage);\n /**\r\n * @ngdoc directive\r\n * @name showerrormessage\r\n * @restrict EA\r\n * @description\r\n * Implementation of show error message\r\n * @attr {String} message: the error message.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function showerrormessage() {\n function link($scope, element, attrs) {\n $scope.errorMessage = attrs.message;\n $scope.hasMessage = attrs.message != null && attrs.message.length > 0;\n }\n\n return {\n restrict: 'E',\n template: '
{{errorMessage}}
',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('updateConfirm', updateConfirm);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name updateConfirm\r\n * @restrict E\r\n * @description\r\n * Implementation of aircraft differences\r\n *\r\n * Display the confirm textto update service workers version\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function updateConfirm(SWUpdateService) {\n function link($scope, element, attributes) {\n //if serviceWorker registered\n if ($scope.SWRegistration != null) {\n $scope.needUpdate = null;\n $scope.update = update; //get waiting service worker if exists\n\n $scope.needUpdate = $scope.SWRegistration.waiting; //if waiting service woker exists check how long its been waiting\n\n if ($scope.needUpdate != null) {\n SWUpdateService.checkVersionExpiration($scope.SWRegistration);\n }\n }\n\n function update() {\n SWUpdateService.update($scope.SWRegistration);\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/directives/updateConfirm.tpl.html',\n scope: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('AddFlightCtrl', AddFlightCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name AddFlightCtrl\r\n * @description \r\n * Add a new flight that is not in schedule\r\n * @ngInject\r\n */\n\n function AddFlightCtrl($scope, UserFactory, FlightFactory, AircraftTypeFactory, $uibModalInstance, $route) {\n $scope.isSecure = UserFactory.isSecure(); // cancel\n\n $scope.doCancel = doCancel; // add flight\n\n $scope.doAdd = doAdd; // setup datetime pickers\n\n var now = new Date();\n var minSelectableDate = new Date();\n var maxSelectableDate = new Date();\n minSelectableDate.setDate(now.getDate() - 15);\n maxSelectableDate.setDate(now.getDate() + 2);\n $scope.minSelectableDateStr = minSelectableDate.toString('dd-MM-yyyy');\n $scope.maxSelectableDateStr = maxSelectableDate.toString('dd-MM-yyyy');\n $scope.selectedDate = null;\n $scope.selectedTime = null;\n $scope.hstep = 1;\n $scope.mstep = 1;\n $scope.ismeridian = false;\n $scope.dateFormat = 'dd-MM-yyyy';\n $scope.hourFormat = \"HH:mm\";\n $scope.datepicker = {\n opened: false\n };\n $scope.openDatepicker = openDatepicker; // get the values from ui and create a flight\n\n $scope.createFlightFromUIValues = createFlightFromUIValues; // setup aircraft types\n\n var actypes = AircraftTypeFactory.getAircraftTypesFromStorage();\n if (!(actypes instanceof Array)) actypes = [];\n actypes.push({\n Code: 'other'\n });\n $scope.aircraftTypes = actypes; // function to process the form\n\n $scope.processForm = processForm;\n /**\r\n * Add the flight to schedule\r\n * @memberof AddFlightCtrl\r\n */\n\n function doAdd() {\n $scope.processForm();\n }\n /**\r\n * Close the modal\r\n * @memberof AddFlightCtrl\r\n */\n\n\n function doCancel() {\n $uibModalInstance.close('cancel');\n }\n /**\r\n * Open Datepicker\r\n * @memberof AddFlightCtrl\r\n */\n\n\n function openDatepicker() {\n $scope.datepicker.opened = true;\n }\n\n ;\n /**\r\n * Get the values from ui and create a flight \r\n * @memberof AddFlightCtrl\r\n */\n\n function createFlightFromUIValues() {\n // get moment dt from controls\n var flightDate = $scope.formData.flightDateStr;\n var flightSTD = $scope.formData.flightTimeStr; // convert them to dates\n\n flightDate = new Date(flightDate);\n flightSTD = new Date(flightSTD); // combine date and time\n\n flightDate.setHours(flightSTD.getHours(), flightSTD.getMinutes(), 0, 0); // flightDate = flightDate.fromUTC();\n // get other flight details\n\n var flightNumber = $scope.formData.flightNumber;\n var flightDeparture = $scope.formData.flightDeparture;\n var flightDestination = $scope.formData.flightDestination;\n var flightRegNo = $scope.formData.flightRegNo;\n var flightAcType = null;\n if ($scope.formData.flightAcType != null) flightAcType = $scope.formData.flightAcType; // try to create a local flight\n\n var newFlight = FlightFactory.createLocalFlight(flightDate, flightNumber, flightDeparture, flightDestination, flightRegNo, flightAcType);\n return newFlight;\n }\n /**\r\n * Process and validate the form\r\n * @memberof AddFlightCtrl\r\n */\n\n\n function processForm() {\n // if all valid\n if ($scope.formFlight.$valid) {\n try {\n // try to create a local flight\n var newFlight = $scope.createFlightFromUIValues(); // save the local flight\n\n if (newFlight != null) {\n FlightFactory.saveLocalFlight(newFlight);\n }\n\n if (newFlight == null) {\n bootbox.alert(\"

Error

Unable to create a flight record.\");\n } else {\n (function () {\n $uibModalInstance.close();\n $route.reload();\n })();\n }\n } catch (e) {\n bootbox.alert(\"

Error

Unable to create a flight record due to unexpected error:\\n\" + e.message);\n }\n } else {\n bootbox.alert(\"Please fill in all the required fields.\");\n }\n } // initialize form data\n\n\n $scope.formData = {};\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CalendarCtrl', CalendarCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CalendarCtrl\r\n * @description \r\n * View your schedule (flights and ground duties)\r\n * @ngInject\r\n */\n\n function CalendarCtrl($scope, version, $location, MemoFactory, FlightFactory, UserFactory, PilotReportLocalEditFactory, CrewRouteFactory, MessageFactory, UpdateService, DataCleanerFactory, SyncLogFactory, $timeout, $uibModal, GroundDutyFactory, SettingsMain, defaultCalendarDate, AutolandFactory, CrewHotelFactory, TrainingSessionFactory, FlightSessionFactory, ScheduleAcknowledgeFactory) {\n $scope.pendingOverdueReports = 0;\n $scope.draftReports = 0;\n $scope.completedReports = 0;\n $scope.isSecure = UserFactory.isSecure();\n $scope.state = 'calendar';\n\n if (version) {\n $scope.version = version.replace('appVersion_', '');\n } else {\n $scope.version = '';\n } //scope variables\n\n\n var user = UserFactory.getUser();\n $scope.logged_user_info = user.aimsId + ' - ' + user.name;\n $scope.storageUsage = storageUsage; //SetupView\n\n $scope.setupView = setupView; //Pages\n\n $scope.addFlight = addFlight;\n $scope.searchPastGroundDuties = searchPastGroundDuties; //Modals\n\n $scope.openSynch = openSynch;\n $scope.hasUnsetTraining = false;\n var groundSessions = [];\n var flightSessions = [];\n TrainingSessionFactory.getAll(function (savedGroundSessions) {\n FlightSessionFactory.getAll(function (savedFlightSessions) {\n groundSessions = savedGroundSessions;\n flightSessions = savedFlightSessions;\n $scope.setupView(false);\n });\n });\n /**\r\n * Setups Calendar View\r\n * @memberof CalendarCtrl\r\n * @param {boolean} isReload\r\n */\n\n function setupView(isReload) {\n if (!UserFactory.isLoggedIn()) {\n $location.path(\"/login\");\n }\n\n $scope.NeedsToSync = UpdateService.updater();\n /*\t\t\t\t\r\n var reportstobesynched = PilotReportLocalEditFactory.getPilotReportLocalEditThatNeedToBeSynched();\r\n \n $scope.number_of_reports_to_sync = reportstobesynched.length;\r\n */\n\n $scope.number_of_messages = MessageFactory.getMessagesFromStorage().length;\n $scope.number_of_messages_not_readen = MessageFactory.getCountOfUnreadMessages(); //Get count of unread memos but remove the ones that belong in 'Training Surveys' Category\n\n MemoFactory.getUnreadMemos(function (memos) {\n var unreadMemosCount = 0; //remove memos that belong in \"Training Surveys\" category\n\n for (var i = 0; i < memos.length; i++) {\n if (memos[i].Category != \"Training Surveys\") {\n unreadMemosCount++;\n }\n }\n\n $scope.unreadMemosCount = unreadMemosCount;\n }); //Get autoland procedures\n\n var autoland = AutolandFactory.getAutolandFromStorage();\n $scope.autolandCount = 0;\n $scope.flightsLeft = 0;\n\n if (autoland != null) {\n $scope.autolandCount = autoland.autolandCount;\n $scope.flightsLeft = autoland.flightsLeft;\n $scope.hasAEFlights = autoland.totalAEFlights > 0;\n } // read the flights from the local storage and display them\n\n\n var flights = FlightFactory.getFlightsFromStorageAndCheckIfTooOld(); // also load the flights created by the user\n\n flights = FlightFactory.getLocalFlightsAndMergeWithServerFlights(flights); // if no local flights are found then force sync\n\n if (!isReload) {\n needsToSync = true;\n }\n\n var crewRoutes = CrewRouteFactory.getCrewRoutesFromStorage();\n var groundDuties = GroundDutyFactory.getGroundDutiesFromStorage();\n var crewRoutesEvents = formatCrewRoutes(crewRoutes);\n var groundDutiesEvents = formatGroundDuties(groundDuties);\n var flightEvents = formatFlights(flights);\n var events = flightEvents.concat(groundDutiesEvents).concat(crewRoutesEvents);\n var specialDates = findScheduleChangedDates(); // //temporary disable for A3\n // var showInCalendar = CrewHotelFactory.showHotelsInCalendar(flights)\n // if(showInCalendar){\n // \tvar crewHotels = CrewHotelFactory.getCrewHotelsFromStorage();\n // \tvar crewHotelsEvents = formatHotels(crewHotels);\n // \tevents = events.concat(crewHotelsEvents);\n // }\n //Enable again!\n\n var crewHotels = CrewHotelFactory.getCrewHotelsFromStorage();\n var crewHotelsEvents = formatHotels(crewHotels);\n events = events.concat(crewHotelsEvents);\n calendar(events, specialDates);\n var needsToSync = false; // check the last sync date\n\n var lastLog = SyncLogFactory.getSyncLog();\n var canShowSync = true;\n\n if (lastLog == null) {\n needsToSync = true;\n } else {\n canShowSync = lastLog.canShowSync(); //used to avoid showing again and again the dialog :: delay X minutes before showing again\n\n if (lastLog.date == null) needsToSync = true;else if (lastLog.date != null) {\n if (Date.today().add(-1).days().toUTC().isAfter(new Date(lastLog.date).toUTC()) || lastLog.forceSync) {\n if (!isReload) needsToSync = true;\n }\n }\n }\n\n var isOpenUpdateModal = ($(\".modal-updating\").data('bs.modal') || {\n isShown: false\n }).isShown;\n\n if (needsToSync && canShowSync && !isOpenUpdateModal) {\n $scope.openSynch();\n } else {\n MemoFactory.getMandatoryUnreadMemos(function (memos) {\n var mandatoryUnread = 0; //remove memos that belong in \"Training Surveys\" category\n\n for (var i = 0; i < memos.length; i++) {\n if (memos[i].Category != \"Training Surveys\") {\n mandatoryUnread++;\n }\n }\n\n $scope.mandatoryUnread = mandatoryUnread;\n\n if ($scope.mandatoryUnread > 0) {\n openMandatoryModal();\n }\n });\n }\n }\n\n function openMandatoryModal() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Flight/dlgMandatory.html',\n controller: 'MandatoryModalCtrl',\n size: 'md',\n backdrop: 'static',\n keyboard: false,\n resolve: {\n mandatoryUnread: $scope.mandatoryUnread\n }\n });\n }\n /**\r\n * Finds the dates with a change on their schedule\r\n * @memberof CalendarCtrl\r\n * @param {array} events Calendar events (Flights and Ground duties) \r\n * @returm {array} scheduleChangedDates\r\n */\n\n\n function findScheduleChangedDates() {\n var scheduleChangedDates = ScheduleAcknowledgeFactory.getScheduleChangesFromStorage();\n return scheduleChangedDates;\n }\n /**\r\n * Initialize Calendar\r\n * @memberof CalendarCtrl\r\n * @param {array} events Flights and Ground duties \r\n * @param {array} specialDates The Schedule Changed Dates\r\n */\n\n\n function calendar(events, specialDates) {\n $(\"#calendar\").fullCalendar({\n defaultView: getDefaultView(),\n defaultDate: defaultCalendarDate,\n firstDay: 1,\n lang: 'en',\n editable: false,\n draggable: false,\n selectable: false,\n selectHelper: false,\n unselectAuto: false,\n disableResizing: false,\n droppable: false,\n fixedWeekCount: false,\n nextDayThreshold: \"00:00:00\",\n header: {\n left: 'title',\n center: '',\n right: 'month,listMonth today prev,next'\n },\n timeFormat: 'HH:mm',\n displayEventEnd: true,\n events: events,\n eventRender: function eventRender(event, element, icon) {\n if ($('#calendar').fullCalendar('getView').type === 'listMonth') {\n element.find('.fc-list-item-title').addClass('listview-icon');\n $.each(event.className, function (index, icon) {\n element.addClass(event.listViewColor);\n }); // $.each(event.icons, function (index, icon) {\n // element.find('.listview-icon').prepend(\" \");\n // });\n\n if (!event.description == \"\") {\n element.find('.fc-list-item-title').append(\"\" + \" \" + event.description + \"\");\n }\n\n if (!event.icon == \"\") {\n element.find('.fc-list-item-title').append(\"\");\n }\n\n if (!event.second_icon == \"\") {\n element.find('.fc-list-item-title').append(\"\");\n }\n } else {\n if (event.type == \"crewRoute\" || event.type == \"crewHotel\") {\n element.find('.fc-time').remove();\n }\n\n element.find('.fc-title').prepend(\"
\");\n\n if (!event.description == \"\") {\n element.find('.fc-title').append(\"
\" + event.description + \"
\");\n }\n\n if (!event.icon == \"\") {\n element.find('.fc-title').append(\"\");\n }\n\n if (!event.second_icon == \"\") {\n element.find('.fc-title').append(\"\");\n }\n }\n },\n dayRender: function dayRender(date, cell) {\n for (var i = 0; i < specialDates.length; i++) {\n var objdate = new Date(specialDates[i]);\n if (date._d.getFullYear() == objdate.getFullYear() && date._d.getDate() == objdate.getDate() && date._d.getMonth() == objdate.getMonth()) cell.addClass('bg-yellow');\n }\n },\n dayClick: function dayClick(date, jsEvent, view) {},\n eventClick: function eventClick(calEvent, jsEvent, view) {\n if (calEvent.type == \"flight\") {\n $timeout(function () {\n gotoFlightInfo(calEvent._id);\n });\n } else if (calEvent.type == \"groundDuty\") {\n $timeout(function () {\n gotoGroundDutyInfo(calEvent._id);\n });\n } else if (calEvent.type == \"crewRoute\") {\n $timeout(function () {\n gotoCrewRouteInfo(calEvent.dutyNo, calEvent.dutyDay);\n });\n }\n },\n height: 'auto'\n });\n\n function getDefaultView() {\n var calendarStyle = SettingsMain.getCalendarViewStyle();\n\n if (calendarStyle == null) {\n calendarStyle = detectMobile() ? \"listMonth\" : \"month\";\n }\n\n return calendarStyle;\n }\n\n function detectMobile() {\n var isMobile = window.innerWidth <= 800 && window.innerHeight <= 735;\n return isMobile;\n }\n\n $('.fc-listMonth-button').click(function () {\n SettingsMain.setCalendarViewStyle('listMonth');\n });\n $('.fc-month-button').click(function () {\n SettingsMain.setCalendarViewStyle('month');\n });\n }\n /**\r\n * Transform flights in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} flights The Scheduled Flights \r\n * @return {array} events \r\n */\n\n\n function formatFlights(flights) {\n var flightEvents = [];\n\n for (var i = 0; i < flights.length; i++) {\n var description = flights[i].getRoute();\n var title = flights[i].FlightNo;\n\n if (flights[i].TrainingIndicatorCode) {\n title = title + \" \" + flights[i].TrainingIndicatorCode;\n }\n\n var classname = \"\";\n var icon = \"fa-plane\";\n var second_icon = \"\";\n var id = flights[i].FlightId;\n var type = \"flight\";\n var listViewColor = \"\";\n\n if (flights[i].LineStatus === 'na') {\n classname = \"fc-aluminum\";\n listViewColor = \"lv-aluminium\";\n } else if (flights[i].LineStatus === 'pending') {\n classname = \"fc-blue\";\n listViewColor = \"lv-blue\";\n } else if (flights[i].LineStatus === 'pendingoverdue') {\n classname = \"fc-seablue\";\n listViewColor = \"lv-seablue\";\n $scope.pendingOverdueReports++;\n } else if (flights[i].LineStatus === 'draft' || flights[i].LineStatus === 'draftotheruser') {\n classname = \"fc-orange\";\n listViewColor = \"lv-orange\";\n $scope.draftReports++;\n } else if (flights[i].LineStatus === 'completed' || flights[i].LineStatus === 'completedotheruser') {\n classname = \"fc-purple\";\n listViewColor = \"lv-purple\";\n $scope.completedReports++;\n } else if (flights[i].LineStatus === 'stored' || flights[i].LineStatus === 'storedotheruser' || flights[i].LineStatus === 'stored+otheruser' || flights[i].LineStatus === 'synched' || flights[i].LineStatus === 'synchedotheruser') {\n classname = \"fc-green\";\n listViewColor = \"lv-green\";\n }\n\n if (flights[i].IsScheduleChanged && flights[i].LineStatus != 'na') {\n classname = classname + \" text-yellow-important\";\n }\n\n if (flights[i].LineStatus === 'na') icon = \"\";else if (flights[i].LineStatus === 'pending') icon = \"fa-plus\";else if (flights[i].LineStatus === 'pendingoverdue') icon = \"fa-exclamation-triangle text-lemon\";else if (flights[i].LineStatus === 'draft') icon = \"fa-pencil\";else if (flights[i].LineStatus === 'completed') icon = \"fa-check-circle\";else if (flights[i].LineStatus === 'synched') icon = \"fa-check-square-o\";else if (flights[i].LineStatus === 'draftotheruser') icon = \"fa-pencil \";else if (flights[i].LineStatus === 'completedotheruser') icon = \"fa-check-circle \";else if (flights[i].LineStatus === 'synchedotheruser') icon = \"fa-check-square-o\";else if (flights[i].LineStatus === 'stored') icon = \"fa-cloud-download\";else if (flights[i].LineStatus === 'storedotheruser') icon = \"fa-cloud-download\";else if (flights[i].LineStatus === 'stored+otheruser') icon = \"fa-cloud-download\";\n if (flights[i].LineStatus === 'draftotheruser' || flights[i].LineStatus === 'completedotheruser' || flights[i].LineStatus === 'synchedotheruser' || flights[i].LineStatus === 'storedotheruser' || flights[i].LineStatus === 'stored+otheruser') second_icon = \"fa-user\";\n var IsScheduleChanged = flights[i].IsScheduleChanged;\n var ScheduledDeparture = flights[i].ScheduledDeparture;\n\n if (flights[i].ScheduledArrival == null) {\n var ScheduledArrival = ScheduledDeparture;\n } else {\n var ScheduledArrival = flights[i].ScheduledArrival;\n }\n\n var event = {\n _id: id,\n title: title,\n start: ScheduledDeparture,\n end: ScheduledArrival,\n description: description,\n icon: icon,\n second_icon: second_icon,\n className: classname,\n type: type,\n isScheduleChanged: IsScheduleChanged,\n listViewColor: listViewColor\n };\n flightEvents.push(event);\n }\n\n return flightEvents;\n }\n /**\r\n * Transform Ground Duties in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} duties The Scheduled Ground Duties \r\n * @return {array} events \r\n */\n\n\n function formatGroundDuties(duties) {\n var groundEvents = [];\n var now = moment.utc();\n\n for (var i = 0; i < duties.length; i++) {\n //var description = duties[i].DutyDescription +\"
\";\n var description = duties[i].Code;\n var title = duties[i].Title ? duties[i].Title : duties[i].Duty;\n var classname = \"fc-white\";\n var icon = \"\";\n\n if (duties[i].RelatedGroundDuties && duties[i].RelatedGroundDuties.length > 1) {\n icon = \"fa-graduation-cap\"; // icon only if training\n //Get ground courses\n\n var courseStatuses = [];\n var coursesFlat = [];\n\n for (var j = 0; j < duties[i].RelatedGroundDuties.length; j++) {\n var relatedDutyCourse = duties[i].RelatedGroundDuties[j].Courses;\n\n if (relatedDutyCourse) {\n coursesFlat = coursesFlat.concat(relatedDutyCourse);\n }\n }\n\n coursesFlat.forEach(function (x) {\n courseStatuses.push(x.Status);\n });\n /*Statuses\r\n \tCompleted : session has been sent\r\n \tOutdated :\tsession submission is overdue\r\n \tDraft\t : session completion has started but not submitted\r\n \tPending : session submission not yet due\r\n */\n\n if (courseStatuses.includes(\"Pending\")) {\n //Pending\n classname = \"fc-blue-inverted\"; //Outdated\n\n var dutyEnd = moment.utc(duties[i].DutyEnd);\n var duration = moment.duration(now.diff(dutyEnd)).asHours();\n\n if (duration > 1) {\n if (courseStatuses.includes(\"Pending\")) $scope.hasUnsetTraining = true;\n classname = \"fc-seablue-inverted\";\n icon = \"fa-exclamation-triangle text-yellow\";\n } //Draft\n\n\n var courseId = coursesFlat[0].CourseId; // each duty should contain ONLY ONE COURSE\n\n var duty = duties[i];\n\n if (groundSessions && groundSessions.length) {\n var existingSession = groundSessions.find(function (s) {\n return s.courseId == courseId && s.day == duty.DutyDateS && s.dutyId == duty.Id;\n });\n\n if (existingSession && !existingSession.HasLimitedInfo && existingSession.trainees && existingSession.trainees.length) {\n //a training session with trainees exists\n classname = \"fc-orange-inverted\";\n icon = \"fa-graduation-cap\";\n }\n }\n } else if (courseStatuses.includes(\"Completed\")) {\n //Completed\n classname = \"fc-green-inverted \";\n }\n }\n\n var second_icon = \"\";\n\n if (duties[i].Unread) {\n second_icon = \"fa-envelope text-orange\";\n }\n\n var id = duties[i].Id;\n var type = \"groundDuty\";\n var start = duties[i].DutyBegin ? duties[i].DutyBegin : duties[i].DutyDateS ? duties[i].DutyDateS : duties[i].DutyDate;\n var end = duties[i].DutyEnd;\n var listViewColor = \"lv-white\";\n var event = {\n _id: id,\n title: title,\n start: start,\n end: end,\n description: description,\n icon: icon,\n second_icon: second_icon,\n className: classname,\n type: type,\n listViewColor: listViewColor\n };\n groundEvents.push(event);\n }\n\n return groundEvents;\n }\n /**\r\n * Transform Crew Routes in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} routes The Scheduled Crew Routes \r\n * @return {array} events \r\n */\n\n\n function formatCrewRoutes(routes) {\n var crewRouteEvents = [];\n var now = moment.utc();\n\n for (var i = 0; i < routes.length; i++) {\n var description = routes[i].Route; // var title = (duties[i].Title)? duties[i].Title : duties[i].Duty;\n\n var classname = \"fc-white\";\n var icon = \"\";\n var second_icon = \"\"; //Get ground courses\n\n var courseStatuses = [];\n var courses = routes[i].Courses;\n\n if (courses) {\n courses.forEach(function (x) {\n courseStatuses.push(x.Status);\n });\n }\n /*Statuses\r\n \tCompleted : session has been sent\r\n \tOutdated :\tsession submission is overdue\r\n \tDraft\t : session completion has started but not submitted\r\n \tPending : session submission not yet due\r\n */\n\n\n var trainingStatus = \"\";\n\n if (courseStatuses.includes(\"Pending\")) {\n //Pending\n trainingStatus = \"Pending\"; //Outdated\n\n var dutyEnd = moment.utc(routes[i].DutyEnd);\n var duration = moment.duration(now.diff(dutyEnd)).asHours();\n\n if (duration > 1) {\n if (courseStatuses.includes(\"Pending\")) $scope.hasUnsetTraining = true;\n trainingStatus = \"Outdated\";\n } //Draft\n\n\n var courseIds = courses.map(function (x) {\n return x.CourseId;\n });\n var route = routes[i];\n\n if (flightSessions && flightSessions.length) {\n //TODO msis fix\n var dutyBegin = new moment(route.DutyBegin).format(\"YYYY-MM-DD\");\n var dutyEnd = new moment(route.DutyEnd).format(\"YYYY-MM-DD\");\n var existingSessions = flightSessions.filter(function (s) {\n return courseIds.includes(s.courseId) && (new moment(s.day).isSame(dutyBegin) || new moment(s.day).isSame(dutyEnd) || new moment(s.day).isBetween(dutyBegin, dutyEnd)) && s.dutyDay == route.DutyDay && s.dutyNo == route.DutyNo;\n });\n\n if (existingSessions && existingSessions.some(function (x) {\n return !x.HasLimitedInfo && x.trainees && x.trainees.length;\n })) {\n //a training session with trainees exists\n trainingStatus = \"Draft\";\n }\n }\n } else if (courseStatuses.includes(\"Completed\")) {\n //Completed\n trainingStatus = \"Completed\";\n classname = \"fc-green-inverted \";\n }\n\n if (trainingStatus == \"Outdated\") {\n second_icon = \"fa-exclamation-triangle text-yellow second-icon-training\";\n classname = \"fc-seablue-inverted\";\n } else if (trainingStatus == \"Draft\") {\n classname = \"fc-orange-inverted\";\n } else if (trainingStatus == \"Pending\") {\n classname = \"fc-blue-inverted\";\n } else if (trainingStatus == \"Completed\") {\n classname = \"fc-green-inverted\";\n }\n\n if (courses && courses.length) {\n icon = \"fa-graduation-cap\";\n } // var id = routes[i].Id;\n\n\n var type = \"crewRoute\";\n var dutyNo = routes[i].DutyNo;\n var dutyDay = routes[i].DutyDay;\n var start = routes[i].DutyBegin ? routes[i].DutyBegin : routes[i].DutyDateS ? routes[i].DutyDateS : routes[i].DutyDate;\n var end = routes[i].DutyEnd;\n var listViewColor = \"lv-white\";\n var event = {\n // _id:id,\n // title: title,\n dutyNo: dutyNo,\n dutyDay: dutyDay,\n start: start,\n end: end,\n description: description,\n icon: icon,\n second_icon: second_icon,\n className: classname,\n type: type,\n listViewColor: listViewColor\n };\n crewRouteEvents.push(event);\n }\n\n return crewRouteEvents;\n }\n /**\r\n * Transform Crew Hotels in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} crew hotels \r\n * @return {array} events \r\n */\n\n\n function formatHotels(hotels, flights, groundDuties) {\n var crewRouteEvents = [];\n\n for (var i = 0; i < hotels.length; i++) {\n var title = hotels[i].HotelName;\n var classname = \"fc-gray-inverted\";\n var icon = \"fa-bed\";\n var second_icon = \"\";\n var type = \"crewHotel\";\n var start = moment(hotels[i].DutyDate).endOf('day').toJSON();\n var listViewColor = \"lv-white\";\n var event = {\n title: title,\n start: start,\n end: start,\n icon: icon,\n second_icon: second_icon,\n className: classname,\n type: type,\n listViewColor: listViewColor\n };\n crewRouteEvents.push(event);\n }\n\n return crewRouteEvents;\n } //Modal functions\n\n /**\r\n * Open Synch Modal\r\n * @memberof CalendarCtrl\r\n */\n\n\n function openSynch() {\n //store last time the sync dialog was displayed\n SyncLogFactory.setLastShow();\n openSynchModal();\n }\n\n function openSynchModal() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgSynch.html',\n controller: 'SynchCtrl',\n size: 'lg',\n backdrop: 'static',\n keyboard: false\n });\n modalInstance.result.then(function (synchresult) {\n //refresh the view after a successful sync\n if (!synchresult == 'cancel') {\n $scope.setupView(true);\n }\n }, function () {});\n }\n /**\r\n * Open the \"Add a flight\" Modal\r\n * @memberof CalendarCtrl\r\n */\n\n\n function addFlight() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgAddFlight.html',\n controller: 'AddFlightCtrl',\n size: 'lg',\n backdrop: 'static',\n keyboard: false\n });\n }\n /**\r\n * Open the \"Search Ground Duties\" Modal\r\n * @memberof CalendarCtrl\r\n */\n\n\n function searchPastGroundDuties() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgSearchGroundDuties.html',\n controller: 'SearchPastGDCtrl',\n size: 'md',\n backdrop: 'static',\n keyboard: false\n });\n }\n /**\r\n * Redirect to flight Info\r\n * @memberof CalendarCtrl\r\n */\n\n\n function gotoFlightInfo(FlightId) {\n $location.path('/flightinfo/' + FlightId);\n }\n /**\r\n * Redirect to groundDuty Info\r\n * @memberof CalendarCtrl\r\n */\n\n\n function gotoGroundDutyInfo(GroundDutyId) {\n $location.path('/groundDuty/' + GroundDutyId);\n }\n /**\r\n * Redirect to crewRoute Info\r\n * @memberof CalendarCtrl\r\n */\n\n\n function gotoCrewRouteInfo(dutyNo, dutyDay) {\n $location.path('/crewRoute/' + dutyNo + '/' + dutyDay);\n }\n /**\r\n * Calculates the local storage Usage\r\n * @memberof CalendarCtrl\r\n * @return {string} usage\r\n */\n\n\n function storageUsage() {\n var usage = localStorageMD5Service.usedSize();\n return usage;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('FlightFactory', FlightFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightFactory\r\n * @description \r\n * Add, Update, Delete and Get Flights \r\n * @ngInject\r\n */\n\n function FlightFactory($log, localStorageMD5Service, UserFactory, PilotReportLocalEditFactory, ServerPilotReportFactory, ServerCabinReportFactory, apiUrl, FlightCrewMemberFactory, MessageFactory, liveVersion, GenericService, SyncLogFactory) {\n var daysThatAFlightIsConsideredTooOld = -20;\n /**\r\n * Initialize the Flight\r\n * @memberof FlightFactory\r\n */\n\n function Flight() {\n this.AcTailNo = null;\n this.AcType = null;\n this.Category = null;\n this.CrewAimsId = null;\n this.Departure = null;\n this.Arrival = null;\n this.FlightAimsId = null;\n this.FlightId = null;\n this.FlightDate = null;\n this.FlightNo = null;\n this.IsDHC = null;\n this.Position = null;\n this.ScheduledDeparture = null;\n this.Status = null;\n this.LineStatus = null;\n this.LineStatusDescr = null;\n this.LocalReportId = null;\n this.ServerReportLink = null;\n this.ScheduledDepartureDateUTC = null;\n this.ScheduledDepartureTimeUTC = null;\n this.LocalReportHasNothingToReport = false;\n this.ServerReportHasNothingToReport = false;\n this.CabinReportId = null;\n this.IsLocal = false;\n this.pilotReports = [];\n this.cabinReports = [];\n this.pilotReportStatusDescr = ''; //v1.1 added pax and dep/arr details\n\n this.BookedC = null;\n this.BookedY = null;\n this.BookedInf = null;\n this.BookedPad = null;\n this.BookedChld = null;\n this.ActualC = null;\n this.ActualY = null;\n this.ActualInf = null;\n this.ActualPad = null;\n this.ActualChld = null;\n this.DepartureICAO = null;\n this.DepartureCountry = null;\n this.DepartureName = null;\n this.ArrivalICAO = null;\n this.ArrivalCountry = null;\n this.ArrivalName = null;\n this.crew = []; //new fields \n\n this.DepartureGate = null;\n this.DepartureTimezone = null;\n this.ArrivalTimezone = null;\n this.CallSign = null;\n this.ScheduledArrival = null;\n this.messages = [];\n this.FlightsFilters = [];\n this.ETA = null;\n this.IsScheduleChanged = false;\n this.Zones = [];\n this.GetId = GetId;\n this.getRoute = getRoute;\n this.getDescription = getDescription;\n this.initialize = initialize;\n this.initializePilotReportStatus = initializePilotReportStatus;\n this.getPilotReportStatusDescr = getPilotReportStatusDescr;\n this.updateFlightFromReport = updateFlightFromReport;\n this.getServerPilotReportForUser = getServerPilotReportForUser;\n this.getServerPilotReportsByAnotherUser = getServerPilotReportsByAnotherUser;\n this.getServerPilotReportForUser = getServerPilotReportForUser;\n }\n\n var service = {\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n getFlightsFromStorage: getFlightsFromStorage,\n getFlightsFromStorageAndCheckIfTooOld: getFlightsFromStorageAndCheckIfTooOld,\n setFlightsToStorage: setFlightsToStorage,\n storeFlightsWithReportsAndMessages: storeFlightsWithReportsAndMessages,\n clearFlightsFromStorage: clearFlightsFromStorage,\n getFlightFromStorage: getFlightFromStorage,\n createLocalFlight: createLocalFlight,\n saveLocalFlight: saveLocalFlight,\n getLocalFlightsAndMergeWithServerFlights: getLocalFlightsAndMergeWithServerFlights,\n getLocalFlightFromStorage: getLocalFlightFromStorage,\n markScheduleChangedFlights: markScheduleChangedFlights,\n getServerPilotReportForUser: getServerPilotReportForUser,\n getServerPilotReportsByAnotherUser: getServerPilotReportsByAnotherUser,\n updateFlightFromReport: updateFlightFromReport,\n initializeFlights: initializeFlights,\n updateFlight: updateFlight,\n mergeFlightInfo: mergeFlightInfo,\n getFlightsByRoute: getFlightsByRoute,\n getFlightFromTotalFlights: getFlightFromTotalFlights,\n getFlightsByDutyNo: getFlightsByDutyNo,\n getFlightsByFlightId: getFlightsByFlightId,\n getCabinReportId: getCabinReportId\n };\n\n function initializeFlights() {\n var objList = localStorageMD5Service.get(objType);\n if (objList == null) return null;\n var arrayLength = objList.length;\n var flights = new Array();\n\n for (var i = 0; i < arrayLength; i++) {\n var flight = new Flight();\n angular.extend(flight, objList[i]);\n if (objList[i].crew == null) objList[i].crew = [];\n flight.crew = new Array();\n\n for (var j = 0; j < objList[i].crew.length; j++) {\n flight.crew.push(FlightCrewMemberFactory.fromObject(objList[i].crew[j]));\n }\n\n flight.initialize();\n flights.push(flight);\n }\n\n localStorageMD5Service.set('flights', flights);\n }\n\n function updateFlight(flight) {\n // get the flights array from storage\n var flights = getFlightsFromStorage(); // find the current flight in the array (if present)\n\n var arrayLength = flights.length;\n var flightIndex = -1;\n\n for (var i = 0; i < arrayLength; i++) {\n if (flights[i].FlightId != null && flights[i].FlightId == flight.FlightId) {\n flightIndex = i;\n break;\n }\n } //Add or update a copy of the current report\n\n\n if (flightIndex >= 0) flights[flightIndex] = flight;else flights.push(flight); //Save\n\n localStorageMD5Service.set('flights', flights);\n }\n\n function updateFlightFromReport(report) {\n var flight = getFlightFromStorage(report.FlightId);\n\n if (flight != null && flight != undefined) {\n flight.AcTailNo = report.AcTailNo;\n flight.AcType = report.AcType;\n var allflights = getFlightsFromStorage();\n\n for (var i = 0; i < allflights.length; i++) {\n if (allflights[i].FlightId != null && allflights[i].FlightId == report.FlightId) {\n var reportIndex = i;\n break;\n }\n }\n\n flight.initialize();\n allflights[reportIndex] = flight;\n setFlightsToStorage(allflights);\n }\n }\n\n function getServerPilotReportForUser(userAimsId) {\n if (this.pilotReports == null) return null;\n var result = null;\n\n for (var i = 0; i < this.pilotReports.length; i++) {\n if (this.pilotReports[i] != null) {\n if (this.pilotReports[i].AuthorAimsId == userAimsId) {\n result = this.pilotReports[i];\n break;\n }\n }\n }\n\n return result;\n }\n\n function getServerPilotReportsByAnotherUser(userAimsId) {\n if (this.pilotReports == null) return [];\n var result = [];\n\n for (var i = 0; i < this.pilotReports.length; i++) {\n if (this.pilotReports[i] != null) {\n if (this.pilotReports[i].AuthorAimsId != userAimsId) {\n result.push(this.pilotReports[i]);\n }\n }\n }\n\n return result;\n }\n\n var objType = 'flights';\n var objCallback = Flight;\n /**\r\n * Overide default get Id\r\n * @memberof FlightFactory\r\n * @returns {number} Id \r\n */\n\n function GetId() {\n return this.FlightId;\n }\n /**\r\n * Get flight's Route\r\n * @memberof FlightFactory\r\n * @returns {string} route \r\n */\n\n\n function getRoute() {\n if (this.Departure == null && this.Arrival == null) return '-null-';else return (this.Departure || '?') + '-' + (this.Arrival || '?');\n }\n /**\r\n * Get flight's description\r\n * @memberof FlightFactory\r\n * @returns {string} description \r\n */\n\n\n function getDescription() {\n if (this.FlightNo == null && this.Departure == null && this.Arrival == null) return '-null-';else return (this.ScheduledDepartureDateUTC || '?') + ' ' + (this.FlightNo || '?') + ' ' + (this.Departure || '?') + '-' + (this.Arrival || '?');\n }\n /**\r\n * Initialize Pilot Report\r\n * @memberof FlightFactory\r\n */\n\n\n function initialize() {\n try {\n // SD date/time\n if (this.ScheduledDeparture != null) {\n var STD = this.ScheduledDeparture;\n if (STD.indexOf('Z') < 0) STD += 'Z';\n STD = new moment(STD);\n STD = new Date(STD);\n STD = STD.toUTC();\n this.ScheduledDepartureDateUTC = STD.toString('yyyy-MM-dd');\n this.ScheduledDepartureTimeUTC = STD.toString('HH:mm');\n } // load the user\n\n\n var user = UserFactory.getUser(); // check if there is a cabin report or a server report for this flight\n\n if (this.cabinReports.length > 0) {\n var token = '';\n\n if (user != null) {\n token = user.token;\n token = encodeURIComponent(token);\n }\n\n this.CabinReportId = this.cabinReports[0].ReportId;\n } else this.CabinReportId = null; // initialize the pilot report status field\n\n\n this.initializePilotReportStatus(user); // initialize css classes for display\n\n this.pilotReportStatusDescr = this.getPilotReportStatusDescr();\n } catch (ex) {\n $log.error(\"initialize failed: \" + ex.message);\n }\n }\n /**\r\n * Initialize Pilot report Status\r\n * @memberof FlightFactory\r\n * @param {object} user \r\n */\n\n\n function initializePilotReportStatus(user) {\n // check that the user is a CP\n if (user == null || this.IsDHC != 0 || this.Position != 'CP') {\n this.LineStatus = \"na\";\n return;\n } // initialize to pending\n\n\n this.LineStatus = \"pending\"; // check if there is a local edit report or a server report for this\n // flight\n\n var serverReportForThisUser = this.getServerPilotReportForUser(user.aimsId);\n var serverReportsByAnotherUser = this.getServerPilotReportsByAnotherUser(user.aimsId);\n var hasServerReportForThisUser = serverReportForThisUser != null;\n var hasServerReportsByAnotherUser = serverReportsByAnotherUser.length > 0;\n var localReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(this.FlightId);\n this.LocalReportId = null;\n this.ServerReportLink = null; // if there is a local copy of the report\n\n if (localReport != null) {\n this.LocalReportId = localReport.ReportGuid;\n this.LocalReportHasNothingToReport = localReport.NothingToReport;\n\n if (localReport.Status === 'draft') {\n if (hasServerReportsByAnotherUser) this.LineStatus = \"draftotheruser\";else this.LineStatus = \"draft\";\n } else if (localReport.Status === 'completed') {\n if (hasServerReportsByAnotherUser) this.LineStatus = \"completedotheruser\";else this.LineStatus = \"completed\";\n } else if (localReport.Status === 'synched') {\n if (hasServerReportsByAnotherUser) this.LineStatus = \"synchedotheruser\";else this.LineStatus = \"synched\";\n } else {\n if (hasServerReportsByAnotherUser) this.LineStatus = \"draftotheruser\";else this.LineStatus = \"draft\";\n }\n } else {\n // if there is a server report by this and by another user\n if (hasServerReportForThisUser && hasServerReportsByAnotherUser) {\n this.LineStatus = \"stored+otheruser\"; // Something if this or any other user has something to\n // report\n\n this.ServerReportHasNothingToReport = serverReportForThisUser.ReportedItems == 0;\n\n if (this.ServerReportHasNothingToReport) {\n // if nothing to report by this user, check if any other\n // user has something to report\n for (var i = 0; i < serverReportsByAnotherUser.length; i++) {\n if (serverReportsByAnotherUser[i].ReportedItems > 0) {\n this.ServerReportHasNothingToReport = false;\n break;\n }\n }\n }\n } // if there is a server report for another user\n else if (hasServerReportsByAnotherUser) {\n this.LineStatus = \"storedotheruser\";\n this.ServerReportHasNothingToReport = true;\n\n for (var i = 0; i < serverReportsByAnotherUser.length; i++) {\n if (serverReportsByAnotherUser[i].ReportedItems > 0) {\n this.ServerReportHasNothingToReport = false;\n break;\n }\n }\n } // if there is a server report for only this user\n else if (hasServerReportForThisUser) {\n this.LineStatus = \"stored\";\n this.ServerReportHasNothingToReport = serverReportForThisUser.ReportedItems == 0;\n } // no server report\n else {\n this.LocalReportId = \"new\"; // no server report found for this user, status is pending\n\n if (new Date(this.ScheduledDeparture) < new Date()) {\n this.LineStatus = \"pendingoverdue\";\n } else {\n this.LineStatus = \"pending\";\n }\n }\n }\n }\n /**\r\n * Get Pilot Report Status Descr\r\n * @memberof FlightFactory\r\n * @returns {string} description \r\n */\n\n\n function getPilotReportStatusDescr() {\n if (this.LineStatus === 'na') return \"n/a\";else if (this.LineStatus === 'pending') return \"Pending\";else if (this.LineStatus === 'pendingoverdue') return \"Pending\";else if (this.LineStatus === 'draft') return \"Draft\";else if (this.LineStatus === 'completed') return \"Completed\";else if (this.LineStatus === 'synched') return \"Synched\";else if (this.LineStatus === 'draftotheruser') return \"Draft +\";else if (this.LineStatus === 'completedotheruser') return \"Completed +\";else if (this.LineStatus === 'synchedotheruser') return \"Synched +\";else if (this.LineStatus === 'stored') return \"Stored\";else if (this.LineStatus === 'storedotheruser') return \"Stored\";else if (this.LineStatus === 'stored+otheruser') return \"Stored +\";else return this.LineStatus;\n }\n /**\r\n * Get Server PilotReport For the selected User\r\n * @memberof FlightFactory\r\n * @param {number} userAimsId The user aims Id\r\n * @return {object} pilotReport \r\n */\n\n\n function getServerPilotReportForUser(userAimsId) {\n if (this.pilotReports == null) return null;\n var result = null;\n\n for (var i = 0; i < this.pilotReports.length; i++) {\n if (this.pilotReports[i] != null) {\n if (this.pilotReports[i].AuthorAimsId == userAimsId) {\n result = this.pilotReports[i];\n break;\n }\n }\n }\n\n return result;\n }\n /**\r\n * Get Server pilotReport For others than the selected User\r\n * @memberof FlightFactory\r\n * @param {number} userAimsId The user aims Id\r\n * @return {object} pilotReport \r\n */\n\n\n function getServerPilotReportsByAnotherUser(userAimsId) {\n if (this.pilotReports == null) return new Array();\n var result = new Array();\n\n for (var i = 0; i < this.pilotReports.length; i++) {\n if (this.pilotReports[i] != null) {\n if (this.pilotReports[i].AuthorAimsId != userAimsId) {\n result.push(this.pilotReports[i]);\n }\n }\n }\n\n return result;\n } //Factory Functions\n\n /**\r\n * Get Flight from local and storage flights\r\n * @memberof FlightFactory\r\n * @param {number} flightId \r\n * @return {object} flight\r\n */\n\n\n function getFlightFromTotalFlights(flightId) {\n var flight = getFlightFromStorage(flightId);\n\n if (!flight) {\n flight = getLocalFlightFromStorage(flightId);\n }\n\n return flight;\n }\n /**\r\n * Get Flight from local and storage flights\r\n * @memberof FlightFactory\r\n * @param {number} flightId \r\n * @return {object} flight\r\n */\n\n\n function getFlightsByRoute(Route, DutyDate) {\n var flights = getFlightsFromStorage();\n if (flights == null) return [];\n var result = [];\n var arrayLength = flights.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (flights[i].Route == Route && flights[i].DutyDate == DutyDate) {\n result.push(flights[i]);\n }\n }\n\n return result;\n }\n /**\r\n * Extend Object from the default Flight Object\r\n * @memberof FlightFactory\r\n * @param {Object} obj a Flight\r\n * @returns {Object} Flight\r\n */\n\n\n function fromObject(obj) {\n if (obj == null) return null;\n var flight = new Flight();\n angular.extend(flight, obj); //handle crew members\n\n if (obj.crew == null) obj.crew = [];\n flight.crew = FlightCrewMemberFactory.fromObjectList(obj.crew);\n return flight;\n }\n\n ;\n /**\r\n * Extend an array of Objects from the default flight Object\r\n * @memberof FlightFactory\r\n * @param {Array} objList an Array Of flights\r\n * @returns {Array} flights\r\n */\n\n function fromObjectList(objList) {\n if (objList == null) return [];\n var arrayLength = objList.length;\n var flights = new Array();\n\n for (var i = 0; i < arrayLength; i++) {\n var flight = new Flight();\n angular.extend(flight, objList[i]); //handle crew members\n\n if (objList[i].crew == null) objList[i].crew = [];\n flights.push(flight);\n }\n\n return flights;\n }\n\n ;\n /**\r\n * Returns all the flights from storage\r\n * @memberof FlightFactory\r\n * @returns {Array} flights\r\n */\n\n function getFlightsFromStorage() {\n var objects = localStorageMD5Service.get('flights');\n return fromObjectList(objects);\n }\n /**\r\n * Returns the flights from local storage only if they are recent\r\n * @memberof FlightFactory\r\n * @returns {Array} flights\r\n */\n\n\n function getFlightsFromStorageAndCheckIfTooOld() {\n var result = getFlightsFromStorage();\n if (result == null) return null;\n var dataIsRecent = false;\n var arrayLength = result.length; // loop all flights and break if a flight in the last 10 days is found\n\n for (var i = 0; i < arrayLength; i++) {\n if (Date.today().add(daysThatAFlightIsConsideredTooOld).days().toUTC().isBefore(new Date(result[i].ScheduledDeparture).toUTC().trimTime())) {\n dataIsRecent = true;\n break;\n }\n }\n\n if (dataIsRecent == true || !liveVersion) return result;else return null;\n }\n /**\r\n * Set flights to storage\r\n * @memberof FlightFactory\r\n * @returns {Array} flights\r\n */\n\n\n function setFlightsToStorage(flights) {\n for (var i = 0; i < flights.length; i++) {\n if (flights[i].FlightId == undefined || flights[i].FlightId == null) {\n flights[i].FlightId = guid();\n }\n }\n\n localStorageMD5Service.set('flights', flights);\n }\n /**\r\n * Store Flights With Reports And Messages\r\n * @memberof FlightFactory\r\n * @param {Array} flights \r\n * @param {Array} pilotReports\r\n * @param {Array} messages\r\n */\n\n\n function storeFlightsWithReportsAndMessages(flights, pilotReports, cabinReports, messages) {\n var flightsX = fromObjectList(flights);\n var pilotReportsX = ServerPilotReportFactory.fromObjectList(pilotReports);\n var cabinReportsX = ServerCabinReportFactory.fromObjectList(cabinReports);\n var messagesX = MessageFactory.fromObjectList(messages);\n\n if (flightsX && flightsX instanceof Array && flightsX.length > 0 && (pilotReportsX && cabinReportsX || messagesX)) {\n // loop all flights\n var user = UserFactory.getUser();\n var f, pr, cr, me;\n\n for (var fi = 0; fi < flightsX.length; fi++) {\n f = flightsX[fi]; // find pilot reports for this flight\n\n f.pilotReports = [];\n f.cabinReports = [];\n\n if (pilotReportsX && pilotReportsX instanceof Array && pilotReportsX.length > 0) {\n for (var pri = 0; pri < pilotReportsX.length; pri++) {\n pr = pilotReportsX[pri];\n\n if (pr.FlightId != null && pr.FlightId == f.FlightId || pr.FlightAimsId != null && pr.FlightAimsId == f.FlightAimsId) {\n if (pr.AuthorAimsId == f.CrewAimsId) {\n pr.Source = ServerPilotReportFactory.constSourceStoredOwn;\n f.pilotReports.push(pr);\n } else {\n pr.Source = ServerPilotReportFactory.constSourceStoredOther;\n f.pilotReports.push(pr);\n }\n }\n }\n } // find cabin reports for this flight\n\n\n if (cabinReportsX && cabinReportsX instanceof Array && cabinReportsX.length > 0) {\n for (var cri = 0; cri < cabinReportsX.length; cri++) {\n cr = cabinReportsX[cri];\n\n if (cr.FlightId != null && cr.FlightId == f.FlightId || cr.FlightAimsId != null && cr.FlightAimsId == f.FlightAimsId) {\n f.cabinReports.push(cr);\n }\n }\n }\n\n if (messagesX && messagesX instanceof Array && messagesX.length > 0) {\n for (var mi = 0; mi < messagesX.length; mi++) {\n me = messagesX[mi];\n\n if (me.QueryType.trim() == 'Country' && (me.Country.trim() == f.ArrivalCountry || me.Country.trim() == f.DepartureCountry)) {\n f.messages.push(me.Id);\n } else if (me.QueryType.trim() == 'FlightNo' && me.FlightNo == f.FlightNo) {\n f.messages.push(me.Id);\n } else if (me.QueryType.trim() == 'Airports') {\n if (me.FlightDirection == 'DEP' && me.AirportA == f.Departure && me.AirportB == f.Arrival) {\n f.messages.push(me.Id);\n } else if (me.FlightDirection == 'ARR' && me.AirportB == f.Departure && me.AirportA == f.Arrival) {\n f.messages.push(me.Id);\n } else if (me.FlightDirection == 'ANY' && (me.AirportA == f.Departure && me.AirportB == f.Arrival || me.AirportB == f.Departure && me.AirportA == f.Arrival)) {\n f.messages.push(me.Id);\n }\n } else if (me.QueryType.trim() == 'Airport') {\n if (me.FlightDirection == 'DEP' && me.AirportA == f.Departure) {\n f.messages.push(me.Id);\n } else if (me.FlightDirection == 'ARR' && me.AirportA == f.Arrival) {\n f.messages.push(me.Id);\n } else if (me.FlightDirection == 'ANY' && (me.AirportA == f.Departure || me.AirportA == f.Arrival)) {\n f.messages.push(me.Id);\n }\n } else if (me.QueryType.trim() == 'Registration' && f.AcTailNo == me.Registration) {\n f.messages.push(me.Id);\n } else if (me.QueryType.trim() == 'AcType' && f.AcType == me.AcType) {\n f.messages.push(me.Id);\n }\n }\n }\n\n f.initialize();\n }\n }\n\n localStorageMD5Service.set('flights', flightsX);\n }\n /**\r\n * Remove the flights of the storage\r\n * @memberof FlightFactory\r\n */\n\n\n function clearFlightsFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get Flight from storage flights\r\n * @memberof FlightFactory\r\n * @param {number} flightId \r\n * @return {object} flight\r\n */\n\n\n function getFlightFromStorage(flightId) {\n var objects = getFlightsFromStorage();\n if (objects == null) return null;\n var result = null;\n var arrayLength = objects.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (objects[i].GetId() == flightId) {\n result = objects[i];\n break;\n }\n }\n\n return result;\n }\n /**\r\n * create a local flight (Add flight button on main screen)\r\n * @memberof FlightFactory\r\n * @param {string} datetime \r\n * @param {string} number \r\n * @param {string} departure \r\n * @param {string} destination \r\n * @param {string} regno \r\n * @param {string} actype \r\n * @return {object} flight\r\n */\n\n\n function createLocalFlight(datetime, number, departure, destination, regno, actype) {\n var user = UserFactory.getUser();\n if (user == null) return null;\n var result = new Flight();\n result.AcTailNo = regno;\n result.AcType = actype;\n result.Category = '-';\n result.CrewAimsId = user.aimsId;\n result.Departure = departure;\n result.Arrival = destination;\n result.FlightAimsId = guid();\n result.FlightId = guid();\n result.FlightDate = datetime.toString('yyyy-MM-dd') + 'T' + datetime.toString('HH:mm:ss');\n ;\n result.FlightNo = number;\n result.IsDHC = 0;\n result.Position = user.position;\n result.ScheduledDeparture = datetime.toString('yyyy-MM-dd') + 'T' + datetime.toString('HH:mm:ss');\n result.Status = 'OK';\n result.IsLocal = true;\n result.initialize();\n return result;\n }\n /**\r\n * Save a local flight\r\n * @memberof FlightFactory\r\n * @param {object} flight\r\n */\n\n\n function saveLocalFlight(flight) {\n // get the local flights array from storage\n var localFlights = fromObjectList(localStorageMD5Service.get('localFlights'));\n if (localFlights == null) localFlights = new Array(); // find the current flight in the array (if present)\n\n var arrayLength = localFlights.length;\n var flightIndex = -1;\n\n for (var i = 0; i < arrayLength; i++) {\n if (localFlights[i].FlightId == flight.FlightId) {\n flightIndex = i;\n break;\n }\n } // add or update a copy of the current report\n\n\n if (flightIndex >= 0) localFlights[flightIndex] = flight;else localFlights.push(flight); // save\n\n localStorageMD5Service.set('localFlights', localFlights);\n }\n /**\r\n * Save a local flight\r\n * @memberof FlightFactory\r\n * @param {object} flight\r\n */\n\n\n function getLocalFlightsAndMergeWithServerFlights(serverFlights) {\n if (serverFlights == null) serverFlights = new Array(); // get the local flights array from storage\n\n var localFlights = fromObjectList(localStorageMD5Service.get('localFlights'));\n if (localFlights == null) localFlights = new Array(); // add the local flight to the given array\n\n var arrayLength = localFlights.length;\n\n for (var i = 0; i < arrayLength; i++) {\n localFlights[i].initialize();\n serverFlights.push(localFlights[i]);\n }\n\n return serverFlights;\n }\n /**\r\n * Get Flight from local flights\r\n * @memberof FlightFactory\r\n * @param {number} flightId \r\n * @return {object} flight\r\n */\n\n\n function getLocalFlightFromStorage(flightId) {\n var flight = GenericService.get(flightId, 'localFlights', objCallback);\n\n if (flight) {\n flight.initialize();\n }\n\n return fromObject(flight);\n }\n /**\r\n * mark Schedule Changed Flights by comparing flights from new and old data\r\n * @memberof FlightFactory\r\n * @param {object} newFlights \r\n * @param {object} oldFlights\r\n * @return {object} newFlights \r\n */\n\n\n function markScheduleChangedFlights(newFlights, oldFlights) {\n var lastScheduleDate = SyncLogFactory.getLastScheduleDate(); //if there are no old flights or no last schedule date\n\n if (oldFlights && lastScheduleDate) {\n //loop all new flights\n var exists;\n\n for (var i = 0; i < newFlights.length; i++) {\n //loop all old flights\n exists = false;\n\n for (var j = 0; j < oldFlights.length; j++) {\n if (newFlights[i].FlightNo == oldFlights[j].FlightNo && newFlights[i].FlightNo == oldFlights[j].FlightNo && newFlights[i].FlightDate == oldFlights[j].FlightDate && newFlights[i].Departure == oldFlights[j].Departure) {\n exists = true;\n break;\n }\n } //check if flight is newly added and is before the last schedule date\n\n\n var flightDate = new Date(newFlights[i].FlightDate);\n\n if (!exists && flightDate.getTime() <= lastScheduleDate) {\n newFlights[i].IsScheduleChanged = true;\n }\n }\n }\n\n return newFlights;\n } //factory functions\n\n /**\r\n * Update Passenger information\r\n * @memberof FlightFactory\r\n * @param {object} flightInfo The flight informations \r\n */\n\n\n function mergeFlightInfo(flightInfo) {\n if (flightInfo) {\n var currentFlightInfo = GenericService.get(flightInfo.FlightId, objType, objCallback);\n currentFlightInfo.CrewAimsId = flightInfo.CrewAimsId;\n currentFlightInfo.DutyDate = flightInfo.DutyDate;\n currentFlightInfo.Route = flightInfo.Route;\n currentFlightInfo.FlightId = flightInfo.FlightId;\n currentFlightInfo.FlightAimsId = flightInfo.FlightAimsId;\n currentFlightInfo.FlightDate = flightInfo.FlightDate;\n currentFlightInfo.FlightNo = flightInfo.FlightNo;\n currentFlightInfo.Departure = flightInfo.Departure;\n currentFlightInfo.Arrival = flightInfo.Arrival;\n currentFlightInfo.AcType = flightInfo.AcType;\n currentFlightInfo.AcTailNo = flightInfo.AcTailNo;\n currentFlightInfo.ScheduledDeparture = flightInfo.ScheduledDeparture;\n currentFlightInfo.ScheduledArrival = flightInfo.ScheduledArrival;\n currentFlightInfo.BookedC = flightInfo.BookedC;\n currentFlightInfo.BookedY = flightInfo.BookedY;\n currentFlightInfo.BookedInf = flightInfo.BookedInf;\n currentFlightInfo.BookedPad = flightInfo.BookedPad;\n currentFlightInfo.BookedChld = flightInfo.BookedChld;\n currentFlightInfo.ActualC = flightInfo.ActualC;\n currentFlightInfo.ActualY = flightInfo.ActualY;\n currentFlightInfo.ActualInf = flightInfo.ActualInf;\n currentFlightInfo.ActualPad = flightInfo.ActualPad;\n currentFlightInfo.ActualChld = flightInfo.ActualChld;\n currentFlightInfo.Category = flightInfo.Category;\n currentFlightInfo.Status = flightInfo.Status;\n currentFlightInfo.Position = flightInfo.Position;\n currentFlightInfo.IsDHC = flightInfo.IsDHC;\n currentFlightInfo.CallSign = flightInfo.CallSign;\n currentFlightInfo.DepartureGate = flightInfo.DepartureGate;\n currentFlightInfo.DepartureStand = flightInfo.DepartureStand;\n currentFlightInfo.DepartureICAO = flightInfo.DepartureICAO;\n currentFlightInfo.DepartureName = flightInfo.DepartureName;\n currentFlightInfo.DepartureCountry = flightInfo.DepartureCountry;\n currentFlightInfo.ArrivalICAO = flightInfo.ArrivalICAO;\n currentFlightInfo.ArrivalName = flightInfo.ArrivalName;\n currentFlightInfo.ArrivalCountry = flightInfo.ArrivalCountry;\n currentFlightInfo.DepartureTimezone = flightInfo.DepartureTimezone;\n currentFlightInfo.ArrivalTimezone = flightInfo.ArrivalTimezone;\n currentFlightInfo.DepartureSchengen = flightInfo.DepartureSchengen;\n currentFlightInfo.ArrivalSchengen = flightInfo.ArrivalSchengen;\n currentFlightInfo.DepartureEU = flightInfo.DepartureEU;\n currentFlightInfo.ArrivalEU = flightInfo.ArrivalEU;\n currentFlightInfo.ETD = flightInfo.ETD;\n currentFlightInfo.ATD = flightInfo.ATD;\n currentFlightInfo.ETA = flightInfo.ETA;\n currentFlightInfo.ATA = flightInfo.ATA;\n currentFlightInfo.CTOT = flightInfo.CTOT;\n currentFlightInfo.DepartureCountryISO = flightInfo.DepartureCountryISO;\n currentFlightInfo.ArrivalCountryISO = flightInfo.ArrivalCountryISO;\n currentFlightInfo.crew = flightInfo.crew;\n currentFlightInfo.Zones = flightInfo.Zones;\n GenericService.save(currentFlightInfo, objType, objCallback);\n }\n }\n /**\r\n * Get Flights of a Crew Route\r\n * @memberof FlightFactory\r\n * @param {number} dutyNo \r\n * @param {string} dutyDay\r\n * @return {array} flights\r\n */\n\n\n function getFlightsByDutyNo(dutyNo, dutyDay) {\n var flights = getFlightsFromStorage();\n if (flights == null) return [];\n var result = [];\n var arrayLength = flights.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (flights[i].DutyNo == dutyNo && flights[i].DutyDay == dutyDay) {\n result.push(flights[i]);\n }\n }\n\n return result;\n }\n /**\r\n * Get Flights of a Crew Route using a flightId\r\n * @memberof FlightFactory\r\n * @param {number} flightId \r\n * @return {array} flights\r\n */\n\n\n function getFlightsByFlightId(flightId) {\n var result = [];\n var flights = getFlightFromStorage(flightId);\n\n if (flights != null) {\n for (var i = 0; i < flights.length; i++) {\n if (flights[i].DutyNo == dutyNo && flights[i].DutyDay == dutyDay) {\n result.push(flights[i]);\n }\n }\n }\n\n return result;\n }\n\n function getCabinReportId() {\n var res = this.CabinReportLink;\n return res;\n }\n\n return service;\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('FlightCrewMemberFactory', FlightCrewMemberFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightCrewMemberFactory\r\n * @description \r\n * Add, Update, Delete and Get Flight Crew Members.\r\n * @ngInject\r\n */\n\n function FlightCrewMemberFactory(GenericModalFactory) {\n /**\r\n * Initialize the FlightCrewMember\r\n * @memberof FlightCrewMemberFactory\r\n */\n function FlightCrewMember() {\n this.aimsId = null;\n this.id = null;\n this.isDHC = null;\n this.name = null;\n this.position = null;\n this.sex = null;\n this.shortname = null;\n }\n\n var service = {\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n deleteFromList: deleteFromList\n };\n /**\r\n * Extend Object from the default FlightCrewMember Object\r\n * @memberof FlightCrewMemberFactory\r\n * @param {Object} obj a FlightCrewMember\r\n * @returns {Object} FlightCrewMember\r\n */\n\n function fromObject(obj) {\n return GenericModalFactory.fromObject(obj, FlightCrewMember);\n }\n /**\r\n * Delete object from given list and update it\r\n * @memberof FlightCrewMemberFactory\r\n * @param {object} obj a Flight Crew Member\r\n * @param {Array} objList an Array Of Flight Crew Member\r\n * @returns {Array} FlightCrewMembers\r\n *\r\n */\n\n\n function deleteFromList(obj, objList) {\n return GenericModalFactory.deleteFromList(obj, objList);\n }\n /**\r\n * Delete object from given list and update it\r\n * @memberof FlightCrewMemberFactory\r\n * @param {object} obj a Flight Crew Member\r\n * @param {Array} objList an Array Of Flight Crew Member\r\n * @returns {Array} FlightCrewMembers\r\n *\r\n */\n\n\n function fromObjectList(objList) {\n return GenericModalFactory.fromObjectList(objList, FlightCrewMember);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('SearchPastGDCtrl', SearchPastGDCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SearchPastGDCtrl\r\n * @description \r\n * Search old ground duties \r\n * @ngInject\r\n */\n\n function SearchPastGDCtrl($scope, GroundDutyFactory, PastGroundDutyFactory, $uibModalInstance, $route, CourseFactory) {\n $scope.dutyId = null;\n $scope.showContent = 'search';\n $scope.course = {\n isCourseLimited: true\n };\n $scope.hasError = false; // cancel\n\n $scope.doCancel = doCancel; //Close modal\n\n $scope.closeModal = closeModal; // search pending gd\n\n $scope.searchGD = searchGD;\n /**\r\n * Close the modal\r\n * @memberof SearchPastGDCtrl\r\n */\n\n function doCancel() {\n $uibModalInstance.close('cancel');\n }\n\n function searchGD() {\n $scope.showContent = 'loading';\n PastGroundDutyFactory.getPastGroundDuties().then(function (res) {\n return handleSubmitResponse(res);\n })[\"catch\"](function (res) {\n return handleFailedResponse(res);\n });\n }\n\n function handleSubmitResponse(res) {\n $scope.showContent = 'results';\n $scope.availableCources = res.data.trainingCourses;\n $scope.pendingDuties = res.data.pendingGroundDuties;\n $scope.availableCources.forEach(function (course) {\n course.HasLimitedInfo = true;\n CourseFactory.upsertCourse(course, function () {});\n });\n $scope.pendingDuties.forEach(function (duty) {\n duty.isManualEntry = true;\n duty.hasPendingCourse = true;\n GroundDutyFactory.addGroundDuty(duty);\n });\n }\n\n function handleFailedResponse(res) {\n $scope.showContent = 'results';\n $scope.hasError = true;\n }\n\n function closeModal() {\n $uibModalInstance.close();\n $route.reload();\n }\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('aimsCrewMemos', aimsCrewMemos);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name aimsCrewMemos\r\n * @restrict E\r\n * @description\r\n * Implementation of aimsCrewMemos\r\n * Initialize the Aims Crew Memos\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function aimsCrewMemos(AimsCrewMemosFactory) {\n function link($scope, element, attrs) {\n $scope.aimsCrewMemos = AimsCrewMemosFactory.getAimsCrewMemosByDate(attrs.date);\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/directives/aimsCrewMemos.tpl.html\",\n scope: true,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('AimsCrewMemosFactory', AimsCrewMemosFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AimsCrewMemosFactory\r\n * @description \r\n * Add, Update, Delete and Get Aims Crew Memos.\r\n * @ngInject\r\n */\n\n function AimsCrewMemosFactory(GenericService) {\n /**\r\n * Initialize the AircaftPositions\r\n * @memberof AircaftPositionsFactory\r\n */\n function AimsCrewMemos() {\n this.Date = null;\n this.Line = null;\n this.OrderNo = null;\n this.GetId = GetId;\n }\n\n var objType = 'AimsCrewMemos';\n var objCallback = AimsCrewMemos;\n var service = {\n getAimsCrewMemosFromStorage: getAimsCrewMemosFromStorage,\n setAimsCrewMemosToStorage: setAimsCrewMemosToStorage,\n clearAimsCrewMemosFactoryFromStorage: clearAimsCrewMemosFactoryFromStorage,\n getAimsCrewMemosByDate: getAimsCrewMemosByDate\n };\n /**\r\n * Overide default get Id\r\n * @memberof AimsCrewMemosFactory\r\n * @returns {string} Id \r\n */\n\n function GetId() {\n return this.Date;\n }\n /**\r\n * Get Aims Crew Memos\r\n * @memberof AimsCrewMemosFactory\r\n * @returns {Array} Aims Crew Memos\r\n */\n\n\n function getAimsCrewMemosFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save Aims Crew Memos to storage\r\n * @memberof AimsCrewMemosFactory\r\n * @param {Array} A list of Aims Crew Memos\r\n */\n\n\n function setAimsCrewMemosToStorage(aircaftPositions) {\n GenericService.saveAll(aircaftPositions, objType, objCallback);\n }\n /**\r\n * Remove the Aims Crew Memos of the local storage\r\n * @memberof AimsCrewMemosFactory\r\n */\n\n\n function clearAimsCrewMemosFactoryFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get AimsCrewMemosFactory of this flight by date\r\n * @memberof AimsCrewMemosFactory\r\n * @returns {Object} AimsCrewMemosFactory\r\n */\n\n\n function getAimsCrewMemosByDate(date) {\n var crewMemos = getAimsCrewMemosFromStorage();\n var datesMemos = [];\n var arrayLength = crewMemos.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (crewMemos[i].GetId() == date) {\n datesMemos.push(crewMemos[i]);\n }\n }\n\n return datesMemos;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('AircaftPositionsFactory', AircaftPositionsFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AircaftPositionsFactory\r\n * @description \r\n * Add, Update, Delete and Get AircaftPositions.\r\n * @ngInject\r\n */\n\n function AircaftPositionsFactory(GenericService) {\n /**\r\n * Initialize the AircaftPositions\r\n * @memberof AircaftPositionsFactory\r\n */\n function AircaftPositions() {\n this.FlightId = null;\n this.PreviousFlightNo = null;\n this.PreviousStation = null;\n this.PreviousSTA = null;\n this.PreviousETA = null;\n this.PreviousATA = null;\n this.PreviousGATE = null;\n this.PreviousSTAND = null;\n this.NextFlightNo = null;\n this.NextStation = null;\n this.NextSTD = null;\n this.NextETD = null;\n this.NextATD = null;\n this.NextGATE = null;\n this.NextSTAND = null;\n this.GetId = GetId;\n }\n\n var objType = 'aircaftpositions';\n var objCallback = AircaftPositions;\n var service = {\n getAircaftPositionsFromStorage: getAircaftPositionsFromStorage,\n setAircaftPositionsToStorage: setAircaftPositionsToStorage,\n clearAircaftPositionsFromStorage: clearAircaftPositionsFromStorage,\n getAircaftPositionsByFlightId: getAircaftPositionsByFlightId,\n updateAircraftPositionsToStorage: updateAircraftPositionsToStorage\n };\n /**\r\n * Overide default get Id\r\n * @memberof AircaftPositionsFactory\r\n * @returns {number} Id \r\n */\n\n function GetId() {\n return this.FlightId;\n }\n /**\r\n * Get messages\r\n * @memberof AircaftPositionsFactory\r\n * @returns {Array} Aircaft Positions \r\n */\n\n\n function getAircaftPositionsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save Aircaft Positions to storage\r\n * @memberof AircaftPositionsFactory\r\n * @param {Array} messages A list of Aircaft Positions\r\n */\n\n\n function setAircaftPositionsToStorage(aircaftPositions) {\n GenericService.saveAll(aircaftPositions, objType, objCallback);\n }\n /**\r\n * Remove the Aircaft Positions of the local storage\r\n * @memberof AircaftPositionsFactory\r\n */\n\n\n function clearAircaftPositionsFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get Aircaft Positions of this flight\r\n * @memberof AircaftPositionsFactory\r\n * @returns {Object} Aircaft Positions \r\n */\n\n\n function getAircaftPositionsByFlightId(flightId) {\n return GenericService.get(flightId, objType, objCallback);\n }\n /**\r\n * Update Aircraft Position to storage\r\n * @memberof AircaftPositionsFactory\r\n * @param {object} aircraftPositions Aircraft Positions\r\n */\n\n\n function updateAircraftPositionsToStorage(aircraftPositions, flightId) {\n if (GenericService.get(flightId, objType, objCallback)) {\n GenericService.save(aircraftPositions, objType, objCallback);\n } else if (aircraftPositions != null) GenericService.add(aircraftPositions, objType, objCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('eventHistory', eventHistory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name eventHistory\r\n * @restrict E\r\n * @description\r\n * Implementation of eventHistory\r\n * Initialize the Event History of report incidents (mockup view).\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function eventHistory() {\n return {\n restrict: 'E',\n templateUrl: 'views/directives/eventHistory.tpl.html'\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('flightStatus', flightStatus);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightStatus\r\n * @restrict EA\r\n * @description\r\n * Implementation of flightStatus\r\n *\r\n * Initialize the flight Status panel needs to have flight in scope\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */\n\n function flightStatus(AircaftPositionsFactory) {\n function needsSecuritySearch() {\n if ($scope.aircaftPositions.PreviousEU) {\n $scope.securitySearch = false;\n }\n\n if ($scope.aircaftPositions.PreviousCounty == \"SWITZERLAND\" || $scope.aircaftPositions.PreviousCounty == \"NORWAY\" || $scope.aircaftPositions.PreviousCounty == \"ICELAND\" || $scope.aircaftPositions.PreviousCounty == \"MONTENEGRO\") {\n $scope.securitySearch = false;\n }\n\n if ($scope.aircaftPositions.PreviousCounty == \"UNITED KINGDOM\" || $scope.aircaftPositions.PreviousCounty == \"FRANCE\") {\n $scope.securitySearch = true;\n }\n\n if ($scope.flight.ArrivalCountry == \"TURKEY\" || $scope.flight.ArrivalCountry == \"EGYPT\" || $scope.flight.ArrivalCountry == \"ISRAEL\" || $scope.flight.ArrivalCountry == \"JORDAN\" || $scope.flight.ArrivalCountry == \"SAUDI ARABIA\") {\n $scope.securitySearch = true;\n }\n }\n\n return {\n restrict: 'EA',\n terminal: true,\n templateUrl: 'views/directives/flightStatus.tpl.html',\n scope: false,\n link: function link($scope, element, attrs) {\n $scope.securitySearch = false;\n\n if ($scope.flight && $scope.flight.FlightId) {\n $scope.aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId($scope.flight.FlightId);\n }\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('FlightConfigCtrl', FlightConfigCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightConfigCtrl\r\n * @description \r\n * Set the ETA of the flight\r\n * @ngInject\r\n */\n\n function FlightConfigCtrl($scope, $uibModalInstance, flight, FlightFactory) {\n $scope.cancel = cancel;\n $scope.save = save;\n $scope.flightETA = new Date(flight.ETA ? flight.ETA : flight.ScheduledArrival);\n /**\r\n * Save the new ETA\r\n * @memberof FlightConfigCtrl\r\n */\n\n function save() {\n if ($scope.flightETA) {\n var ETAdate = $scope.flightETA;\n var STDdate = new Date(flight.ScheduledDeparture);\n var ETAtimestamp = ETAdate.getTime();\n var STDtimestamp = STDdate.getTime();\n ETAdate.setUTCFullYear(STDdate.getUTCFullYear());\n ETAdate.setUTCMonth(STDdate.getUTCMonth());\n ETAdate.setUTCDate(STDdate.getUTCDate());\n\n if (ETAtimestamp < STDtimestamp) {\n ETAdate.setUTCDate(STDdate.getUTCDate() + 1);\n }\n\n $scope.flightETA = ETAdate;\n }\n\n flight.ETA = $scope.flightETA;\n FlightFactory.updateFlight(flight);\n $uibModalInstance.close(flight);\n }\n /**\r\n * Close the modal\r\n * @memberof FlightConfigCtrl\r\n */\n\n\n function cancel() {\n $uibModalInstance.dismiss();\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('FlightGateCtrl', FlightGateCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightGateCtrl\r\n * @description \r\n * View all flight connections and search for more possible connecting flights\r\n * @ngInject\r\n */\n\n function FlightGateCtrl($scope, $uibModalInstance, flight, FlightGateFactory, SyncLogFactory, FlightFactory, PaxInfoFactory) {\n var paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flight.FlightId);\n var flightId = flight.FlightId;\n var items = [];\n var syncLog = SyncLogFactory.getSyncLog();\n var distinct_gates = [];\n var searchFilters = flight.FlightsFilters;\n var gates = FlightGateFactory.getAfterSTDFromStorage(flight.ScheduledDeparture, flight.Arrival);\n $scope.isConnectedFlightClose = isConnectedFlightClose;\n $scope.TimeDifference = TimeDifference;\n $scope.IsOld = IsOld;\n $scope.searchText = '';\n $scope.addFilter = addFilter;\n $scope.removeFilter = removeFilter;\n $scope.cancel = cancel;\n $scope.filters = searchFilters;\n applyFilter();\n\n if (paxInfo) {\n items = paxInfo.TotalFlights;\n }\n\n for (var i = 0; i < gates.length; i++) {\n var exists = false;\n\n for (var j = 0; j < items.length; j++) {\n if (items[j].FlightNo == gates[i].FlightNo && items[j].Dep == gates[i].Dep) {\n var connectingTime = new Date(items[j].STD_lcl);\n var flightGateTime = new Date(gates[i].STD);\n\n if (connectingTime.getTime() == flightGateTime.getTime()) {\n if (items[j].Codeshares.length == 0) {\n items[j].Codeshares == gates[i].Codeshares;\n }\n\n exists = true;\n break;\n }\n }\n }\n\n if (!exists) {\n var distinct_gate = {\n FlightNo: gates[i].FlightNo,\n Gate: gates[i].DepGate,\n Arr: gates[i].Arrival,\n STD_lcl: gates[i].STD_lcl,\n STD: gates[i].STD,\n pax: null,\n Codeshares: gates[i].Codeshares,\n UpdatedDate: gates[i].lastUpdate\n };\n distinct_gates.push(distinct_gate);\n }\n }\n\n var flightArrivalTime = new Date(flight.ScheduledArrival).getTime();\n $scope.hasGates = distinct_gates.length > 0;\n $scope.items = items.sort(function (a, b) {\n return new Date(a.STD).getTime() - new Date(b.STD).getTime();\n });\n $scope.flightETA = flight.ETA ? new Date(flight.ETA).getTime() : flightArrivalTime;\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof FlightGateCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\n\n function isConnectedFlightClose(connection) {\n if (!connection) {\n return '';\n }\n\n var connFlightDate = new Date(connection).getTime();\n if ($scope.flightETA > connFlightDate) return '';\n\n if (connFlightDate - $scope.flightETA < 3600001) {\n return 'bg-bisque';\n }\n\n if (connFlightDate - $scope.flightETA < 6480000) {\n return 'bg-cornsilk';\n }\n\n return '';\n }\n /**\r\n * Returns the time difference\r\n * @memberof FlightGateCtrl\r\n * @param {string} time Connection STD\r\n * @return {string} timeDifference\r\n */\n\n\n function TimeDifference(time) {\n var timeString = '';\n var sign = '';\n var dayString = null;\n\n if (time) {\n var connFlightDate = new Date(time);\n var ms = connFlightDate.getTime() - $scope.flightETA; // this is a time in milliseconds\n\n if (ms < 0) {\n ms = -ms;\n sign = \"-\";\n }\n\n var days = Math.floor(ms / (24 * 60 * 60 * 1000));\n days = days < 0 ? days + 1 : days;\n var daysms = ms % (24 * 60 * 60 * 1000);\n var hours = Math.floor(daysms / (60 * 60 * 1000));\n var hoursms = ms % (60 * 60 * 1000);\n var minutes = Math.floor(hoursms / (60 * 1000));\n timeString = '' + sign + (hours > 0 ? (\"0\" + hours).substr(-2) + \":\" : '') + (\"0\" + minutes).substr(-2) + '\\'' + '';\n dayString = ' ' + days + 'd';\n }\n\n return timeString + (days && days != 0 ? dayString : '');\n }\n /**\r\n * Checks if the data are new\r\n * @memberof FlightGateCtrl\r\n * @param {string} time timestamp\r\n * @return {boolean} IsOld\r\n */\n\n\n function IsOld(time) {\n IsOld = false;\n\n if (time) {\n var now = new Date();\n var timeDate = new Date(time);\n var diff = now.getTime() - timeDate.getTime();\n\n if (diff > 3600000) {\n IsOld = true;\n }\n }\n\n return IsOld;\n }\n /**\r\n * Apply given filters to show connectings flights\r\n * @memberof FlightGateCtrl\r\n */\n\n\n function applyFilter() {\n var newFlightgates = [];\n\n if (searchFilters.length > 0) {\n for (var i = 0; i < distinct_gates.length; i++) {\n for (var j = 0; j < searchFilters.length; j++) {\n var row = distinct_gates[i].FlightNo + \",\" + distinct_gates[i].Codeshares.toString();\n\n if (row.indexOf(searchFilters[j].toString()) >= 0) {\n newFlightgates.push(distinct_gates[i]);\n break;\n }\n }\n }\n }\n\n $scope.gates = newFlightgates.sort(function (a, b) {\n return new Date(a.STD).getTime() - new Date(b.STD).getTime();\n });\n }\n /**\r\n * Add a filter\r\n * @memberof FlightGateCtrl\r\n * @param {string} searchText Search text\r\n */\n\n\n function addFilter(searchText) {\n if (searchText.trim().length > 0) {\n var exists = false;\n\n for (var i = 0; i < $scope.filters.length; i++) {\n if ($scope.filters[i] == searchText.toString().toUpperCase()) {\n exists = true;\n break;\n }\n }\n\n if (!exists) {\n var flight = FlightFactory.getFlightFromStorage(flightId);\n searchFilters.push(searchText.toString().toUpperCase());\n flight.FlightsFilters = searchFilters;\n FlightFactory.updateFlight(flight);\n $scope.filters = searchFilters;\n }\n\n $scope.searchText = \"\";\n applyFilter();\n }\n }\n /**\r\n * Remove a filter\r\n * @memberof FlightGateCtrl\r\n * @param {item} string filter\r\n */\n\n\n function removeFilter(item) {\n var flight = FlightFactory.getFlightFromStorage(flightId);\n var index = searchFilters.indexOf(item);\n searchFilters.splice(index, 1);\n flight.FlightsFilters = searchFilters;\n FlightFactory.updateFlight(flight);\n $scope.filters = searchFilters;\n applyFilter();\n }\n /**\r\n * Close the modal\r\n * @memberof FlightGateCtrl\r\n */\n\n\n function cancel() {\n $uibModalInstance.close($scope.gates);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('FlightGateFactory', FlightGateFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightGateFactory\r\n * @description \r\n * Add, Update, Delete and Get Flight Gates.\r\n * @ngInject\r\n */\n\n function FlightGateFactory(GenericService) {\n /**\r\n * Initialize the FlightGate\r\n * @memberof FlightGateFactory\r\n */\n function FlightGate() {\n this.FlightDate = null;\n this.Codeshares = [];\n this.FlightNo = null;\n this.Codeshares = [];\n this.Departure = null;\n this.Arrival = null;\n this.STD = null;\n this.STA = null;\n this.ETD = null;\n this.ETA = null;\n this.STD_Diff = null;\n this.STA_Diff = null;\n this.STD_lcl = null;\n this.STA_lcl = null;\n this.ETD_lcl = null;\n this.ETA_lcl = null;\n this.DepGate = null;\n this.DepStand = null;\n this.AcType = null;\n this.lastUpdate = null; //net fields used to hold values before latest update\n\n this.previousUpdate = null;\n this.previousGate = null;\n this.previousSTD = null;\n this.previousSTD_lcl = null;\n this.previousSTD_Diff = null;\n this.previousSTA = null;\n this.previousSTA_lcl = null;\n this.previousSTA_Diff = null; //object functions\n\n this.getRoute = getRoute;\n this.dtSTD = dtSTD;\n this.dtSTA = dtSTA;\n this.dtETD = dtETD;\n this.dtETA = dtETA;\n this.dtSTD_lcl = dtSTD_lcl;\n this.dtSTA_lcl = dtSTA_lcl;\n this.dtETD_lcl = dtETD_lcl;\n this.dtETA_lcl = dtETA_lcl;\n this.dateSTD = dateSTD;\n this.timeSTD = timeSTD;\n this.timeSTA = timeSTA;\n this.timeETD = timeETD;\n this.timeETA = timeETA;\n this.timeSTD_lcl = timeSTD_lcl;\n this.timeSTA_lcl = timeSTA_lcl;\n this.timeETD_lcl = timeETD_lcl;\n this.timeETA_lcl = timeETA_lcl;\n this.hasETD = hasETD;\n this.hasETA = hasETA;\n this.depDelay = depDelay;\n this.arrDelay = arrDelay;\n this.setUpdatedNow = setUpdatedNow;\n this.gateChanged = gateChanged;\n this.stdChanged = stdChanged;\n this.staChanged = staChanged;\n this.stdDiffChanged = stdDiffChanged;\n this.staDiffChanged = staDiffChanged;\n this.toString = toString;\n this.changesToString = changesToString;\n this.getKey = getKey;\n }\n\n var objType = 'FlightGates';\n var objCallback = FlightGate;\n var service = {\n processUpdatedData: processUpdatedData,\n getFromStorage: getFromStorage,\n getAfterSTDFromStorage: getAfterSTDFromStorage,\n setToStorage: setToStorage\n }; //Object functions\n\n function getRoute() {\n if (this.Departure == null && this.Arrival == null) return '-null-';else return (this.Departure || '?') + '-' + (this.Arrival || '?');\n }\n /**\r\n * Transform STD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtSTD() {\n return stringIsoToDateTime(this.STD);\n }\n /**\r\n * Transform STA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtSTA() {\n return stringIsoToDateTime(this.STA);\n }\n /**\r\n * Transform ETD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtETD() {\n return stringIsoToDateTime(this.ETD);\n }\n /**\r\n * Transform ETA iso string to date\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtETA() {\n return stringIsoToDateTime(this.ETA);\n }\n /**\r\n * Transform local STD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtSTD_lcl() {\n return stringIsoToDateTime(this.STD_lcl);\n }\n /**\r\n * Transform local STA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtSTA_lcl() {\n return stringIsoToDateTime(this.STA_lcl);\n }\n /**\r\n * Transform local ETD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtETD_lcl() {\n return stringIsoToDateTime(this.ETD_lcl);\n }\n /**\r\n * Transform local ETA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dtETA_lcl() {\n return stringIsoToDateTime(this.ETA_lcl);\n }\n /**\r\n * Transform local ETA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\n\n\n function dateSTD() {\n return stringIsoToDateString(this.STD);\n }\n /**\r\n * Transform STD iso string to time string \r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeSTD() {\n return stringIsoToTimeString(this.STD);\n }\n /**\r\n * Transform STA iso string to time string \r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeSTA() {\n return stringIsoToTimeString(this.STA);\n }\n /**\r\n * Transform ETD iso string to time string\r\n * @memberof FlightGateFactory\r\n * @return {object} time\r\n */\n\n\n function timeETD() {\n return stringIsoToTimeString(this.ETD);\n }\n /**\r\n * Transform ETA iso string to time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeETA() {\n return stringIsoToTimeString(this.ETA);\n }\n /**\r\n * Transform STD iso string to local time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeSTD_lcl() {\n return stringIsoToTimeString(this.STD_lcl);\n }\n /**\r\n * Transform local STA iso string to string time\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeSTA_lcl() {\n return stringIsoToTimeString(this.STA_lcl);\n }\n /**\r\n * Transform local ETD iso string to time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeETD_lcl() {\n return stringIsoToTimeString(this.ETD_lcl);\n }\n /**\r\n * Transform local ETA iso string to time\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function timeETA_lcl() {\n return stringIsoToTimeString(this.ETA_lcl);\n }\n /**\r\n * Transform local ETA iso string to time\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function hasETD() {\n if (this.ETD && this.STD != this.ETD && this.dtSTD() < this.dtETD()) return true;else return false;\n }\n /**\r\n * check if gate has ETA\r\n * @memberof FlightGateFactory\r\n * @return {boolean} hasETA\r\n */\n\n\n function hasETA() {\n return this.ETA && this.STA != this.ETA && this.dtSTA() < this.dtETA();\n }\n /**\r\n * check if gate has ETA\r\n * @memberof FlightGateFactory\r\n * @return {boolean} hasETA\r\n */\n\n\n function depDelay() {\n if (this.hasETD() && this.STD_Diff && this.STD_Diff > 0) return this.STD_Diff;else return null;\n }\n /**\r\n * Return arrival delay\r\n * @memberof FlightGateFactory\r\n * @return {boolean} STA_Diff\r\n */\n\n\n function arrDelay() {\n if (this.hasETA() && this.STA_Diff && this.STA_Diff > 0) return this.STA_Diff;else return null;\n }\n /**\r\n * record the current time as the lastUpdate of the object\r\n * @memberof FlightGateFactory\r\n */\n\n\n function setUpdatedNow() {\n this.lastUpdate = new Date();\n if (this.DepGate == null) this.DepGate = '';\n }\n /**\r\n * Check if the gate has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} gateChanged\r\n */\n\n\n function gateChanged() {\n if (!this.previousGate) return false;else return true;\n }\n /**\r\n * Check if the STD has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} stdChanged\r\n */\n\n\n function stdChanged() {\n if (!this.previousSTD) return false;else return true;\n }\n /**\r\n * Check if the STA has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} staChanged\r\n */\n\n\n function staChanged() {\n if (!this.previousSTA) return false;else return true;\n }\n /**\r\n * Check if the STD diff has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} stdDiffChanged\r\n */\n\n\n function stdDiffChanged() {\n if (!this.previousSTD_Diff) return false;else return true;\n }\n /**\r\n * Check if the STA diff has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} staDiffChanged\r\n */\n\n\n function staDiffChanged() {\n if (!this.previousSTA_Diff) return false;else return true;\n }\n /**\r\n * Print the flight gate info\r\n * @memberof FlightGateFactory\r\n * @return {string} toSting\r\n */\n\n\n function toString() {\n var s = this.dateSTD() + ' ' + this.FlightNo;\n s += ' ' + this.Departure + '-' + this.Arrival;\n s += ' ' + (this.hasETD() ? 'ETD' + this.timeETD_lcl() + (this.depDelay() ? '[+' + this.depDelay() + '\\']' : '') : 'STD' + this.timeSTD_lcl());\n s += '->' + (this.hasETA() ? 'ETA' + this.timeETA_lcl() + '[' + (this.STA_Diff > 0 ? '+' : '-') + this.STA_Diff + '\\']' : 'STA' + this.timeSTA_lcl());\n s += this.DepGate ? ' Gate: ' + this.DepGate : '';\n return s;\n }\n /**\r\n * Show all the changes of the flight gates\r\n * @memberof FlightGateFactory\r\n * @return {string} toSting\r\n */\n\n\n function changesToString() {\n var s = '';\n if (this.stdChanged()) s += 'STD: ' + stringIsoToTimeString(this.previousSTD) + ' -> ' + this.timeSTD();\n if (self.stdDiffChanged()) s += (s == '' ? '' : ', ') + 'departure delay: ' + this.previousSTD_Diff + ' -> ' + this.STD_Diff;\n if (self.staChanged()) s += (s == '' ? '' : ', ') + 'STA: ' + stringIsoToTimeString(this.previousSTA) + ' -> ' + this.timeSTA();\n if (self.staDiffChanged()) s += (s == '' ? '' : ', ') + 'arrival delay: ' + this.previousSTA_Diff + ' -> ' + this.STA_Diff;\n if (self.gateChanged()) s += (s == '' ? '' : ', ') + ' gate: ' + this.previousGate + ' -> ' + this.DepGate;\n return s;\n }\n /**\r\n * returns a string with all the fields uniquely defining a flight, concatenated\r\n * @memberof FlightGateFactory\r\n * @return {string} key\r\n */\n\n\n function getKey() {\n var s = this.FlightDate + '|' + this.FlightNo + '|' + this.Departure + '-' + this.Arrival;\n return s;\n }\n /**\r\n * Transform iso datetime string to date time Object\r\n * @memberof FlightGateFactory\r\n * @return {Object} DateTime\r\n */\n\n\n function stringIsoToDateTime(str) {\n var dt = null;\n\n try {\n if (str) {\n //replace T in order to avoid browser converting datetime to browser's timezone\n //eg 2016-05-17T23:04:00 would be converted to Wed May 18 2016 02:04:00 GMT+0300 (GTB Daylight Time) when we want it to be Tue May 17 2016 23:04:00 GMT+0300 (GTB Daylight Time)\n str = str.replace('T', ' ');\n dt = new Date(str);\n }\n } catch (e) {}\n\n return dt;\n }\n /**\r\n * Transform iso datetime string to date string\r\n * @memberof FlightGateFactory\r\n * @return {string} date\r\n */\n\n\n function stringIsoToDateString(str) {\n var dt = stringIsoToDateTime(str);\n var s = null;\n\n if (dt) {\n var year = dt.getFullYear();\n var month = dt.getMonth() + 1;\n var day = dt.getDate();\n s = (day < 10 ? '0' : '') + day + '.' + (month < 10 ? '0' : '') + month + '.' + year;\n }\n\n return s;\n }\n /**\r\n * Transform iso datetime string to time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\n\n\n function stringIsoToTimeString(str) {\n var dt = stringIsoToDateTime(str);\n var s = null;\n\n if (dt) {\n var hour = dt.getHours();\n var min = dt.getMinutes();\n s = (hour < 10 ? '0' : '') + hour + ':' + (min < 10 ? '0' : '') + min + '';\n }\n\n return s;\n }\n /**\r\n * Process updated list of fligths 'gates' and store them.Before storing them, we need to identify changes in Gates and in ETD/ETA to notify customers when required. \r\n * @memberof FlightGateFactory\r\n */\n\n\n function processUpdatedData(data) {\n //Update List\n var list = fromObjectList(data); //Original List\n\n var listPrevious = getFromStorage(); //Search each \"new\" flight in the new list, and check if it has been modified since last update\n\n if (list && list.length > 0) {\n var flight, flightPrevious, hasChanged;\n var previousLength = listPrevious.length;\n\n for (var i = 0; i < list.length; i++) {\n flight = list[i]; //mark that this flight was updated now\n\n flight.setUpdatedNow(); //check for flight in previous list, and if found, check for changes\n\n if (listPrevious && previousLength > 0) {\n for (var p = 0; p < previousLength; p++) {\n flightPrevious = listPrevious[p];\n\n if (flight.getKey() === flightPrevious.getKey()) {\n hasChanged = false;\n\n if (flight.DepGate != flightPrevious.DepGate) {\n hasChanged = true;\n flight.previousGate = flightPrevious.DepGate;\n }\n\n if (flight.STD != flightPrevious.STD) {\n hasChanged = true;\n flight.previousSTD = flightPrevious.STD;\n flight.previousSTD_lcl = flightPrevious.STD_lcl;\n }\n\n if (flight.STA != flightPrevious.STA) {\n hasChanged = true;\n flight.previousSTA = flightPrevious.STA;\n flight.previousSTA_lcl = flightPrevious.STA_lcl;\n }\n\n if (flight.STD_Diff != flightPrevious.STD_Diff) {\n hasChanged = true;\n flight.previousSTD_Diff = flightPrevious.STD_Diff;\n }\n\n if (flight.STA_Diff != flightPrevious.STA_Diff) {\n hasChanged = true;\n flight.previousSTA_Diff = flightPrevious.STA_Diff;\n }\n\n if (hasChanged) {\n flight.previousUpdate = flightPrevious.lastUpdate;\n }\n\n break;\n }\n }\n }\n }\n }\n\n setToStorage(list);\n }\n /**\r\n * Get flightgates from storage\r\n * @memberof FlightGateFactory\r\n * @return {array} flightgates\r\n */\n\n\n function getFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Get flightgates after std and flight gates selected departure\r\n * @memberof FlightGateFactory\r\n * @param {string} std STD iso datetime string \r\n * @param {string} dep Departure\r\n * @return {array} flightgates\r\n */\n\n\n function getAfterSTDFromStorage(std, dep) {\n var newFlightgates = [];\n var now_utc = new Date(std);\n var date = now_utc.getTime();\n var flightgates = getFromStorage();\n\n for (var i = 0; i < flightgates.length; i++) {\n var dateSTD = new Date(flightgates[i].STD);\n var dateETD = null;\n\n if (dateETD) {\n dateETD = new Date(flightgates[i].ETD);\n }\n\n if ((dateSTD.getTime() >= date || dateETD != null && dateETD.getTime() >= date) && dep == flightgates[i].Departure && //check only for 2 days later\n dateSTD.getTime() <= date + 172800000) {\n newFlightgates.push(flightgates[i]);\n }\n }\n\n return newFlightgates;\n }\n /**\r\n * Set flightgates from storage\r\n * @memberof FlightGateFactory\r\n * @param {array} data\r\n */\n\n\n function setToStorage(data) {\n GenericService.saveAll(data, objType, objCallback);\n }\n /**\r\n * Set flightgates from storage\r\n * @memberof FlightGateFactory\r\n * @param {array} data\r\n */\n\n\n function fromObjectList(objList) {\n if (objList == null) return [];\n var arrayLength = objList.length;\n var result = [];\n\n for (var i = 0; i < arrayLength; i++) {\n var item = new FlightGate();\n angular.extend(item, objList[i]);\n result.push(item);\n }\n\n return result;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('FlightInfoCtrl', FlightInfoCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightInfoCtrl\r\n * @description \r\n * Shows the flight informations\r\n * @ngInject\r\n */\n\n function FlightInfoCtrl($scope, $location, $routeParams, $uibModal, barOptions, FlightFactory, PaxInfoFactory, MessageFactory, $anchorScroll, CrewCallFactory, PreviousDutyFactory, UserFactory, AircaftPositionsFactory, AimsCrewMemosFactory, showCatIIApprachAcTypes, showGroundInfoAcTypes, FlightCheckInsFactory) {\n var flightId = $routeParams.flightId;\n var flight = FlightFactory.getFlightFromTotalFlights(flightId);\n $scope.user = UserFactory.getUser();\n $scope.flightId = flightId;\n $scope.shownSideMenu = false;\n $scope.sideMenuItems = [];\n $scope.showSidePanel = showSidePanel;\n $scope.hideSidePanel = hideSidePanel;\n $scope.goToPanel = goToPanel;\n\n function hideSidePanel() {\n $scope.shownSideMenu = false;\n }\n\n function goToPanel(id) {\n $location.hash(id);\n $anchorScroll();\n hideSidePanel();\n }\n\n ;\n\n function showSidePanel() {\n $scope.sideMenuItems = [];\n $('.panel-heading .title').each(function () {\n var menuItem = {};\n menuItem.id = $(this).attr(\"id\");\n menuItem.title = $(this).html();\n menuItem.icon = $(this).data('icon');\n $scope.sideMenuItems.push(menuItem);\n });\n $scope.shownSideMenu = true;\n }\n\n if (!flight) {\n // go to dashboard\n $location.path(\"/\");\n } else {\n //Initialize Zones\n var onlyUnique = function onlyUnique(value, index, self) {\n return self.indexOf(value) === index;\n };\n\n var RenderFlightZones = function RenderFlightZones(zones) {\n var flightZones = [];\n\n if (zones != null) {\n var zoneTitles = zones.map(function (item) {\n return item.Title;\n });\n var uniqueZones = zoneTitles.filter(onlyUnique); // //or\n // var uniqueZones2 = Array.from(new Set(zoneTitles));\n\n uniqueZones.forEach(function (element) {\n var getZoneCounter = zoneTitles.filter(function (item) {\n return item == element;\n });\n\n if (getZoneCounter.length > 1) {\n flightZones.push({\n Title: element.Title,\n Class: null\n });\n } else {\n var zone = zones.filter(function (item) {\n return item.Title == element;\n });\n flightZones.push(zone[0]);\n }\n });\n }\n\n return flightZones;\n };\n\n /**\r\n * Open modal to see information for the selected message\r\n * @memberof FlightInfoCtrl\r\n * @param {object} message A message object\r\n */\n var openMessage = function openMessage(_message) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgMessage.html',\n controller: 'MessageModalCtrl',\n size: 'lg',\n keyboard: false,\n backdrop: \"static\",\n resolve: {\n message: function message() {\n return _message;\n }\n }\n });\n modalInstance.result.then(function () {\n if (_message.ReadDt == null) {\n MessageFactory.markReaden(_message.Id);\n _message.ReadDt = new Date();\n }\n });\n };\n /**\r\n * Return the text ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\n\n\n var getTextClass = function getTextClass() {\n var classname = \"\";\n if (flight.LineStatus === 'na') classname = \"text-gray\";else if (flight.LineStatus === 'pending') classname = \"text-blue\";else if (flight.LineStatus === 'pendingoverdue') classname = \"text-blue\";else if (flight.LineStatus === 'draft' || flight.LineStatus === 'draftotheruser') {\n classname = \"text-orange\";\n } else if (flight.LineStatus === 'completed' || flight.LineStatus === 'completedotheruser') {\n classname = \"text-purple\";\n } else if (flight.LineStatus === 'stored' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synched' || flight.LineStatus === 'synchedotheruser') {\n classname = \"text-green\";\n }\n return classname;\n };\n /**\r\n * Return the panel border ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\n\n\n var getTopClass = function getTopClass() {\n var classname = \"\";\n if (flight.LineStatus === 'na') classname = \"border-top-gray\";else if (flight.LineStatus === 'pending') classname = \"border-top-blue\";else if (flight.LineStatus === 'pendingoverdue') classname = \"border-top-blue\";else if (flight.LineStatus === 'draft' || flight.LineStatus === 'draftotheruser') {\n classname = \"border-top-orange\";\n } else if (flight.LineStatus === 'completed' || flight.LineStatus === 'completedotheruser') {\n classname = \"border-top-purple\";\n } else if (flight.LineStatus === 'stored' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synched' || flight.LineStatus === 'synchedotheruser') {\n classname = \"border-top-green\";\n }\n return classname;\n };\n /**\r\n * Return the panel border ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\n\n\n var getBottomClass = function getBottomClass() {\n var classname = \"\";\n if (flight.LineStatus === 'na') classname = \"border-bottom-gray\";else if (flight.LineStatus === 'pending') classname = \"border-bottom-blue\";else if (flight.LineStatus === 'pendingoverdue') classname = \"border-bottom-blue\";else if (flight.LineStatus === 'draft' || flight.LineStatus === 'draftotheruser') {\n classname = \"border-bottom-orange\";\n } else if (flight.LineStatus === 'completed' || flight.LineStatus === 'completedotheruser') {\n classname = \"border-bottom-purple\";\n } else if (flight.LineStatus === 'stored' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synched' || flight.LineStatus === 'synchedotheruser') {\n classname = \"border-bottom-green\";\n }\n return classname;\n };\n /**\r\n * If report from another user exists, show icon\r\n * @memberof FlightInfoCtrl\r\n * @returns {boolean} hasIcon\r\n */\n\n\n var hasIcon = function hasIcon() {\n var hasIcon = false;\n\n if (flight.LineStatus === 'draftotheruser' || flight.LineStatus === 'completedotheruser' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synchedotheruser') {\n hasIcon = true;\n }\n\n return hasIcon;\n };\n /**\r\n * Returns the crew Chart\r\n * @memberof FlightInfoCtrl\r\n * @param {object} flight The flight object\r\n * @return {object} crewChart\r\n */\n\n\n var generateCrewChart = function generateCrewChart(flight) {\n var cp = 0;\n var fo = 0;\n var sa = 0;\n var fa = 0;\n var dhcCp = 0;\n var dhcFo = 0;\n var dhcSa = 0;\n var dhcFa = 0;\n\n if (flight.crew) {\n for (var i = 0; i < flight.crew.length; i++) {\n if (flight.crew[i].isDHC) {\n switch (flight.crew[i].position) {\n case \"CP\":\n dhcCp++;\n break;\n\n case \"FO\":\n dhcFo++;\n break;\n\n case \"SA\":\n dhcSa++;\n break;\n\n case \"FA\":\n dhcFa++;\n break;\n }\n } else {\n switch (flight.crew[i].position) {\n case \"CP\":\n cp++;\n break;\n\n case \"FO\":\n fo++;\n break;\n\n case \"SA\":\n sa++;\n break;\n\n case \"FA\":\n fa++;\n break;\n }\n }\n }\n }\n\n var crewData = {\n labels: [\"CP\", \"FO\", \"SA\", \"FA\"],\n datasets: [{\n label: \"Crew\",\n fillColor: \"rgba(33,150,243,0.5)\",\n strokeColor: \"rgba(33,150,243,0.8)\",\n highlightFill: \"rgba(33,150,243,0.75)\",\n highlightStroke: \"rgba(33,150,243,1)\",\n data: [cp, fo, sa, fa]\n }, {\n label: \"DHC\",\n fillColor: \"rgba(99,181,246,0.5)\",\n strokeColor: \"rgba(99,181,246,0.8)\",\n highlightFill: \"rgba(99,181,246,0.75)\",\n highlightStroke: \"rgba(99,181,246,1)\",\n data: [dhcCp, dhcFo, dhcSa, dhcFa]\n }]\n };\n var crewChart = {\n \"data\": crewData,\n \"options\": barOptions\n };\n return crewChart;\n };\n /**\r\n * toggle Panel\r\n * @memberof FlightInfoCtrl\r\n * @param {number} panelId\r\n */\n\n\n var togglePanel = function togglePanel(panelId) {\n $('#' + panelId).toggle();\n if (panelId == \"info-panel\") $scope.isPanelOpen = !$scope.isPanelOpen;\n };\n /**\r\n * toggle View Mode\r\n * @memberof FlightInfoCtrl\r\n * @param {string} elem\r\n * @param {string} className \r\n */\n\n\n var toggleViewMode = function toggleViewMode(elem, className) {\n $('body').find('div#' + elem + ' > div').not('.tip').hide(\"slow\");\n $('body').find('div#' + elem + ' div.' + className).not('.tip').show(\"slow\");\n };\n /**\r\n * Checks if the data are new\r\n * @memberof FlightInfoCtrl\r\n * @param {string} time timestamp\r\n * @return {boolean} IsOld\r\n */\n\n\n var _IsOld = function IsOld(time) {\n _IsOld = false;\n\n if (time) {\n var now = new Date();\n var timeDate = new Date(time);\n var diff = now.getTime() - timeDate.getTime();\n\n if (diff > 3600000) {\n _IsOld = true;\n }\n }\n\n return _IsOld;\n };\n /**\r\n * Open modal to see information for gates and connections\r\n * @memberof FlightInfoCtrl\r\n */\n\n\n var openGates = function openGates() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgFlightGates.html',\n controller: 'FlightGateCtrl',\n size: 'lg',\n resolve: {\n flight: function flight() {\n return $scope.flight;\n }\n }\n });\n modalInstance.result.then(function (selectedItem) {\n $scope.gates = selectedItem;\n });\n };\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof FlightInfoCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\n\n\n var isConnectedFlightClose = function isConnectedFlightClose(connection) {\n if (!connection) {\n return '';\n }\n\n var connFlightDate = new Date(connection.STD).getTime();\n if ($scope.flightETA > connFlightDate) return '';\n\n if (connFlightDate - $scope.flightETA <= connection.MCT * 60000) {\n return 'bg-bisque';\n }\n\n if (connFlightDate - $scope.flightETA <= connection.MCT * 1.2 * 60000) {\n return 'bg-cornsilk';\n }\n\n return '';\n };\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof FlightInfoCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\n\n\n var TimeDifference = function TimeDifference(time) {\n var timeString = '';\n var sign = '';\n var dayString = null;\n\n if (time) {\n var connFlightDate = new Date(time);\n var ms = connFlightDate.getTime() - $scope.flightETA; // this is a time in milliseconds\n\n if (ms < 0) {\n ms = -ms;\n sign = \"-\";\n }\n\n var days = Math.floor(ms / (24 * 60 * 60 * 1000));\n days = days < 0 ? days + 1 : days;\n var daysms = ms % (24 * 60 * 60 * 1000);\n var hours = Math.floor(daysms / (60 * 60 * 1000));\n var hoursms = ms % (60 * 60 * 1000);\n var minutes = Math.floor(hoursms / (60 * 1000));\n timeString = '' + sign + (hours > 0 ? (\"0\" + hours).substr(-2) + \":\" : '') + (\"0\" + minutes).substr(-2) + '\\'' + '';\n dayString = ' ' + days + 'd';\n }\n\n return timeString + (days && days != 0 ? dayString : '');\n };\n /**\r\n * Open Flight config modal\r\n * @memberof FlightInfoCtrl\r\n */\n\n\n var openFlightConfig = function openFlightConfig() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgFlightConfig.html',\n controller: 'FlightConfigCtrl',\n size: 'md',\n resolve: {\n flight: function flight() {\n return $scope.flight;\n }\n }\n });\n modalInstance.result.then(function (selectedItem) {\n $scope.flightETA = new Date(selectedItem.ETA).getTime();\n $scope.flight = selectedItem;\n });\n };\n /**\r\n * Open Flight config modal\r\n * @memberof FlightInfoCtrl\r\n */\n\n\n var generateDistinctGates = function generateDistinctGates(gates, FlightsFilters) {\n var distinct_gates = [];\n\n for (var i = 0; i < gates.length; i++) {\n for (var j = 0; j < FlightsFilters.length; j++) {\n var row = gates[i].FlightNo + \",\" + gates[i].Codeshares.toString();\n\n if (row.indexOf(FlightsFilters[j].toString()) >= 0) {\n var distinct_gate = {\n FlightNo: gates[i].FlightNo,\n Gate: gates[i].DepGate,\n Arr: gates[i].Arrival,\n STD_lcl: gates[i].STD_lcl,\n STD: gates[i].STD,\n pax: null,\n Codeshares: gates[i].Codeshares\n };\n distinct_gates.push(distinct_gate);\n break;\n }\n }\n }\n\n return distinct_gates;\n };\n\n var applyPhoneNumber = function applyPhoneNumber() {\n var crewPhoneNumbers = CrewCallFactory.getFlightCrewCallsFromStorage(flightId);\n flight.crew.forEach(function (user) {\n var phoneNumberInfo = crewPhoneNumbers.find(function (x) {\n return x.CrewId == user.id;\n });\n\n if (phoneNumberInfo) {\n user.PhoneNumber = phoneNumberInfo.PhoneNumber;\n } else {\n user.PhoneNumber = null;\n }\n });\n };\n\n var applyPreviousDuty = function applyPreviousDuty() {\n var previousDuties = PreviousDutyFactory.getFlightPreviousDutiesFromStorage(flightId);\n var dutyDate = moment(flight.ScheduledDeparture).startOf('day');\n flight.crew.forEach(function (user) {\n var previousDutyInfo = previousDuties.find(function (x) {\n return x.CrewId == user.id;\n });\n\n if (previousDutyInfo) {\n user.PreviousDuty = previousDutyInfo.PreviousDuty;\n } else {\n user.PreviousDuty = null;\n }\n\n if (user.PreviousDuty && user.PreviousDuty.isFlight) {\n var arrivalDate = user.PreviousDuty.ATA;\n if (!arrivalDate) arrivalDate = user.PreviousDuty.ETA;\n if (!arrivalDate) arrivalDate = user.PreviousDuty.STA;\n user.PreviousDuty.showArrivalDate = !moment(arrivalDate).startOf('day').isSame(dutyDate);\n var departureDate = user.PreviousDuty.ATA;\n if (!departureDate) departureDate = user.PreviousDuty.ETA;\n if (!departureDate) departureDate = user.PreviousDuty.STA;\n user.PreviousDuty.showDepartureDate = !moment(departureDate).startOf('day').isSame(dutyDate);\n }\n\n if (user.PreviousDuty && !user.PreviousDuty.isFlight) {\n user.PreviousDuty.showDate = !moment(user.PreviousDuty.GroundDutyDate).startOf('day').isSame(dutyDate);\n }\n });\n };\n\n var applyCrewCheckInStatus = function applyCrewCheckInStatus() {\n var crewCheckInStatuses = FlightCheckInsFactory.getFlightCrewCheckInFromStorage(flightId);\n flight.crew.forEach(function (user) {\n var statuses = crewCheckInStatuses.find(function (x) {\n return x.CrewId == user.id;\n });\n\n if (statuses) {\n user.CheckIn = statuses.CheckIn;\n user.WillBeThereAt = statuses.WillBeThereAt;\n } else {\n user.CheckIn = null;\n user.WillBeThereAt = null;\n }\n });\n };\n\n // (1312896)flightId\n applyPhoneNumber();\n applyPreviousDuty();\n applyCrewCheckInStatus();\n $scope.flightCrewPreviousDuty = flight.crew.filter(function (x) {\n return x.PreviousDuty && x.PreviousDuty.isDifferent && (x.position == \"CP\" || x.position == \"FO\") && !x.isDHC;\n }).length;\n $scope.cabinCrewPreviousDuty = flight.crew.filter(function (x) {\n return x.PreviousDuty && x.PreviousDuty.isDifferent && (x.position == \"SA\" || x.position == \"FA\") && !x.isDHC;\n }).length;\n $scope.dhcCrewPreviousDuty = flight.crew.filter(function (x) {\n return x.PreviousDuty && x.PreviousDuty.isDifferent && x.isDHC;\n }).length;\n $scope.hasPreviousDuties = $scope.flightCrewPreviousDuty + $scope.cabinCrewPreviousDuty + $scope.dhcCrewPreviousDuty;\n var paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flightId);\n var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId(flight.FlightId);\n $scope.dayOfFlight = new Date(flight.FlightDate).getDate();\n $scope.showCatIIApprachSection = showCatIIApprachAcTypes.includes(flight.AcType);\n $scope.showGroundInfoSection = showGroundInfoAcTypes.includes(flight.AcType);\n $scope.aimsCrewMemos = AimsCrewMemosFactory.getAimsCrewMemosByDate(flight.FlightDate); //Initialized scope variables\n\n $scope.state = 'flight';\n $scope.isEnabled = false;\n $scope.flight = flight;\n $scope.aircaftPositions = aircaftPositions;\n $scope.isPanelOpen = true;\n $scope.IsProvisional = true;\n $scope.paxInfo = paxInfo;\n $scope.showConnFlights = true;\n $scope.flightZones = RenderFlightZones(flight.Zones);\n var flightArrivalTime = new Date(flight.ScheduledArrival).getTime(); //Initialize Messages\n\n $scope.messages = MessageFactory.getMessagesFromIds(flight.messages);\n var messages = $scope.messages;\n $scope.openMessage = openMessage; //Initialize CSS classes\n\n $scope.getTextClass = getTextClass();\n $scope.getTopClass = getTopClass();\n $scope.getBottomClass = getBottomClass();\n $scope.hasIcon = hasIcon(); //Charts\n\n $scope.crewChart = generateCrewChart(flight);\n\n if (paxInfo) {\n $scope.cStat = paxInfo.PaxTotalC / paxInfo.ConfigurationC * 100;\n $scope.yStat = paxInfo.PaxTotalY / paxInfo.ConfigurationY * 100;\n var listSentTimestamp = new Date(paxInfo.LastRun).getTime();\n var DepartureTimestamp = new Date(flight.ScheduledDeparture).getTime(); //20 minutes before takeoff\n\n if (DepartureTimestamp - listSentTimestamp <= 1200000) {\n $scope.IsProvisional = false;\n }\n }\n\n $scope.isConnectedFlightClose = isConnectedFlightClose;\n $scope.flightETA = $scope.flight.ETA ? moment(flight.ETA).valueOf() : flightArrivalTime;\n $scope.TimeDifference = TimeDifference;\n $scope.openFlightConfig = openFlightConfig;\n $scope.togglePanel = togglePanel;\n $scope.toggleViewMode = toggleViewMode;\n $scope.IsOld = _IsOld;\n $scope.openGates = openGates;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('groundInfo', groundInfo);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundInfo\r\n * @restrict EA\r\n * @description\r\n * Implementation of groundInfo\r\n *\r\n * Initialize the ground information (Contacts,Hotels)\r\n * @attr {String} station The name of the station to get the ground information.\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */\n\n function groundInfo(AirportContactFactory, AirportHotelFactory) {\n /**\r\n * Calculates distinct HotelTypes (used for filtering results)\r\n * @memberof AirportHotelCtrl\r\n * @param {array} All the airport Hotels (object which containts Hotels property)\r\n * @return {array} The distinct HotelTypes as an array of strings\r\n */\n function findDistinctHotelTypes(items) {\n var unique = {};\n var distinct = [];\n\n for (var i in items) {\n if (items[i].Name && typeof unique[items[i].Name] == \"undefined\") {\n distinct.push(items[i].Name);\n }\n\n unique[items[i].Name] = 0;\n }\n\n return distinct;\n }\n /**\r\n * Used to properly display some Hotel Types, eg nulls\r\n * @memberof AirportHotelCtrl\r\n * @param {string} The Hotel type to examine and \"fix\"\r\n * @return {string} The \"fixed\" string for the given Hotel type (maybe the same as the input value if no fix is needed)\r\n */\n\n\n function printHotelType(HotelType) {\n if (!HotelType || HotelType == '') {\n console.log(HotelType);\n HotelType = '-no Hotel type-';\n }\n\n return HotelType;\n }\n /**\r\n * Calculates distinct ContactTypes (used for filtering results)\r\n * @memberof AirportContactCtrl\r\n * @param {array} All the airport contacts (object which containts Contacts property)\r\n * @return {array} The distinct ContactTypes as an array of strings\r\n */\n\n\n function findDistinctContactTypes(items) {\n var unique = {};\n var distinct = [];\n\n for (var i in items) {\n if (items[i].ContactType && typeof unique[items[i].ContactType] == \"undefined\") {\n distinct.push(items[i].ContactType);\n }\n\n unique[items[i].ContactType] = 0;\n }\n\n return distinct;\n }\n /**\r\n * Used to properly display some Contact Types, eg nulls\r\n * @memberof AirportContactCtrl\r\n * @param {string} The contact type to examine and \"fix\"\r\n * @return {string} The \"fixed\" string for the given contact type (maybe the same as the input value if no fix is needed)\r\n */\n\n\n function printContactType(contactType) {\n if (!contactType || contactType == '') return '-no contact type-';\n return contactType;\n }\n\n return {\n restrict: 'EA',\n terminal: true,\n templateUrl: 'views/directives/groundInfo.tpl.html',\n scope: true,\n link: function link($scope, element, attrs) {\n var stations = attrs.stations ? attrs.stations.split(\",\") : [];\n $scope.stationsInfo = [];\n $scope.filterHotelType = '';\n $scope.filterContactType = ''; //scope methods\n\n $scope.printHotelType = printHotelType;\n $scope.printContactType = printContactType;\n $scope.showInfo = showInfo;\n angular.forEach(stations, function (station) {\n var stationInfo = {};\n var flightDate = $scope.flight && $scope.flight.FlightDate ? $scope.flight.FlightDate : null;\n var contactInfo = AirportContactFactory.getAirportContacts(station);\n stationInfo.Contacts = contactInfo ? contactInfo.Contacts : [];\n stationInfo.ContactTypes = findDistinctContactTypes(stationInfo.Contacts);\n var hotelInfo = AirportHotelFactory.getAirportHotels(station, flightDate);\n stationInfo.Hotels = hotelInfo ? hotelInfo.Hotels : [];\n stationInfo.HotelTypes = findDistinctHotelTypes(stationInfo.Hotels);\n stationInfo.ActiveHotels = false;\n stationInfo.ActiveContacts = false;\n stationInfo.ActiveGeneralInfo = false;\n stationInfo.Name = station;\n\n if (stationInfo.Hotels.length > 0 || stationInfo.Contacts.length > 0) {\n $scope.stationsInfo.push(stationInfo);\n }\n });\n var oldViewStation = '';\n var oldViewType = '';\n\n function showInfo(station, type) {\n angular.forEach($scope.stationsInfo, function (stationInfo) {\n if (stationInfo.Name == station.Name) {\n if (type == 'Hotels') {\n stationInfo.ActiveHotels = !stationInfo.ActiveHotels;\n stationInfo.ActiveContacts = false;\n stationInfo.ActiveGeneralInfo = false;\n } else if (type == 'Contacts') {\n stationInfo.ActiveContacts = !stationInfo.ActiveContacts;\n stationInfo.ActiveHotels = false;\n stationInfo.ActiveGeneralInfo = false;\n } else if (type == 'General') {\n stationInfo.ActiveGeneralInfo = !stationInfo.ActiveGeneralInfo;\n stationInfo.ActiveHotels = false;\n stationInfo.ActiveContacts = false;\n }\n } else {\n stationInfo.ActiveHotels = false;\n stationInfo.ActiveContacts = false;\n stationInfo.ActiveGeneralInfo = false;\n }\n });\n }\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('GroundServicesFactory', GroundServicesFactory);\n /**\r\n * @memberOf PilotReports\r\n * @ngdoc factory\r\n * @name GroundServicesFactory\r\n * @description\r\n * Get Ground Services\r\n * @gnInject\r\n */\n\n function GroundServicesFactory(GenericService) {\n /**\r\n * Initialize the GroundServices\r\n * @memberof GroundServicesFactory\r\n */\n function GroundService() {\n this.Station = null;\n }\n\n var objType = 'groundServices';\n var objCallBack = GroundService;\n var service = {\n fromObjectList: fromObjectList,\n getGroundServicesFromStorage: getGroundServicesFromStorage,\n setGroundServicesToStorage: setGroundServicesToStorage,\n clearGroundServicesFromStorage: clearGroundServicesFromStorage,\n getGroundServicesByStation: getGroundServicesByStation\n };\n /**\r\n * Extend an array of Objects from the default GroundService Object\r\n * @memberof GroundServicesFactory\r\n * @param {Array} objList an Array Of ground Services\r\n * @returns {Array} groundServices\r\n */\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallBack);\n }\n /**\r\n * Get ground services from local storage\r\n * @memberof GroundServicesFactory\r\n * @returns {Array} groundServices \r\n */\n\n\n function getGroundServicesFromStorage() {\n return GenericService.list(objType, objCallBack);\n }\n /**\r\n * Save ground services to storage\r\n * @memberof GroundServicesFactory\r\n * @param {Array} List of ground services\r\n */\n\n\n function setGroundServicesToStorage(groundServices) {\n if (groundServices) {\n for (var i = 0; i < groundServices.length; i++) {\n for (var j = 0; j < groundServices[i].Services.length; j++) {\n // isDefault could be null\n if (groundServices[i].Services[j].IsDefault) groundServices[i].Services[j].Used = 1;else groundServices[i].Services[j].Used = 0;\n }\n }\n\n GenericService.saveAll(groundServices, objType, objCallBack);\n }\n }\n /**\r\n * Remove the ground services from the local storage\r\n * @memberof GroundServicesFactory\r\n */\n\n\n function clearGroundServicesFromStorage() {\n GenericService.removeAll(objType, objCallBack);\n }\n /**\r\n * Get Ground Services of a current station from the local storage\r\n * @memberof GroundServicesFactory\r\n * @param {number} station \r\n * @return {object} GroundServices \r\n */\n\n\n function getGroundServicesByStation(station) {\n var objects = getGroundServicesFromStorage();\n if (objects == null) return [];\n var results = [];\n var arrayLength = objects.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (objects[i].Station == station) {\n results = objects[i].Services;\n }\n }\n\n return results;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.filter('paxNames', paxNames);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name paxNames\r\n * @description \r\n * List pax names in list and return $sce html \r\n * @ngInject\r\n */\n\n function paxNames($sce) {\n return function (input) {\n var html = '\"
C
Y
';\n html = html + \"
Passengers \";\n html = html + '
' + input.PassengerSummaryC.Passengers + \"
\";\n html = html + '
' + input.PassengerSummaryY.Passengers + '
';\n html = html + \"
PRM \";\n html = html + '
' + input.PassengerSummaryC.PRM + \"
\";\n html = html + '
' + input.PassengerSummaryY.PRM + '
';\n html = html + \"
UMNR \";\n html = html + '
' + input.PassengerSummaryC.UMNR + \"
\";\n html = html + '
' + input.PassengerSummaryY.UMNR + '
';\n html = html + \"
DEP \";\n html = html + '
' + input.PassengerSummaryC.DEP + \"
\";\n html = html + '
' + input.PassengerSummaryY.DEP + '
\\\"';\n return $sce.trustAsHtml(html);\n };\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('reportsPanel', reportsPanel);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name reportsPanel\r\n * @restrict E\r\n * @description\r\n * Implementation of reportsPanel\r\n * Initialize the panels with reports.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function reportsPanel($location, defaultCalendarDate) {\n function link($scope, element, attrs) {\n $scope.togglePanel = togglePanel;\n var flight = $scope.flight;\n $scope.showSafetyReport = showSafetyReport(); //Initialize CSS classes\n\n $scope.getTextClass = getTextClass();\n $scope.getTopClass = getTopClass();\n $scope.getBottomClass = getBottomClass();\n $scope.hasIcon = hasIcon();\n $scope.openCabinReport = openCabinReport;\n /**\r\n * toggle Panel\r\n * @memberof FlightInfoCtrl\r\n * @param {number} panelId\r\n */\n\n function togglePanel(panelId) {\n $('#' + panelId).toggle();\n }\n\n function showSafetyReport() {\n var today = new Date().toUTC();\n\n if (defaultCalendarDate) {\n today = new Date(defaultCalendarDate).toUTC();\n }\n\n var flightDate = new Date(flight.FlightDate);\n var trimmedToday = new Date(today);\n var trimmedFlightDate = new Date(flightDate);\n var diffDays = Date.DifferenceInDays(trimmedToday.trimTime(), trimmedFlightDate.trimTime());\n return diffDays <= 0;\n }\n /**\r\n * Return the text ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\n\n\n function getTextClass() {\n var classname = \"\";\n if (flight.LineStatus === 'na') classname = \"text-gray\";else if (flight.LineStatus === 'pending') classname = \"text-blue\";else if (flight.LineStatus === 'pendingoverdue') classname = \"text-blue\";else if (flight.LineStatus === 'draft' || flight.LineStatus === 'draftotheruser') {\n classname = \"text-orange\";\n } else if (flight.LineStatus === 'completed' || flight.LineStatus === 'completedotheruser') {\n classname = \"text-purple\";\n } else if (flight.LineStatus === 'stored' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synched' || flight.LineStatus === 'synchedotheruser') {\n classname = \"text-green\";\n }\n return classname;\n }\n /**\r\n * Return the panel upper ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\n\n\n function getTopClass() {\n var classname = \"\";\n if (flight.LineStatus === 'na') classname = \"border-top-gray\";else if (flight.LineStatus === 'pending') classname = \"border-top-blue\";else if (flight.LineStatus === 'pendingoverdue') classname = \"border-top-blue\";else if (flight.LineStatus === 'draft' || flight.LineStatus === 'draftotheruser') {\n classname = \"border-top-orange\";\n } else if (flight.LineStatus === 'completed' || flight.LineStatus === 'completedotheruser') {\n classname = \"border-top-purple\";\n } else if (flight.LineStatus === 'stored' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synched' || flight.LineStatus === 'synchedotheruser') {\n classname = \"border-top-green\";\n }\n return classname;\n }\n /**\r\n * Return the panel border ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\n\n\n function getBottomClass() {\n var classname = \"\";\n if (flight.LineStatus === 'na') classname = \"border-bottom-gray\";else if (flight.LineStatus === 'pending') classname = \"border-bottom-blue\";else if (flight.LineStatus === 'pendingoverdue') classname = \"border-bottom-blue\";else if (flight.LineStatus === 'draft' || flight.LineStatus === 'draftotheruser') {\n classname = \"border-bottom-orange\";\n } else if (flight.LineStatus === 'completed' || flight.LineStatus === 'completedotheruser') {\n classname = \"border-bottom-purple\";\n } else if (flight.LineStatus === 'stored' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synched' || flight.LineStatus === 'synchedotheruser') {\n classname = \"border-bottom-green\";\n }\n return classname;\n }\n /**\r\n * If report from another user exists, show icon\r\n * @memberof FlightInfoCtrl\r\n * @returns {boolean} hasIcon\r\n */\n\n\n function hasIcon() {\n var hasIcon = false;\n\n if (flight.LineStatus === 'draftotheruser' || flight.LineStatus === 'completedotheruser' || flight.LineStatus === 'storedotheruser' || flight.LineStatus === 'stored+otheruser' || flight.LineStatus === 'synchedotheruser') {\n hasIcon = true;\n }\n\n return hasIcon;\n }\n /**\r\n * Redirects to cabin report page\r\n * @memberof FlightInfoCtrl\r\n * @returns {boolean} hasIcon\r\n */\n\n\n function openCabinReport() {\n $location.path(\"reportsHistory/\" + flight.CabinReportId + \"/\" + flight.FlightId + \"/Cabin\");\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/directives/reportsPanel.tpl.html\",\n scope: false,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('ssr', ssr);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name ssr\r\n * @restrict EA\r\n * @description\r\n * Implementation of issues\r\n *\r\n * Initialize the special service template\r\n * @attr {String} format The name of the format to initialize the ssr.\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */\n\n function ssr($sce, ssrCodes, showRecomendedWaterAcTypes) {\n return {\n restrict: 'EA',\n terminal: true,\n templateUrl: 'views/directives/ssr.tpl.html',\n scope: {\n paxInfo: '=',\n flight: '='\n },\n link: function link($scope, element, attrs) {\n $scope.format = attrs.format;\n $scope.FQTVGold = detailedInfo('FQTVGold');\n $scope.FQTVSilver = detailedInfo('FQTVSilver');\n $scope.UMNR = detailedInfo('UMNR');\n $scope.PRM = detailedInfo('WCBD,WCBW,WCHC,WCHR,WCHS,WCLB,WCMP,WCOB');\n $scope.DEAF = detailedInfo('DEAF');\n $scope.BLND = detailedInfo('BLND');\n $scope.DPNA = detailedInfo('DPNA');\n $scope.DEP = detailedInfo('DEPA,DEPU,ESCD');\n $scope.INAD = detailedInfo('INAD');\n $scope.MEDA = detailedInfo('AOXY,MEDA,MEQT,POXY');\n $scope.CBBG = detailedInfo('CBBG');\n $scope.OTH = detailedInfo('AVIH,BIKE,EMIG,ESAN,EXST,FAMS,GPST,HAJJ,PETC,SVAN,WEAP,XBGS');\n $scope.showFQTVGold = false;\n $scope.showFQTVSilver = false;\n $scope.showUMNR = false;\n $scope.showPRM = false;\n $scope.showDEAF = false;\n $scope.showBLND = false;\n $scope.showDPNA = false;\n $scope.showDEP = false;\n $scope.showINAD = false;\n $scope.showMEDA = false;\n $scope.showCBBG = false;\n $scope.showOTH = false;\n $scope.waterQuantity = getWaterQuantity();\n $scope.showRecomendedWater = showRecomendedWater();\n\n function showRecomendedWater() {\n return showRecomendedWaterAcTypes.includes($scope.flight.AcType);\n }\n\n function getWaterQuantity() {\n var totalPax = $scope.flight.BookedC + $scope.flight.BookedY;\n var startDate = moment($scope.flight.ScheduledDeparture);\n var endDate = moment($scope.flight.ScheduledArrival);\n var duration = moment.duration(endDate.diff(startDate)).asHours();\n var waterQuantity = (0, 18 * totalPax * duration) / 200;\n var formattedwaterQuantity = waterQuantity.toString().substring(0, 4);\n return formattedwaterQuantity;\n }\n\n function detailedInfo(properties) {\n var propertiesArray = properties.split(',');\n var htmlPopover = '';\n\n if ($scope.paxInfo && $scope.paxInfo.PassengerSummaryC && $scope.paxInfo.PassengerSummaryY) {\n if (propertiesArray.length > 1) {\n htmlPopover = '
C
Y
Total
';\n angular.forEach(propertiesArray, function (property) {\n var Total = $scope.paxInfo.PassengerSummaryC['Total' + property] + $scope.paxInfo.PassengerSummaryY['Total' + property];\n\n if (Total > 0) {\n var code = '';\n\n for (var i = 0; i < ssrCodes.length; i++) {\n if (ssrCodes[i].code == property) {\n code = ssrCodes[i].description;\n }\n }\n\n htmlPopover = htmlPopover + '
' + property + \"\";\n htmlPopover = htmlPopover + '' + code + \"\";\n htmlPopover = htmlPopover + '
' + $scope.paxInfo.PassengerSummaryC[property] + \"
\";\n htmlPopover = htmlPopover + '
' + $scope.paxInfo.PassengerSummaryY[property] + \"
\";\n htmlPopover = htmlPopover + '
' + Total + \"
\";\n }\n });\n } else {\n angular.forEach(propertiesArray, function (property) {\n var Total = $scope.paxInfo.PassengerSummaryC['Total' + property] + $scope.paxInfo.PassengerSummaryY['Total' + property];\n htmlPopover = '
C ' + $scope.paxInfo.PassengerSummaryC[property] + '';\n htmlPopover = htmlPopover + ' Y ' + $scope.paxInfo.PassengerSummaryY[property] + '';\n\n if (Total) {\n htmlPopover = htmlPopover + ' Total ' + Total + '';\n }\n\n htmlPopover = htmlPopover + '
';\n });\n }\n }\n\n return $sce.trustAsHtml(htmlPopover);\n }\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('SyncPaxCtrl', SyncPaxCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SyncPaxCtrl\r\n * @description \r\n * Get the latest PAX and gate Information\r\n * @ngInject\r\n */\n\n function SyncPaxCtrl($scope, InfoAPIService, $uibModalInstance, $route, $timeout, flightId, LogService, FlightFactory, FlightSessionFactory, CourseFactory, CrewCallFactory, PreviousDutyFactory) {\n var flight = FlightFactory.getFlightFromTotalFlights(flightId);\n $scope.hideElements = true;\n $scope.showOnSuccess = false;\n $scope.showOnEmptyData = false;\n $scope.showOnSuccessNoFlightData = false;\n $scope.showOnOutOfDateRange = false;\n $scope.cancel = cancel;\n $scope.flightId = flightId;\n var isThisFlightSynced = false;\n $scope.isFetchingFlightData = false;\n $scope.flightDataStatus = [{\n datatype: \"Flight Status\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Aircraft Movement\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Crew Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Crew Contacts\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, // {\n // \tdatatype: \"Aims Crew Memos\",\n // \tstatus: \"PENDING\",\n // \ttext: \"Pending...\"\n // },\n {\n datatype: \"Pax Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Meals\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Connections\",\n status: \"PENDING\",\n text: \"Pending...\"\n }, {\n datatype: \"Training Info\",\n status: \"PENDING\",\n text: \"Pending...\"\n }];\n /**\r\n * Close the modal\r\n * @memberof SyncPaxCtrl\r\n */\n\n function cancel() {\n $uibModalInstance.close('close');\n $route.reload();\n }\n\n ;\n var q = InfoAPIService.getPax(flightId);\n $scope.isFetchingFlightData = true;\n q.then(function (responseData) {\n updateStatusGenerator(responseData);\n $scope.isFetchingFlightData = !$scope.isFetchingFlightData;\n\n if (responseData == undefined || responseData.data == undefined || responseData.data.data == undefined) {\n var err = new Error();\n err.status = -1;\n var msg = \"ResponseData error in sync :\" + JSON.stringify(responseData);\n LogService.debug(msg, err);\n q.reject(err);\n } //Save training\n\n\n var trainingCourses = responseData.data.data.TrainingCourses;\n\n if (trainingCourses && trainingCourses.length) {\n trainingCourses.forEach(function (trainingCourse) {\n CourseFactory.upsertCourse(trainingCourse, function (course) {\n FlightSessionFactory.applyTraineeInfoToSession(course, course.Id, new moment(flight.DutyDate).format(\"YYYY-MM-DD\"), flight.DutyNo, flight.DutyDay, function (session) {});\n });\n });\n } //1. First remove all additional info (phone numbers & previous duties) for this flight\n\n\n CrewCallFactory.cleanFlightCrewNumbers(flightId);\n PreviousDutyFactory.cleanFlightPreviousDuties(flightId); //2. Then save any fetched info\n\n if (responseData.data.data.FlightInfo) {\n var crew = responseData.data.data.FlightInfo.crew;\n CrewCallFactory.saveFlightPhoneNumbers(flightId, crew, flight.ScheduledArrival, flight.ScheduledDeparture);\n PreviousDutyFactory.saveFlightPreviousDuties(flightId, crew);\n } //Save pax\n\n\n if (responseData.data.data.CabinServiceManagementLists) {\n for (var i = 0; i < responseData.data.data.CabinServiceManagementLists.length; i++) {\n if (responseData.data.data.CabinServiceManagementLists[i].FlightId == flightId) {\n //check for out of date range pax info\n var today = new Date().getTime();\n var paxDate = new Date(responseData.data.data.CabinServiceManagementLists[i].LastRun).getTime();\n\n if (paxDate <= today - 172800000) {\n $scope.showOnOutOfDateRange = true;\n break;\n }\n\n $scope.pax = responseData.data.data.CabinServiceManagementLists[i];\n $scope.showOnSuccess = true;\n isThisFlightSynced = true;\n break;\n }\n }\n\n if (!$scope.showOnSuccess) {\n $scope.showOnSuccessNoFlightData = true;\n } // $timeout(function() {\n // \t$uibModalInstance.close();\n // \t$route.reload();\n // }, 3000);\n\n } else {\n $scope.showOnEmptyData = true;\n }\n }, function (responseData) {\n updateStatusGenerator(responseData);\n $scope.isFetchingFlightData = !$scope.isFetchingFlightData;\n $scope.hideElements = false;\n });\n\n function updateStatusGenerator(data) {\n if (!data.data || !data.data.success) {\n for (var i = 0; i < $scope.flightDataStatus.length; i++) {\n $scope.flightDataStatus[i].status = \"FAIL\";\n $scope.flightDataStatus[i].text = \"Update failed\";\n }\n } else {\n var newDuty = data.data.data;\n InfoAPIService.updateFlightStatusSetter(newDuty, $scope.flightDataStatus);\n }\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('turnAroundTimes', turnAroundTimes);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name turnAroundTimes\r\n * @restrict EA\r\n * @description\r\n * Implementation of turnAroundTimes\r\n *\r\n * Initialize the turn Around Times panel needs to have flight in scope\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */\n\n function turnAroundTimes(AircaftPositionsFactory, turnAroundTimesSupportingAcTypes) {\n /**\r\n * Initialize turnAroundTimes\r\n * @memberof turnAroundTimes\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attributes attributes of this element\r\n */\n function link($scope, element, attrs) {\n $scope.showTaTpanel = false;\n var supportsTurnAround = $scope.flight && turnAroundTimesSupportingAcTypes.includes($scope.flight.AcType);\n\n if ($scope.flight && $scope.flight.FlightId && supportsTurnAround) {\n var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId($scope.flight.FlightId);\n\n if (aircaftPositions != null && aircaftPositions.PreviousSTA) {\n var std = moment.utc($scope.flight.ScheduledDeparture);\n var TaTMinutes = $scope.flight.AcType == '321' ? -50 : -45;\n var startofTAT = moment.utc($scope.flight.ScheduledDeparture).add(TaTMinutes, 'm');\n var prevATA = aircaftPositions.PreviousATA ? moment.utc(aircaftPositions.PreviousATA) : null;\n var prevSTA = moment.utc(aircaftPositions.PreviousSTA);\n var lateArrival = 0;\n var inadequateGroundTime = 0;\n\n if (startofTAT.diff(prevSTA, 'm') >= 0 && aircaftPositions.PreviousATA) {\n var comparedValue = startofTAT;\n\n if (lateArrival > 0) {\n var comparedValue = prevATA;\n }\n\n lateArrival = prevATA.diff(comparedValue, 'm');\n $scope.ShowlateArrival = true;\n } else {\n lateArrival = aircaftPositions.PreviousATA ? prevATA.diff(prevSTA, 'm') : 0;\n inadequateGroundTime = prevSTA.diff(startofTAT, 'm');\n\n if (lateArrival < 0) {\n inadequateGroundTime = inadequateGroundTime + lateArrival;\n }\n }\n\n $scope.lateArrival = lateArrival < 0 ? 0 : lateArrival;\n $scope.inadequateGroundTime = inadequateGroundTime < 0 ? 0 : inadequateGroundTime;\n $scope.showTaTpanel = true;\n }\n }\n }\n\n return {\n restrict: 'EA',\n terminal: true,\n templateUrl: 'views/directives/turnAroundTimes.tpl.html',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('GroundDutyCtrl', GroundDutyCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name GroundDutyCtrl\r\n * @description \r\n * Shows the ground duty information\r\n * @ngInject\r\n */\n\n function GroundDutyCtrl(GroundDutyFactory, CourseFactory, TrainingSessionFactory, $scope, $location, $routeParams) {\n $scope.toggleCrewList = toggleCrewList;\n $scope.toggleEditMode = toggleEditMode;\n $scope.selectTrainee = selectTrainee;\n $scope.refresh = refresh;\n $scope.refreshSuccess = true;\n $scope.isRefreshing = false;\n var groundDutyId = Number($routeParams.groundDutyId);\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(groundDutyId);\n $scope.dutyCourses = GroundDutyFactory.getGroundDutyActiveCourses(groundDutyId);\n\n if (!groundDuty) {\n // go to dashboard if no groundDuty\n $location.path(\"/\");\n } else {\n //Toggle trainees\n groundDuty.Trainees.forEach(function (relatedTrainees) {\n relatedTrainees.isCollapsed = false;\n relatedTrainees.dynamicSize = 10;\n }); //Collect all trainees in list\n\n var traineesFlat = [];\n groundDuty.Trainees.forEach(function (related) {\n related.CrewMembers.forEach(function (trainee) {\n traineesFlat.push(trainee);\n });\n });\n groundDuty.traineesFlat = traineesFlat;\n\n if (groundDuty.RelatedGroundDuties) {\n $scope.courses = GroundDutyFactory.getGroundDutyActiveCourses(groundDutyId);\n }\n\n $scope.groundDuty = groundDuty;\n $scope.groundDutyId = groundDutyId;\n }\n\n function toggleCrewList(relatedTrainees) {\n relatedTrainees.isCollapsed = !relatedTrainees.isCollapsed;\n if (relatedTrainees.isCollapsed) relatedTrainees.dynamicSize = relatedTrainees.CrewMembers.length;else relatedTrainees.dynamicSize = 10;\n }\n\n function toggleEditMode(elem, className) {\n $('body').find('div#' + elem + ' > div').not('.tip').hide(\"slow\");\n $('body').find('div#' + elem + ' div.' + className).not('.tip').show(\"slow\");\n }\n /**\r\n * Edit ground duty's attendance list\r\n * @param {object} trainee \r\n */\n\n\n function selectTrainee(trainee) {\n //Value will be saved in ground duty's crew members\n trainee.Absent = !trainee.Absent;\n GroundDutyFactory.updateGroundDuty($scope.groundDuty);\n }\n /**\r\n * Sync ground duty\r\n */\n\n\n function refresh() {\n var courseIds = $scope.dutyCourses.map(function (x) {\n return x.CourseId;\n }).filter(onlyUnique);\n var refreshGroundDuty = {\n DutyId: groundDutyId,\n CourseIds: courseIds\n };\n $scope.isRefreshing = true; //get latest info\n\n GroundDutyFactory.refresh(refreshGroundDuty, function (responseData) {\n $scope.isRefreshing = false;\n $scope.refreshSuccess = true; //Save training\n\n var trainingCourses = responseData.data.TrainingCourses;\n\n if (trainingCourses && trainingCourses.length) {\n trainingCourses.forEach(function (trainingCourse) {\n CourseFactory.upsertCourse(trainingCourse, function (course) {\n TrainingSessionFactory.applyTraineeInfoToSession(course, course.Id, $scope.groundDuty.DutyDateS, groundDutyId, function (session) {});\n });\n });\n }\n })[\"catch\"](function () {\n $scope.refreshSuccess = false;\n $scope.isRefreshing = false;\n });\n }\n\n function onlyUnique(value, index, self) {\n return self.indexOf(value) === index;\n }\n }\n})();\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('GroundDutyFactory', GroundDutyFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GroundDutyFactory\r\n * @description \r\n * Add, Update and Get Ground Duties.\r\n * @ngInject\r\n */\n\n function GroundDutyFactory(GenericService, $http, apiUrl) {\n /**\r\n * Initialize the GroundDuty\r\n * @memberof GroundDutyFactory\r\n */\n function GroundDuty() {\n this.Id = null;\n this.Duty = null;\n this.DutyDescription = null;\n this.DutyBegin = null;\n this.DutyEnd = null;\n this.GetId = GetId;\n this.isTraining = false;\n this.icon = null;\n this.Instructors = new Array();\n this.Trainees = new Array();\n this.isManualEntry = false;\n this.hasPendingCourse = false;\n }\n\n var objType = 'groundDuty';\n var objCallback = GroundDuty;\n var service = {\n getGroundDutiesFromStorage: getGroundDutiesFromStorage,\n setGroundDutiesToStorage: setGroundDutiesToStorage,\n getGroundDutyFromStorage: getGroundDutyFromStorage,\n getGroundDutiesByDutyNo: getGroundDutiesByDutyNo,\n mergeGroundDutyInfo: mergeGroundDutyInfo,\n updateGroundDuty: updateGroundDuty,\n getGroundDutyActiveCourses: getGroundDutyActiveCourses,\n setCourseCompleted: setCourseCompleted,\n setCoursePending: setCoursePending,\n mergeGroundDutiesToStorage: mergeGroundDutiesToStorage,\n refresh: refresh,\n addGroundDuty: addGroundDuty,\n removeGroundDuty: removeGroundDuty,\n getManualGroundDutiesFromStorage: getManualGroundDutiesFromStorage\n }; //object functions\n\n /**\r\n * Overide default get Id\r\n * @memberof GroundDutyFactory\r\n * @returns {number} Id \r\n */\n\n function GetId() {\n return this.Id;\n }\n /**\r\n * Get Ground Duties.\r\n * @memberof GroundDutyFactory\r\n * @returns {Array} GroundDuties \r\n */\n\n\n function getGroundDutiesFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Get GroundDuty from storage groundDuties\r\n * @memberof GroundDutyFactory\r\n * @param {number} groundDutyId \r\n * @return {object} groundDuty\r\n */\n\n\n function getGroundDutyFromStorage(groundDutyId) {\n var groundDuty = GenericService.get(groundDutyId, objType, objCallback);\n var instructors = [];\n var trainees = [];\n\n if (groundDuty != null && groundDuty != undefined) {\n //only training\n if (groundDuty.RelatedGroundDuties && groundDuty.RelatedGroundDuties.length > 1) {\n groundDuty.isTraining = true;\n groundDuty.RelatedGroundDuties.forEach(function (element) {\n if (element.IsInstructor) {\n instructors.push(element);\n } else {\n trainees.push(element);\n }\n });\n groundDuty.Trainees = trainees;\n groundDuty.Instructors = instructors;\n }\n }\n\n return groundDuty;\n }\n /**\r\n * Save Ground Duties to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} GroundDuties A list of Ground Duties\r\n */\n\n\n function setGroundDutiesToStorage(objList) {\n GenericService.saveAll(objList, objType);\n }\n /**\r\n * Get GroundDuties of a Crew Route\r\n * @memberof GroundDutyFactory\r\n * @param {number} dutyNo \r\n * @param {string} dutyDay\r\n * @return {array} groundDuties\r\n */\n\n\n function getGroundDutiesByDutyNo(dutyNo, dutyDay) {\n var groundDuties = getGroundDutiesFromStorage();\n if (groundDuties == null) return [];\n var result = [];\n var instructors = [];\n var trainees = [];\n var arrayLength = groundDuties.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (groundDuties[i].DutyNo == dutyNo && groundDuties[i].DutyDay == dutyDay) {\n //only training\n if (groundDuties[i].RelatedGroundDuties && groundDuties[i].RelatedGroundDuties.length > 1) {\n groundDuties[i].isTraining = true;\n instructors = [];\n trainees = [];\n groundDuties[i].RelatedGroundDuties.forEach(function (element) {\n if (element.IsInstructor) {\n instructors.push(element);\n } else {\n trainees.push(element);\n }\n });\n groundDuties[i].Trainees = trainees;\n groundDuties[i].Instructors = instructors;\n }\n\n result.push(groundDuties[i]);\n }\n }\n\n return result;\n }\n /**\r\n * Merge new info to current Ground Duty\r\n * @memberof GroundDutyFactory\r\n * @param {object} duty \r\n */\n\n\n function mergeGroundDutyInfo(duty) {\n var currentGroundDutyInfo = GenericService.get(duty.Id, objType, objCallback);\n currentGroundDutyInfo.Code = duty.Code;\n currentGroundDutyInfo.Description = duty.Description;\n currentGroundDutyInfo.DutyDate = duty.DutyDate;\n currentGroundDutyInfo.GroundDutyNo = duty.GroundDutyNo;\n currentGroundDutyInfo.DutyDateS = duty.DutyDateS;\n currentGroundDutyInfo.DutyBegin = duty.DutyBegin;\n currentGroundDutyInfo.DutyEnd = duty.DutyEnd;\n currentGroundDutyInfo.DutyDay = duty.DutyDay;\n currentGroundDutyInfo.DutyNo = duty.DutyNo;\n currentGroundDutyInfo.Route = duty.Route;\n\n if (currentGroundDutyInfo.RelatedGroundDuties && currentGroundDutyInfo.RelatedGroundDuties.length) {\n currentGroundDutyInfo.RelatedGroundDuties = duty.RelatedGroundDuties;\n }\n\n GenericService.save(currentGroundDutyInfo, objType, objCallback);\n }\n\n function updateGroundDuty(groundDuty) {\n GenericService.save(groundDuty, objType, objCallback);\n }\n\n function addGroundDuty(groundDuty) {\n var storedGroundDuty = GenericService.get(groundDuty.Id, objType, objCallback);\n\n if (!storedGroundDuty) {\n GenericService.add(groundDuty, objType, objCallback);\n } else {\n updateGroundDuty(groundDuty);\n }\n }\n\n function removeGroundDuty(groundDuty) {\n GenericService.remove(groundDuty, objType, objCallback);\n }\n\n function setCourseCompleted(dutyId, courseId) {\n var groundDuty = GenericService.get(dutyId, objType, objCallback);\n groundDuty.RelatedGroundDuties.filter(function (x) {\n return x.Courses;\n }).forEach(function (item) {\n var groundDutyCourse = item.Courses.find(function (x) {\n return x.CourseId == courseId;\n });\n if (groundDutyCourse) groundDutyCourse.Status = \"Completed\";\n });\n var allCoursesAreCompleted = false;\n\n if (groundDuty.RelatedGroundDuties && groundDuty.RelatedGroundDuties.length > 0) {\n allCoursesAreCompleted = groundDuty.RelatedGroundDuties.filter(function (x) {\n return x.Courses && x.Courses.length > 0;\n }).every(function (relatedDuty) {\n return relatedDuty.Courses.every(function (course) {\n return course.Status == \"Completed\";\n });\n });\n }\n\n if (groundDuty.isManualEntry && allCoursesAreCompleted) {\n groundDuty.hasPendingCourse = false;\n }\n\n updateGroundDuty(groundDuty);\n }\n\n function setCoursePending(dutyId, courseId) {\n var groundDuty = GenericService.get(dutyId, objType, objCallback);\n groundDuty.RelatedGroundDuties.filter(function (x) {\n return x.Courses;\n }).forEach(function (item) {\n var groundDutyCourse = item.Courses.find(function (x) {\n return x.CourseId == courseId;\n });\n if (groundDutyCourse) groundDutyCourse.Status = \"Pending\";\n });\n updateGroundDuty(groundDuty);\n }\n\n function getGroundDutyActiveCourses(groundDutyId) {\n var groundDuty = GenericService.get(groundDutyId, objType, objCallback);\n var courses = [];\n\n if (groundDuty != null && groundDuty != undefined) {\n if (groundDuty.RelatedGroundDuties && groundDuty.RelatedGroundDuties.length > 1) {\n groundDuty.RelatedGroundDuties.filter(function (x) {\n return !x.IsInstructor && x.Courses;\n }).forEach(function (item) {\n courses.push.apply(courses, _toConsumableArray(item.Courses));\n });\n }\n }\n\n return courses;\n }\n /**Save Ground Duties to storage but keep local storage values\r\n * Necessary to maintain Absent values in training duties\r\n */\n\n\n function mergeGroundDutiesToStorage(objList) {\n var groundDuties = getGroundDutiesFromStorage();\n groundDuties.filter(function (x) {\n return x.isManualEntry;\n }).forEach(function (duty) {\n objList.push(duty);\n });\n\n if (groundDuties) {\n objList.forEach(function (incomingDuty) {\n if (incomingDuty.RelatedGroundDuties) {\n var incomingTraineesFlat = [];\n incomingDuty.RelatedGroundDuties.filter(function (x) {\n return !x.IsInstructor;\n }).forEach(function (related) {\n related.CrewMembers.forEach(function (trainee) {\n incomingTraineesFlat.push(trainee);\n });\n }); //Initialize all as present\n\n incomingTraineesFlat.forEach(function (incomingTrainee) {\n incomingTrainee.Absent = false;\n }); //Copy Absent value from existing local storage duties\n\n var existingDuty = groundDuties.find(function (x) {\n return x.Id == incomingDuty.Id;\n });\n\n if (existingDuty && existingDuty.RelatedGroundDuties) {\n var existingTraineesFlat = [];\n existingDuty.RelatedGroundDuties.filter(function (x) {\n return !x.IsInstructor;\n }).forEach(function (related) {\n related.CrewMembers.forEach(function (trainee) {\n existingTraineesFlat.push(trainee);\n });\n });\n incomingTraineesFlat.forEach(function (incomingTrainee) {\n var existingTrainee = existingTraineesFlat.find(function (x) {\n return x.Id == incomingTrainee.Id;\n });\n\n if (existingTrainee) {\n incomingTrainee.Absent = existingTrainee.Absent;\n }\n });\n }\n }\n });\n }\n\n GenericService.saveAll(objList, objType);\n }\n\n function refresh(refreshGroundDuty, callback) {\n return $http.post(apiUrl + '/GroundDuty/Refresh', refreshGroundDuty, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**Get manual Ground Duties from storage*/\n\n\n function getManualGroundDutiesFromStorage() {\n var groundDuties = getGroundDutiesFromStorage();\n return groundDuties.filter(function (x) {\n return x.isManualEntry;\n });\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PastGroundDutyFactory', PastGroundDutyFactory);\n /**\r\n * @memberof CabinReports\r\n * @ngdoc factory\r\n * @name PastGroundDutyFactory\r\n * @description \r\n * Get Past Ground Duties.\r\n * @ngInject\r\n */\n\n function PastGroundDutyFactory($http, apiUrl) {\n var service = {\n getPastGroundDuties: getPastGroundDuties\n };\n\n function getPastGroundDuties(callback) {\n return $http.get(apiUrl + '/Training/GetPastGroundDuties', {\n 'Content-Type': 'application/json'\n })[\"catch\"](callback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('encryptionInterceptor', encryptionInterceptor);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpHeaderInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\n\n function encryptionInterceptor($location, apiUrl) {\n return {\n request: function request(config) {\n if (config.url.includes(\"api\")) {\n if (config.method === \"POST\" || config.method === \"PUT\") {\n var encryptedData = encrypt(config.data);\n console.log(encryptedData);\n } else if (config.method === \"GET\") {\n var absolutePath = config.url;\n var stringToHash = absolutePath.substring(absolutePath.lastIndexOf(\"/\") + 1, absolutePath.length);\n var hash = (stringToHash + user.aimsId).getHash();\n }\n }\n\n return config;\n }\n };\n }\n\n function encrypt(data) {\n debugger;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.config(exceptionConfig);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc config\r\n * @name exceptionConfig\r\n * @description \r\n * By default, AngularJS will catch errors and log them to\r\n * the Console. We want to keep that behavior; however, we\r\n * want to intercept it so that we can also log the errors\r\n * to the server for later analysis.\r\n * @ngInject\r\n */\n\n function exceptionConfig($provide) {\n $provide.decorator('$exceptionHandler', extendExceptionHandler);\n }\n /**\r\n * @memberof exceptionConfig\r\n * @description \r\n * Override default exception handling and log errors \r\n * @ngInject\r\n */\n\n\n function extendExceptionHandler($delegate, LogService) {\n return function (exception, cause) {\n $delegate(exception, cause);\n /**\r\n * Could add the error to a service's collection,\r\n * add errors to $rootScope, log errors to remote web server,\r\n * or log locally. Or throw hard. It is entirely up to you.\r\n * throw exception;\r\n */\n\n LogService.error(exception, cause);\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict'; //***************************************************************************//\n //************ Redirect HTTP401 to login page, examine json format on success\n //***************************************************************************//\n // register the interceptor as a service\n\n a3_pilot_reports.factory('http401interceptor', http401interceptor);\n /* @ngInject */\n\n function http401interceptor($q, $location, $log) {\n return {\n 'response': function response(_response) {\n // do something on success\n //expecting specific object as a response: success:true/false,errorMessage:string,data:any not null object\n //var contentType=response.headers(\"content-type\");\n var header = \"\";\n if (_response && _response.headers() && _response.headers(\"content-type\")) header = _response.headers(\"content-type\").substring(0, 16);\n\n if (header === \"application/json\") {\n var errorMessage = \"\";\n var isError = false;\n\n if (_response == null || _response.data == null || _response.data.success == null || _response.data.errorMessage == null || _response.data.data === 'undefined') {\n isError = true;\n errorMessage = \"Server response not found\";\n } else if (_response.data.success == false) {\n isError = true;\n errorMessage = _response.data.errorMessage;\n }\n\n if (isError) $q.reject(_response, errorMessage);\n }\n\n return _response || $q.when(_response);\n },\n // optional method\n 'responseError': function responseError(rejection) {\n if (rejection.status === 401) {\n $log.error('Authorization failed. Need to login again');\n\n if ($location.path() != '/login') {\n $location.path('/login'); //force refresh so that the browser will download any updates from the cache.manifest\n //without refresh, user may stick to an older version for ever\n\n setTimeout(function () {\n window.location.reload(true);\n }, 1000);\n }\n\n return $q.reject(rejection);\n } else {\n return $q.reject(rejection);\n }\n }\n };\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('httpCrewTokenInterceptor', httpCrewTokenInterceptor);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpCrewTokenInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\n\n function httpCrewTokenInterceptor($location, $log, localStorageMD5Service, UserTokenFactory) {\n return {\n request: function request(config) {\n if ($location.$$url != \"/login\") {\n // get the user token\n var user = localStorageMD5Service.get('user');\n var token = '';\n if (user != null) token = user.token;\n config.headers['X-CrewToken'] = token;\n }\n\n return config;\n },\n response: function response(_response) {\n if (_response.headers()['content-type'] === \"application/json; charset=utf-8\") {\n var expiresAt = _response.headers()['x-expires-token'];\n\n var crewToken = _response.headers()['x-rolling-token'];\n\n if (expiresAt && crewToken) {\n var user = localStorageMD5Service.get('user');\n\n if (user != null) {\n user.token = crewToken;\n user.expires = expiresAt;\n localStorageMD5Service.set('user', user);\n }\n\n UserTokenFactory.setToken(crewToken);\n }\n }\n\n return _response;\n }\n };\n }\n})();\n\"use strict\";\n\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('httpHeaderInterceptor', httpHeaderInterceptor);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpHeaderInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\n\n function httpHeaderInterceptor($location, localStorageMD5Service, apiUrl) {\n return {\n request: function request(config) {\n if ($location.$$url != \"/login\") {\n if (config.url.includes(\"api\")) {\n var user = localStorageMD5Service.get('user');\n var aimsIdToString = user.aimsId.toString();\n\n if (config.method === \"POST\" || config.method === \"PUT\") {\n var dataToHash = _typeof(config.data) === \"object\" ? angular.toJson(config.data) + aimsIdToString : config.data + aimsIdToString;\n var hash = dataToHash.getHash();\n config.headers['X-VCode'] = hash;\n } else if (config.method === \"GET\") {\n var absolutePath = config.url;\n var stringToHash = absolutePath.substring(absolutePath.lastIndexOf(\"/\") + 1, absolutePath.length);\n var hash = (stringToHash + aimsIdToString).getHash();\n config.headers['X-VCode'] = hash;\n }\n }\n }\n\n return config;\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.config(httpProviderConfig);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpCrewTokenInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\n\n function httpProviderConfig($httpProvider) {\n $httpProvider.defaults.useXDomain = true;\n delete $httpProvider.defaults.headers.common['X-Requested-With'];\n $httpProvider.interceptors.push('http401interceptor');\n $httpProvider.interceptors.push('httpCrewTokenInterceptor');\n $httpProvider.interceptors.push('httpHeaderInterceptor'); //$httpProvider.interceptors.push('encryptionInterceptor');\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.config(localStorageMD5Config);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc config\r\n * @name localStorageMD5Config\r\n * @description \r\n * Config localStorageMD5ServiceProvider directly by using localStorageMD5ServiceProvider\r\n * @ngInject\r\n */\n\n function localStorageMD5Config(localStorageMD5ServiceProvider, localStorageServiceProvider) {\n //localStorageMD5ServiceProvider.help();\n var regx = /[?&]secure[&#]?/;\n\n if (regx.exec(window.location.href)) {\n console.log('*** SECURE MODE ***');\n localStorageServiceProvider.setStorageType('sessionStorage');\n }\n\n localStorageServiceProvider.setPrefix('a3.pilot.reports');\n localStorageServiceProvider.setStorageCookie(10, '/');\n localStorageMD5ServiceProvider.enableCompression();\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory(\"LogService\", LogService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name LogService\r\n * @description \r\n * The error log service is our wrapper around the core error\r\n * handling ability of AngularJS. Notice that we pass off to\r\n * the native \"$log\" method and then handle our additional\r\n * server-side logging.\r\n * @ngInject\r\n */\n\n function LogService($log, $injector, $window, apiUrl, UserTokenFactory, version) {\n var lastError = null;\n var acceptedTimeDiff = 5;\n\n function post(errorMessage, stackTrace, cause) {\n try {\n var $http = $injector.get(\"$http\");\n /*// get the user token\r\n var user = UserFactory.getUser();\r\n var token = '';\r\n if (user != null)\r\n \ttoken = user.token;*/\n\n var token = UserTokenFactory.getToken(); // Log the JavaScript error to the server.\n // --\n // NOTE: In this demo, the POST URL doesn't\n // exists and will simply return a 404.\n\n $http({\n method: \"POST\",\n url: apiUrl + \"/log\",\n contentType: \"application/json\",\n data: {\n errorUrl: $window.location.href,\n errorMessage: version + \" \" + errorMessage,\n stackTrace: stackTrace,\n cause: cause || \"\"\n },\n beforeSend: function beforeSend(request) {\n request.setRequestHeader('X-CrewToken', token);\n }\n });\n } catch (loggingError) {\n // For Developers - log the log-failure.\n $log.warn(\"Error logging failed\");\n $log.log(loggingError);\n }\n }\n\n ;\n\n function postFilter(errorMessage, stackTrace, cause) {\n if (lastError != null && lastError.errorDescr == errorMessage) {\n var timestampDiff = Date.now() - lastError.timestamp;\n var timeDiffInSec = timestampDiff / 1000;\n\n if (timeDiffInSec > acceptedTimeDiff) {\n lastError = {\n 'errorDescr': errorMessage,\n 'timestamp': Date.now()\n };\n post(errorMessage, stackTrace, cause);\n }\n } else {\n lastError = {\n 'errorDescr': errorMessage,\n 'timestamp': Date.now()\n };\n post(errorMessage, stackTrace, cause);\n }\n }\n\n ;\n return {\n debug: function debug(errorMessage, error) {\n if (error == null) {\n error = new Error();\n }\n\n if (errorMessage != null) {\n error.description = errorMessage;\n }\n\n post(error.description, error.stack, \"\");\n },\n error: function error(exception, cause) {\n // Pass off the error to the default error handler\n // on the AngualrJS logger. This will output the\n // error to the console (and let the application\n // keep running normally for the user).\n $log.error.apply($log, arguments); // Now, we need to try and log the error the server.\n // --\n // NOTE: In production, I have some debouncing\n // logic here to prevent the same client from\n // logging the same error over and over again! All\n // that would do is add noise to the log.\n\n var errorMessage = exception.toString(); //var stackTrace = stacktraceService.print({ e: exception });\n //var stackTrace = $log.info({ e: exception });\n\n var stackTrace = exception.stack;\n postFilter(errorMessage, stackTrace, cause);\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('UserTokenFactory', UserTokenFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name UserTokenFactory\r\n * @description \r\n * Used to maintain the user token, outside the localStorage, in order to be accessible from the service which logs js errors\r\n * /(this service may not use localstorage provider)\r\n * @ngInject\r\n */\n\n function UserTokenFactory() {\n return {\n token: '',\n setToken: function setToken(value) {\n this.token = value;\n },\n getToken: function getToken() {\n return this.token;\n }\n };\n }\n})();\n\"use strict\";\n\n// create guid\nvar guid = function () {\n function s4() {\n return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\n }\n\n return function () {\n return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();\n };\n}(); // generic sort function\n\n\nvar sort_by = function sort_by(field, reverse, primer) {\n var key = function key(x) {\n return primer ? primer(x[field]) : x[field];\n };\n\n return function (a, b) {\n var A = key(a),\n B = key(b);\n return (A < B ? -1 : A > B ? 1 : 0) * [-1, 1][+!!reverse];\n };\n};\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('flexCombination', FlexCombination);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name FlexCombination\r\n * @restrict E\r\n * @description\r\n * Implementation of Flex Combinations\r\n *\r\n * Initialize the Flex Combination of a season\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function FlexCombination($timeout) {\n function link(scope, element, attrs) {\n angular.forEach(scope.seasonRequest.LeaveRequestPriorityPeriods, function (value, key) {\n var temp = value.MockLeaveRequestPrioritySlots;\n var temp2 = value.LeaveRequestPrioritySlots;\n $timeout(function () {\n value.MockLeaveRequestPrioritySlots = angular.fromJson(temp);\n value.LeaveRequestPrioritySlots = angular.fromJson(temp2);\n });\n });\n scope.sortableOptions = {\n handle: '>.row .myHandle',\n update: function update(e, ui) {},\n stop: function stop(e, ui) {\n for (var i = 0; i < scope.seasonRequest.LeaveRequestPriorityPeriods.length; i++) {\n sortSetupOrderNo(scope.seasonRequest.LeaveRequestPriorityPeriods[i]);\n }\n }\n };\n scope.setupOrderNo = setupOrderNo;\n\n function sortSetupOrderNo(period) {\n if (Array.isArray(period.LeaveRequestPrioritySlots)) {\n for (var i = 0; i < period.LeaveRequestPrioritySlots.length; i++) {\n period.LeaveRequestPrioritySlots[i].OrderNo = i + 1;\n }\n }\n }\n\n ;\n\n function setupOrderNo(period) {\n if (Array.isArray(period.MockLeaveRequestPrioritySlots)) {\n period.LeaveRequestPrioritySlots = [];\n\n for (var i = 0; i < period.MockLeaveRequestPrioritySlots.length; i++) {\n var temp = Object.assign({}, period.MockLeaveRequestPrioritySlots[i]);\n temp.OrderNo = i + 1;\n period.LeaveRequestPrioritySlots.push(temp);\n }\n }\n }\n\n ;\n scope.removeSlot = removeSlot;\n\n function removeSlot(slotIndex, period) {\n period.LeaveRequestPrioritySlotsHelper = [];\n\n for (var i = 0; i < period.LeaveRequestPrioritySlots.length; i++) {\n if (i != slotIndex) {\n period.LeaveRequestPrioritySlotsHelper.push(period.LeaveRequestPrioritySlots[i]);\n }\n }\n\n period.LeaveRequestPrioritySlots = period.LeaveRequestPrioritySlotsHelper;\n period.MockLeaveRequestPrioritySlots = period.LeaveRequestPrioritySlotsHelper;\n setupOrderNo(period);\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/LeaveRequest/flexCombinations.tpl.html',\n scope: {\n seasonConfiguration: '<',\n seasonRequest: '=',\n editable: '<'\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('LeaveRequestCtrl', LeaveRequestCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name LeaveRequestCtrl\r\n * @description \r\n * View Leave Request Tool\r\n * @ngInject\r\n */\n\n function LeaveRequestCtrl($route, $scope, $filter, LeaveRequestFactory, $uibModal, $timeout) {\n $scope.state = 'leaveRequest';\n $scope.getRandomBorderColor = getRandomBorderColor;\n $scope.getRandomTextColor = getRandomTextColor;\n $scope.IsValidLeaveRequest = IsValidLeaveRequest;\n $scope.showHelp = showHelp;\n $scope.showSuccessLeaveApplicationMessage = false;\n $scope.hasErrors = false;\n progressBarBox(true);\n LeaveRequestFactory.getConfigurationDetails(function (responseData) {\n $scope.QualificationGroup = responseData.data.data.QualificationGroup;\n $scope.LeaveRequestInformation = responseData.data.data.LeaveRequestInformation;\n $scope.QualificationGroup.RequestLessDays = $scope.QualificationGroup.RequestLessDays ? $scope.QualificationGroup.RequestLessDays : false;\n $scope.QualificationGroup.RequestNoLeave = $scope.QualificationGroup.RequestNoLeave ? $scope.QualificationGroup.RequestNoLeave : false;\n\n if (responseData.data && responseData.data.data && responseData.data.data.QualificationGroup && responseData.data.data.LeaveRequestInformation) {\n //TEST\n //$scope.LeaveRequestInformation.GroupStatus = \"PROCESS\";\n $scope.closeDateStr = moment($scope.LeaveRequestInformation.CloseDate).format('Do of MMMM');\n $scope.isOpen = $scope.LeaveRequestInformation.GroupStatus == \"OPEN\";\n $scope.LeaveRequest = {\n YearId: $scope.LeaveRequestInformation.YearId,\n MemberId: $scope.LeaveRequestInformation.MemberId,\n RequestNoleave: responseData.data.data.LeaveRequest ? responseData.data.data.LeaveRequest.RequestNoleave : false,\n // Default: Request Leave selected\n LeaveRequestSeasons: []\n };\n\n if (responseData.data.data.LeaveRequest) {\n $scope.showSuccessLeaveApplicationMessage = true;\n }\n\n if (responseData.data.data.LeaveRequest && !responseData.data.data.LeaveRequest.RequestNoleave) {\n mergeRequest(responseData.data.data.LeaveRequest, $scope.QualificationGroup.Seasons);\n } else {\n initializeNewRequest($scope.QualificationGroup.Seasons); //Temporary: Hide Instructions\n //if($scope.isOpen) $timeout(showHelp,500);\n }\n } else {\n $scope.hasErrors = true;\n }\n\n progressBarBox(false);\n }, function (data) {\n $scope.hasErrors = true;\n progressBarBox(false);\n });\n\n function mergeRequest(leaveRequest, seasons) {\n $scope.LeaveRequest = leaveRequest;\n\n for (var j = 0; j < leaveRequest.LeaveRequestSeasons.length; j++) {\n leaveRequest.LeaveRequestSeasons[j].HasSpecificCombinations = $filter('filter')(leaveRequest.LeaveRequestSeasons[j].LeaveRequestPriorities, {\n Type: 'All'\n }).length > 0;\n\n for (var i = 0; i < seasons.length; i++) {\n if (seasons[i].Id == leaveRequest.LeaveRequestSeasons[j].SeasonId) {\n leaveRequest.LeaveRequestSeasons[j].StartDate = seasons[i].StartDate;\n leaveRequest.LeaveRequestSeasons[j].EndDate = seasons[i].EndDate;\n leaveRequest.LeaveRequestSeasons[j].Slots = seasons[i].Slots;\n leaveRequest.LeaveRequestSeasons[j].Configurations = seasons[i].Configurations;\n setupMockLeaveRequestPriorities(leaveRequest.LeaveRequestSeasons[j].LeaveRequestPriorities, seasons[i].Slots);\n\n for (var h = 0; h < seasons[i].Configurations.length; h++) {\n if (seasons[i].Configurations[h].Id == leaveRequest.LeaveRequestSeasons[j].ConfigurationId) {\n leaveRequest.LeaveRequestSeasons[j].Configuration = seasons[i].Configurations[h];\n }\n }\n }\n }\n }\n\n $scope.LeaveRequest = leaveRequest;\n }\n\n function setupMockLeaveRequestPriorities(priorities, slots) {\n for (var i = 0; i < priorities.length; i++) {\n for (var j = 0; j < priorities[i].LeaveRequestPriorityPeriods.length; j++) {\n for (var h = 0; h < priorities[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots.length; h++) {\n var tempOrderNo = priorities[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots[h].OrderNo;\n priorities[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots[h] = findSlot(priorities[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots[h], slots);\n priorities[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots[h].OrderNo = tempOrderNo;\n }\n\n priorities[i].LeaveRequestPriorityPeriods[j].MockLeaveRequestPrioritySlots = priorities[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots;\n }\n }\n }\n\n function findSlot(value, slots) {\n var temp = null;\n\n for (var i = 0; i < slots.length; i++) {\n if (slots[i].Id == value.Id) {\n temp = slots[i];\n }\n }\n\n return temp;\n }\n\n function showHelp() {\n $uibModal.open({\n templateUrl: 'views/LeaveRequest/dlgLeaveRequestInstructions.html',\n controller: 'LeaveRequestInstructionsCtrl',\n size: 'lg',\n backdrop: 'static',\n keyboard: false,\n resolve: {}\n });\n }\n\n function initializeNewRequest(seasons) {\n for (var i = 0; i < seasons.length; i++) {\n var leaveRequestSeason = seasons[i];\n leaveRequestSeason.SeasonId = leaveRequestSeason.Id;\n var flexLeaveRequestPriority = {\n Type: \"Any\",\n Priority: 1000,\n LeaveRequestPriorityPeriods: []\n };\n var configurationDays = [];\n\n for (var j = 0; j < seasons[i].Configurations.length; j++) {\n configurationDays.push(seasons[i].Configurations[j].Days);\n }\n\n leaveRequestSeason.Days = configurationDays.unique();\n leaveRequestSeason.HasSpecificCombinations = false;\n leaveRequestSeason.LeaveRequestPriorities = [flexLeaveRequestPriority];\n $scope.LeaveRequest.LeaveRequestSeasons.push(leaveRequestSeason);\n }\n }\n\n function IsValidLeaveRequest() {\n var isValid = true;\n\n if (!$scope.LeaveRequest.RequestNoleave) {\n //Validate only if Requested Leave\n if ($scope.LeaveRequest && !$scope.invalidSelectedLeaveDays) {\n for (var i = 0; i < $scope.LeaveRequest.LeaveRequestSeasons.length; i++) {\n for (var j = 0; j < $scope.LeaveRequest.LeaveRequestSeasons[i].LeaveRequestPriorities.length; j++) {\n if ($scope.LeaveRequest.LeaveRequestSeasons[i].LeaveRequestPriorities[j].HasInvalidPeriod) {\n isValid = false;\n break;\n }\n }\n\n if (!$scope.LeaveRequest.LeaveRequestSeasons[i].Configuration) {\n isValid = false;\n break;\n }\n }\n } else {\n isValid = false;\n }\n }\n\n return isValid;\n }\n\n $scope.updateLeaveRequestSeason = updateLeaveRequestSeason;\n $scope.showCombo = false;\n $scope.radioConfigurationModel = null;\n $scope.sendRequest = sendRequest;\n $scope.addComment = addComment;\n\n function addComment(request) {\n request.Comments = \" \";\n }\n\n function sendRequest() {\n //Request No Leave: Clear any selected values\n if ($scope.LeaveRequest.RequestNoleave) {\n $scope.LeaveRequest.LeaveRequestSeasons = null;\n }\n\n progressBarBox(true);\n LeaveRequestFactory.saveLeaveRequest($scope.LeaveRequest, onSuccessSendRequest, onErrorSendRequest);\n }\n\n function onSuccessSendRequest(data) {\n progressBarBox(false);\n\n if (data.data.success == true) {\n ShowSuccessMessage();\n } else {\n ShowErrorMessage();\n }\n }\n\n function onErrorSendRequest(data) {\n progressBarBox(false);\n ShowErrorMessage();\n }\n\n function ShowSuccessMessage() {\n var closeDateStr = moment($scope.LeaveRequestInformation.CloseDate).format('Do of MMMM');\n bootbox.alert({\n title: \"
Success
\",\n message: \"You have successfully submitted your leave request. You can modify your leave request untill the \" + closeDateStr + \".\",\n callback: function callback() {\n $route.reload();\n }\n });\n }\n\n function ShowErrorMessage() {\n bootbox.alert({\n title: \"
Error
\",\n message: \"Failed to send your leave request. Please try again later\",\n callback: function callback() {\n $route.reload();\n }\n });\n }\n\n function progressBarBox(isOpen) {\n if (isOpen) {\n bootbox.dialog({\n closeButton: false,\n message: '
Please wait...
' //title: \"Please wait...\"\n\n });\n } else {\n bootbox.hideAll();\n }\n }\n /* function setupView() {\r\n if (!UserFactory.isLoggedIn()) {\r\n $location.path(\"/login\");\r\n }*/\n //$scope.sortableOptions['ui-floating'] = true;\n\n\n function updateLeaveRequestSeason(season) {\n season.ConfigurationId = season.Configuration.Id;\n\n for (var i = 0; i < season.LeaveRequestPriorities.length; i++) {\n for (var j = 0; j < season.Configuration.Periods.length; j++) {\n season.Configuration.Periods[j].ConfigurationPeriodId = season.Configuration.Periods[j].Id;\n }\n\n season.LeaveRequestPriorities[i].LeaveRequestPriorityPeriods = JSON.parse(JSON.stringify(season.Configuration.Periods));\n }\n\n var totalDays = 0;\n var hasConfig = true;\n\n for (var i = 0; i < $scope.LeaveRequest.LeaveRequestSeasons.length; i++) {\n totalDays = totalDays + ($scope.LeaveRequest.LeaveRequestSeasons[i].Configuration && $scope.LeaveRequest.LeaveRequestSeasons[i].Configuration.Days ? $scope.LeaveRequest.LeaveRequestSeasons[i].Configuration.Days : 0);\n hasConfig = hasConfig && $scope.LeaveRequest.LeaveRequestSeasons[i].Configuration;\n }\n\n if (totalDays > $scope.LeaveRequestInformation.LeaveDays) {\n $scope.invalidSelectedLeaveDays = true;\n bootbox.alert(\"

Warning!

You are entilted to \" + $scope.LeaveRequestInformation.LeaveDays + \" leave days but you have selected a combination of \" + totalDays + \" days. Please proceed with the necessary changes.\");\n } else if (!$scope.QualificationGroup.RequestLessDays && totalDays < $scope.LeaveRequestInformation.LeaveDays) {\n $scope.invalidSelectedLeaveDays = true;\n\n if (hasConfig) {\n bootbox.alert(\"

Warning!

You are entilted to \" + $scope.LeaveRequestInformation.LeaveDays + \" leave days but you have selected a combination of \" + totalDays + \" days. Please proceed with the necessary changes.\");\n }\n } else {\n $scope.invalidSelectedLeaveDays = false;\n }\n }\n\n function getRandomBorderColor(season) {\n var cssClass = \"border-left-green\";\n\n if (!season.Configuration) {\n cssClass = \"border-left-orange\";\n }\n\n return cssClass;\n }\n\n function getRandomTextColor(season) {\n var cssClass = \"text-green\";\n\n if (!season.Configuration) {\n cssClass = \"text-orange\";\n }\n\n return cssClass;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('LeaveRequestFactory', LeaveRequestFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name LeaveRequestFactory\r\n * @description \r\n * Get Leave Request Configuration Data and submit new Leave Request\r\n * @ngInject\r\n */\n\n function LeaveRequestFactory(GenericService, $http, $q, apiUrl) {\n var service = {\n getConfigurationDetails: getConfigurationDetails,\n saveLeaveRequestInformation: saveLeaveRequestInformation,\n getLeaveRequestInformation: getLeaveRequestInformation,\n saveLeaveRequest: saveLeaveRequest\n };\n /**\r\n * Initialize the LeaveRequestInformation\r\n * @memberof LeaveRequestFactory\r\n */\n\n function LeaveRequestInformation() {}\n\n var objType = 'LeaveRequestInformation';\n var objCallback = LeaveRequestInformation;\n var leaveRequestApiURL = apiUrl + '/LeaveRequest';\n /**\r\n * Get the LeaveRequestInformation and the qualification Group\r\n * @memberof LeaveRequestFactory\r\n * @param {function} callback an on success callback function\r\n * @param {function} errorCallback an on error callback function\r\n */\n\n function getConfigurationDetails(callback, errorCallback) {\n return $http.get(leaveRequestApiURL, {\n 'Content-Type': 'application/json'\n }).then(function (responseData) {\n if (responseData && responseData.data && responseData.data.data && responseData.data.data.LeaveRequestInformation) {\n saveLeaveRequestInformation(responseData.data.data.LeaveRequestInformation);\n }\n\n callback(responseData);\n })[\"catch\"](errorCallback);\n }\n\n function saveLeaveRequest(request, callback, errorCallback) {\n var cleanRequest = angular.toJson(request);\n return $http.post(leaveRequestApiURL, cleanRequest, {\n 'Content-Type': 'application/json'\n }).then(function (responseData) {\n if (responseData && responseData.data && responseData.data.data && responseData.data.data.LeaveRequestInformation) {\n saveLeaveRequestInformation(responseData.data.data.LeaveRequestInformation);\n }\n\n console.log(request);\n callback(responseData);\n })[\"catch\"](errorCallback);\n }\n /**\r\n * Save the leave Request Information Object in local storage\r\n * @memberof LeaveRequestFactory\r\n * @param {object} leaveRequestInformation a leaveRequestInformation\r\n */\n\n\n function saveLeaveRequestInformation(leaveRequestInformation) {\n GenericService.saveOne(leaveRequestInformation, objType, objCallback);\n }\n /**\r\n * Save the leave Request Information Object in local storage\r\n * @memberof LeaveRequestFactory \r\n * @returns {object} leaveRequestInformation \r\n */\n\n\n function getLeaveRequestInformation() {\n return GenericService.getOne(objType, objCallback);\n }\n /* function postProposal(proposal){\r\n return $http.post(apiUrl + '/bucket/PostProposal/', proposal, { 'Content-Type' : 'application/json' });\r\n }\r\n */\n\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('LeaveRequestInstructionsCtrl', LeaveRequestInstructionsCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name LeaveRequestInstructionsCtrl\r\n * @description \r\n * Get the Leave Request Instructions\r\n * @ngInject\r\n */\n\n function LeaveRequestInstructionsCtrl($scope, $uibModalInstance) {\n $scope.page = 1;\n $scope.cancel = cancel;\n $scope.nextPage = nextPage;\n $scope.previousPage = previousPage;\n $scope.instructionPages = 6;\n /**\r\n * Goes to the next page of leave instructions\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\n\n function nextPage() {\n $scope.page = $scope.page + 1;\n normalizePage();\n }\n /**\r\n * Goes to the previous page of leave instructions\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\n\n\n function previousPage() {\n $scope.page = $scope.page - 1;\n normalizePage();\n }\n /**\r\n * Normalize the page number if it is out of range\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\n\n\n function normalizePage() {\n if ($scope.page > $scope.instructionPages || $scope.page < 1) {\n $scope.page = 1;\n }\n }\n /**\r\n * Close the modal\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('close');\n }\n\n ;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('specificCombinations', SpecificCombinations);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name SpecificCombinations\r\n * @restrict E\r\n * @description\r\n * Implementation of Specific Combinations\r\n *\r\n * Initialize the Specific Combinations of a season\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function SpecificCombinations($filter) {\n function link(scope, element, attrs) {\n scope.IsEditEnabled = false;\n scope.selectEditablePeriod = selectEditablePeriod;\n scope.updateEditablePeriod = updateEditablePeriod;\n scope.removeSpecificCombination = removeSpecificCombination;\n scope.addNewSpecificCombination = addNewSpecificCombination;\n scope.getBorderClass = getBorderClass;\n scope.selectedSlotTemp = null;\n scope.isDisabled = isDisabled;\n scope.specificCombinations = $filter('filter')(scope.seasonRequests, {\n Type: 'All'\n });\n scope.sortableOptions = {\n handle: '> .row .myHandle',\n update: function update(e, ui) {},\n stop: function stop(e, ui) {\n recalculatePriorities();\n }\n };\n\n function recalculatePriorities() {\n for (var i = 0; i < scope.specificCombinations.length; i++) {\n scope.specificCombinations[i].Priority = i + 1;\n }\n }\n\n function selectEditablePeriod(period, request) {\n if (!period.isEditable) {\n resetEditablePeriods();\n\n if (period.LeaveRequestPrioritySlots && period.LeaveRequestPrioritySlots.length > 0) {\n scope.selectedSlotTemp = period.LeaveRequestPrioritySlots[0];\n } else {\n scope.selectedSlotTemp = null;\n }\n\n scope.selectedRequestTemp = request;\n scope.selectedSlotDaysTemp = period.Days;\n period.isEditable = true;\n scope.IsEditEnabled = true;\n } else {\n resetEditablePeriods();\n }\n }\n\n function getBorderClass(request) {\n var hasEmptyFields = false;\n var hasFilledFields = false;\n var cssClass = \"\";\n\n for (var i = 0; i < request.LeaveRequestPriorityPeriods.length; i++) {\n hasEmptyFields = hasEmptyFields || !request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots || request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots.length == 0;\n hasFilledFields = hasFilledFields || !(!request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots || request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots.length == 0);\n }\n\n if (hasEmptyFields && hasFilledFields) {\n cssClass = 'specific-combination-orange';\n request.HasInvalidPeriod = true;\n } else if (hasEmptyFields && !hasFilledFields) {\n cssClass = 'specific-combination-blue';\n request.HasInvalidPeriod = false;\n } else if (hasFilledFields && !hasEmptyFields) {\n cssClass = 'specific-combination-green';\n request.HasInvalidPeriod = false;\n }\n\n return cssClass;\n }\n\n function isDisabled(slot) {\n var CSSclass = \"\";\n\n if (scope.selectedRequestTemp) {\n for (var i = 0; i < scope.selectedRequestTemp.LeaveRequestPriorityPeriods.length; i++) {\n if (scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots && scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots.length > 0 && (scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots[0].Id == slot.Id || scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots[0].EndDay >= slot.StartDay && scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots[0].StartDay <= slot.EndDay)) {\n CSSclass = \"disabled\";\n break;\n }\n }\n }\n\n return CSSclass;\n }\n\n function resetEditablePeriods() {\n for (var i = 0; i < scope.seasonRequests.length; i++) {\n for (var j = 0; j < scope.seasonRequests[i].LeaveRequestPriorityPeriods.length; j++) {\n scope.seasonRequests[i].LeaveRequestPriorityPeriods[j].isEditable = false;\n }\n }\n\n scope.IsEditEnabled = false;\n }\n\n function updateEditablePeriod(slot) {\n for (var i = 0; i < scope.seasonRequests.length; i++) {\n for (var j = 0; j < scope.seasonRequests[i].LeaveRequestPriorityPeriods.length; j++) {\n if (scope.seasonRequests[i].LeaveRequestPriorityPeriods[j].isEditable && slot && slot.Code) {\n scope.seasonRequests[i].LeaveRequestPriorityPeriods[j].LeaveRequestPrioritySlots = [slot];\n }\n }\n }\n\n resetEditablePeriods();\n }\n\n function removeSpecificCombination(priority) {\n var indexOfRemovedObj = null;\n\n for (var i = 0; i < scope.seasonRequests.length; i++) {\n if (scope.seasonRequests[i].Priority == priority) {\n indexOfRemovedObj = i;\n }\n }\n\n if (indexOfRemovedObj != null) {\n scope.seasonRequests.splice(indexOfRemovedObj, 1);\n scope.specificCombinations = $filter('filter')(scope.seasonRequests, {\n Type: 'All'\n });\n recalculatePriorities();\n }\n }\n\n function addNewSpecificCombination() {\n var newSpecificCombinationPriority = 1;\n\n if (scope.specificCombinations && scope.specificCombinations.length > 0) {\n newSpecificCombinationPriority = scope.specificCombinations.length + 1;\n }\n\n var newObj = {\n Type: \"All\",\n Priority: newSpecificCombinationPriority,\n LeaveRequestPriorityPeriods: []\n };\n scope.seasonRequests.push(newObj);\n updateLeaveRequestSeason();\n scope.specificCombinations = $filter('filter')(scope.seasonRequests, {\n Type: 'All'\n });\n scope.IsEditEnabled = false;\n }\n\n function updateLeaveRequestSeason() {\n scope.seasonConfiguration.ConfigurationId = scope.seasonConfiguration.Configuration.Id;\n\n for (var i = 0; i < scope.seasonRequests.length; i++) {\n for (var j = 0; j < scope.seasonConfiguration.Configuration.Periods.length; j++) {\n scope.seasonConfiguration.Configuration.Periods[j].ConfigurationPeriodId = scope.seasonConfiguration.Configuration.Periods[j].Id;\n }\n\n if (scope.seasonRequests[i].LeaveRequestPriorityPeriods && scope.seasonRequests[i].LeaveRequestPriorityPeriods.length == 0) {\n scope.seasonRequests[i].LeaveRequestPriorityPeriods = JSON.parse(JSON.stringify(scope.seasonConfiguration.Configuration.Periods));\n }\n }\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: 'views/LeaveRequest/specificCombinations.tpl.html',\n scope: {\n seasonConfiguration: '<',\n seasonRequests: '=',\n editable: '<'\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('LoginCtrl', LoginCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name LoginCtrl\r\n * @description \r\n * Manages the login view\r\n * @ngInject\r\n */\n\n function LoginCtrl($location, $timeout, $scope, localStorageMD5Service, UserFactory) {\n $scope.isSupported = isSupported;\n $scope.isSecure = UserFactory.isSecure();\n $scope.isLoggingIn = false;\n $scope.formData = {};\n $scope.goSecure = goSecure;\n $scope.errorName = \"\"; //$('button').tooltip(); //show tooltips on buttons\n\n $scope.goNormal = goNormal;\n $scope.moreInfo = false; //used to show more info on the page\n\n $scope.toggleMoreInfo = toggleMoreInfo;\n $scope.processForm = processForm;\n $scope.resetDevice = resetDevice;\n $scope.showTokenExtensionForm = false;\n $scope.showExtendTokenBootBox = showExtendTokenBootBox; //Unlock Password textbox -- \n\n document.getElementById(\"txtPass\").readOnly = true;\n $timeout(function () {\n document.getElementById(\"txtPass\").readOnly = false;\n }, 300); //--------------------------\n\n /**\r\n * Informs you if local storage is supported \r\n * @memberof LoginCtrl\r\n * @returns {boolean} isSupported\r\n */\n\n function isSupported() {\n return localStorageMD5Service.isSupported;\n }\n /**\r\n * Converts application to normal local storage mode \r\n * @memberof LoginCtrl\r\n */\n\n\n function goNormal() {\n var path = window.location.href;\n path = path.replace('?secure', '');\n window.location = path;\n location.reload();\n }\n /**\r\n * Proccess login form and try to login\r\n * @memberof LoginCtrl\r\n */\n\n\n function goSecure() {\n var path = window.location.href;\n path = path + '?secure';\n window.location = path;\n location.reload();\n }\n /**\r\n * Show More info\r\n * @memberof LoginCtrl\r\n */\n\n\n function toggleMoreInfo() {\n $scope.moreInfo = !$scope.moreInfo;\n }\n /**\r\n * Proccess login form and try to login\r\n * @memberof LoginCtrl\r\n */\n\n\n function processForm() {\n var un = $('#txtName').val();\n var pw = $('#txtPass').val();\n\n if (un != '') {\n $scope.formLogin.txtName.$setViewValue(un);\n }\n\n if (pw != '') {\n $scope.formLogin.txtPass.$setViewValue(pw);\n }\n\n if (!$scope.formLogin.$valid) return;\n $scope.isLoggingIn = true;\n var username = $scope.formLogin.txtName.$modelValue;\n var password = $scope.formLogin.txtPass.$modelValue; // call remote service to login\n\n $scope.isLoggingIn = true;\n UserFactory.login(username, password, function () {\n // load main page\n $scope.errorName = \"\";\n $location.path(\"/\");\n $scope.isLoggingIn = false;\n }, function (response) {\n $scope.isLoggingIn = false; // clear the password\n\n $scope.formData.password = \"\"; // display an error message\n\n if (response.status == 401) {\n showTokenExtensionForm();\n if (response.data && response.data.Message) $scope.errorName = response.data.Message.length > 1 ? response.data.Message : \"Wrong UserName or password, please try again.\";else $scope.errorName = \"Wrong UserName or password, please try again.\";\n } else if (response.status == 404) {\n $scope.errorName = \"Could not reach the remote server for authentication. Please connect to the Internet and try again.\";\n } else {\n $scope.errorName = \"An error occured during authentication. Please make sure you are connected to the Internet and try again.\";\n }\n\n ;\n }, function (response) {\n if (response.data && response.data.Message) $scope.errorName = response.data.Message.length > 1 ? response.data.Message : \"Could not extend your token\";else $scope.errorName = \"Wrong UserName or password, please try again.\";\n });\n }\n\n ;\n /**\r\n * Redirect to reset view\r\n * @memberof LoginCtrl\r\n */\n\n function resetDevice() {\n $location.path(\"/reset\");\n }\n /**\r\n * Shows the token extension form\r\n * @memberof LoginCtrl\r\n */\n\n\n function showTokenExtensionForm() {\n var username = $scope.formLogin.txtName.$modelValue;\n var user = UserFactory.getUser();\n if (user.token && !user.tokenExtended && username === user.username) $scope.showTokenExtensionForm = true;\n }\n /**\r\n * Extends the token\r\n * @memberof LoginCtrl\r\n */\n\n\n function extendToken() {\n UserFactory.extendToken(function () {\n $scope.errorName = \"\";\n $location.path(\"/\");\n $scope.isLoggingIn = false;\n }, function (response) {\n if (response.status === 401) {\n if (response.data && response.data.errorMessage) {\n $scope.errorName = response.data.Message;\n } else {\n $scope.errorName = 'We are sorry, we could not extend your token.';\n }\n }\n });\n }\n /**\r\n * Shows the bootbox for extending the token\r\n * @memberof LoginCtrl\r\n */\n\n\n function showExtendTokenBootBox() {\n bootbox.dialog({\n message: \"
We understand that you have forgot your password. We suggest you to contact with IT department in order to reset it. \\n\\t\\t\\t\\tTill then we can try to give you limited access to the application. Do you want to proceed?


\",\n title: \"Forgot password\",\n buttons: {\n confirm: {\n label: ' Yes',\n className: \"btn-success\",\n callback: function callback() {\n extendToken();\n }\n },\n cancel: {\n label: \"No\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"PilotAPIService\", PilotAPIService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name PilotAPIService\r\n * @description \r\n * Api login service\r\n * @ngInject\r\n */\n\n function PilotAPIService($http, $q, apiUrl) {\n return {\n /**\r\n * Login to Pilot Api\r\n * @memberof PilotAPIService\r\n * @param {number} username\r\n * @returns {string} password\r\n */\n login: function login(username, password) {\n var call = $q.defer();\n $http.post(apiUrl + '/login', {\n 'username': username,\n 'password': password\n }, {\n 'Content-Type': 'application/json'\n }).then(function (responseData) {\n call.resolve(responseData);\n }, function (err) {\n call.reject(err);\n });\n return call.promise;\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('UserFactory', UserFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name UserFactory\r\n * @description \r\n * Add, Update, Delete and Get User.\r\n * @ngInject\r\n */\n\n function UserFactory($log, localStorageMD5Service, $http, apiUrl, PilotAPIService, DataCleanerFactory, GenericService) {\n /**\r\n * Initialize the User\r\n * @memberof UserFactory\r\n */\n function User() {\n this.id = null;\n this.aimsId = null;\n this.username = null;\n this.name = null;\n this.shortname = null;\n this.position = null;\n this.hashedPwd = null;\n this.token = null;\n this.syncDialogLastDt = null;\n this.getDescription = getDescription;\n this.tokenExtended = false;\n }\n\n var service = {\n getUser: getUser,\n setUser: setUser,\n isSecure: isSecure,\n isLoggedIn: isLoggedIn,\n clearActiveUser: clearActiveUser,\n setActiveUser: setActiveUser,\n login: login,\n extendToken: extendToken\n };\n var objType = 'user';\n var objCallback = User; //Object Functions\n\n function getDescription() {\n if (this.aimsid == null && this.name == null) return '-null-';else return (this.aimsid || '?') + ' - ' + (this.name || '?');\n } //Factory Functions\n\n /**\r\n * Get User \r\n * @memberof UserFactory\r\n * @returns {Object} User\r\n */\n\n\n function getUser() {\n return GenericService.getOne(objType, objCallback);\n }\n /**\r\n * Save User \r\n * @memberof UserFactory\r\n * @param {Object} User\r\n */\n\n\n function setUser(user) {\n GenericService.saveAll(user, objType, objCallback);\n }\n /**\r\n * Checks if local storage is on secure mode \r\n * @memberof UserFactory\r\n * @param {boolean} isSecure\r\n */\n\n\n function isSecure() {\n return localStorageMD5Service.isSecure();\n }\n /**\r\n * Check if user exists and he has logged in\r\n * @memberof UserFactory\r\n * @param {boolean} isLoggedIn\r\n */\n\n\n function isLoggedIn() {\n var user = null;\n\n try {\n user = getUser();\n\n if (user != null) {\n var act = localStorageMD5Service.get('active');\n\n if (!act || !act.aimsId || act.aimsId != user.aimsId) {\n user = null;\n }\n } else user = null;\n } catch (e) {\n user = null;\n }\n\n return user;\n }\n /**\r\n * Clear Active User\r\n * @memberof UserFactory\r\n */\n\n\n function clearActiveUser() {\n localStorageMD5Service.remove('active');\n }\n /**\r\n * Save Active User \r\n * @memberof UserFactory\r\n * @param {Object} User\r\n */\n\n\n function setActiveUser(user) {\n if (user != null && user.aimsId != null) {\n var value = {\n aimsId: user.aimsId\n };\n localStorageMD5Service.set('active', value);\n }\n }\n /**\r\n * Add code to try to login locally if remote login fails with a 404 or timeout\r\n * @memberof UserFactory\r\n * @param {number} username The User Name\r\n * @param {string} password The User Password\r\n * @param {function} onsuccess callback function if the call is a success\r\n * @param {function} onerror callback function if the call failed\r\n * @param {function} onfinally callback function that runs on the end\r\n */\n\n\n function login(username, password, onsuccess, onerror, onfinally) {\n clearActiveUser();\n var q = PilotAPIService.login(username, password);\n q.then(function (response) {\n // if the user that tries to log in is different than the last\n // logged in user, then reset all stored server data\n var localUser = getUser();\n\n if (localUser != null && localUser.aimsId != null && localUser.aimsId.toString() != response.data.data.aimsId.toString()) {\n DataCleanerFactory.deleteAllData();\n } // delete any flights created locally, that do not have any local\n // reports\n\n\n DataCleanerFactory.deleteOrphanedLocalFlights(); // assign the logged in user\n\n var user = response.data.data; // save the hashed password for offline login\n\n user.hashedPwd = password.getHash();\n setUser(user);\n setActiveUser(user);\n\n if (typeof onsuccess == \"function\") {\n onsuccess();\n }\n });\n q[\"catch\"](function (response) {\n // try to login using local cache\n if (response.status != 401) {\n var newHashedPwd = password.getHash();\n var usr = getUser(); // check if we may try a local login, since the server is not\n // available\n\n if (usr != null && usr.username != null && usr.username == username && usr.hashedPwd != null) {\n // local login failed due to wrong password\n if (usr.hashedPwd != newHashedPwd) {\n // emulate response from server, when pass or userid is\n // incorrect\n response.status = 401;\n response.statusText = \"The username or password you entered is incorrect.\";\n } else {\n setUser(usr);\n setActiveUser(usr);\n\n if (typeof onsuccess == \"function\") {\n onsuccess();\n }\n\n return q;\n }\n }\n }\n\n if (typeof onerror == \"function\") {\n onerror(response);\n }\n });\n q[\"finally\"](function (response) {\n if (typeof onfinally == \"function\") {\n onfinally();\n }\n });\n return q;\n }\n /**\r\n * the function that extends the token for limited time if a user forgot their password\r\n * @memberof UserFactory\r\n * @param {function} onsuccess callback function if the call is a success\r\n * @param {function} onerror callback function if the call failed\r\n */\n\n\n function extendToken(onsuccess, onerror) {\n var user = getUser();\n $http.post(apiUrl + '/login/extendtoken', {\n 'Token': user.token\n }, {\n 'Content-Type': 'application/json'\n }).then(function (response) {\n user.token = response.data.data;\n user.tokenExtended = true;\n setUser(user);\n setActiveUser(user);\n\n if (typeof onsuccess == \"function\") {\n onsuccess();\n }\n })[\"catch\"](function (response) {\n if (typeof onerror == \"function\") {\n onerror(response);\n }\n });\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CalendarRedirectModalCtrl', CalendarRedirectModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CalendarRedirectModalCtrl\r\n * @description \r\n * Modal to redirect to Calendar after all mandatory memos are read\r\n * @ngInject\r\n */\n\n function CalendarRedirectModalCtrl($scope, $location, $uibModalInstance) {\n $scope.gotoCalendar = gotoCalendar;\n\n function gotoCalendar() {\n cancel();\n $location.path('/');\n }\n /**\r\n * Closes modal\r\n * @memberof CalendarRedirectModalCtrl\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('cancel');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('MandatoryModalCtrl', MandatoryModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name MandatoryModalCtrl\r\n * @description \r\n * Warning Modal about unread mandatory memos\r\n * @ngInject\r\n */\n\n function MandatoryModalCtrl($scope, mandatoryUnread, MemoFactory, $uibModal, $routeParams, $location, $uibModalInstance) {\n $scope.mandatoryUnread = mandatoryUnread;\n $scope.gotoMandatoryUnreadMemos = gotoMandatoryUnreadMemos;\n\n function gotoMandatoryUnreadMemos() {\n $location.path('/memos/unreadMandatory');\n cancel();\n }\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('cancel');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('MemoFactory', MemoFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name MemoFactory\r\n * @description \r\n * Add, Update, Delete and Get Memos.\r\n * @ngInject\r\n */\n\n function MemoFactory(FlightFactory, GroundDutyFactory, IndexedDBService, PaxInfoFactory, $q) {\n /**\r\n * Initialize the Memo\r\n * @memberof MemoFactory\r\n */\n function Memo() {\n this.Id = null;\n this.expired = false;\n }\n\n var objType = 'Memos';\n var objCallback = Memo;\n var service = {\n getMemosFromStorage: getMemosFromStorage,\n setMemosToStorage: setMemosToStorage,\n clearMemosFromStorage: clearMemosFromStorage,\n getMemosForFlight: getMemosForFlight,\n getStoredMemosIds: getStoredMemosIds,\n saveOneMemoToStorage: saveOneMemoToStorage,\n addMemoToStorage: addMemoToStorage,\n deleteMemoFromStorage: deleteMemoFromStorage,\n setMemosFromServer: setMemosFromServer,\n getMemosForGroundDuty: getMemosForGroundDuty,\n getMemosForCrewRoute: getMemosForCrewRoute,\n getUnreadMemos: getUnreadMemos,\n getMandatoryUnreadMemos: getMandatoryUnreadMemos,\n getAllUnreadGroundDutyMemos: getAllUnreadGroundDutyMemos,\n markGroundDutiesUnread: markGroundDutiesUnread,\n info: info\n };\n /**\r\n * Get Memos\r\n * @memberof MemoFactory\r\n * @param {function} callback \r\n */\n\n function getMemosFromStorage(callback) {\n //return GenericService.list(objType,objCallback);\n IndexedDBService.getAll(objType).then(function (results) {\n callback(results);\n });\n }\n\n ;\n /**\r\n * Set Memos\r\n * @memberof MemoFactory\r\n * @param {array} Memos a list of memos to set to indexedDB\r\n */\n\n function setMemosToStorage(Memos) {\n IndexedDBService.addAll(objType, Memos);\n }\n\n ;\n /**\r\n * Update Memo to Storage\r\n * @memberof MemoFactory\r\n * @param {object} Memo a memo\r\n */\n\n function saveOneMemoToStorage(Memo) {\n IndexedDBService.put(objType, Memo);\n }\n\n ;\n\n function info() {\n IndexedDBService.info(objType);\n }\n /**\r\n * Add Memo to Storage\r\n * @memberof MemoFactory\r\n * @param {object} Memo a memo\r\n */\n\n\n function addMemoToStorage(Memo) {\n IndexedDBService.add(objType, Memo);\n }\n\n ;\n /**\r\n * Delete Memo from Storage\r\n * @memberof MemoFactory\r\n * @param {number} MemoId The unique Identifier of the Memo\r\n */\n\n function deleteMemoFromStorage(MemoId) {\n IndexedDBService.remove(objType, MemoId);\n }\n\n ;\n /**\r\n * Clear Memo from Storage\r\n * @memberof MemoFactory\r\n */\n\n function clearMemosFromStorage() {\n IndexedDBService.removeAll(objType);\n }\n\n ;\n\n function ValidateCountryCategory(criteria, isDepartureCategory, isArrivalCategory) {\n var isValid = false;\n\n if (criteria.Special == \"Specific\") {\n isValid = (criteria.Field == \"Intra\" && isDepartureCategory || criteria.Field == \"Extra\" && !isDepartureCategory) && (criteria.FieldOptional == \"Intra\" && isArrivalCategory || criteria.FieldOptional == \"Extra\" && !isArrivalCategory);\n } else {\n if (criteria.Field == \"Intra\") {\n isValid = isDepartureCategory && criteria.Special != \"To\" || isArrivalCategory && criteria.Special != \"From\";\n } else if (criteria.Field == \"Extra\") {\n isValid = !isDepartureCategory && criteria.Special != \"To\" || !isArrivalCategory && criteria.Special != \"From\";\n }\n }\n\n return isValid;\n }\n\n function isValid(field, departureField, arrivalField, special) {\n var isValid = false;\n var isDeparture = departureField == field;\n var isArrival = arrivalField == field;\n\n if (special == \"From\") {\n isValid = isDeparture;\n } else if (special == \"To\") {\n isValid = isArrival;\n } else {\n isValid = isArrival || isDeparture;\n }\n\n return isValid;\n }\n\n function getMemosForGroundDuty(Id, callback) {\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(Id);\n\n if (!groundDuty) {\n return [];\n }\n\n getMemosFromStorage(function (results) {\n var memosCollection = results;\n var groundDutyMemos = [];\n var fromDutyDate = new Date(groundDuty.DutyDate).getTime();\n var toDutyDate = new Date(groundDuty.DutyDate).getTime();\n\n for (var i = 0; i < memosCollection.length; i++) {\n if (new Date(memosCollection[i].ValidFrom).getTime() <= fromDutyDate && new Date(memosCollection[i].ValidTo).getTime() >= toDutyDate) {\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\n var item = memosCollection[i].MemoCriteria[j];\n\n if (item.QueryType == \"GroundDutyCode\" && (item.Field == groundDuty.DutyNo || item.Field == groundDuty.GroundDutyNo)) {\n groundDutyMemos.push(memosCollection[i]);\n break;\n }\n }\n }\n }\n\n callback(groundDutyMemos);\n });\n }\n /**\r\n * Get Memos that are relate to this flight\r\n * @memberof MemoFactory\r\n * @param {number} Id The unique Identifier of the Memo\r\n * @param {function} callback The callback function\r\n */\n\n\n function getMemosForFlight(Id, callback) {\n var flight = FlightFactory.getFlightFromStorage(Id);\n\n if (!flight) {\n flight = FlightFactory.getLocalFlightFromStorage(Id);\n }\n\n if (!flight) {\n return [];\n }\n\n getMemosFromStorage(function (results) {\n var memosCollection = results;\n var flightMemos = [];\n PaxInfoFactory.getPaxInfoFromStorage(flight.FlightId, function (paxInfo) {\n for (var i = 0; i < memosCollection.length; i++) {\n if (new Date(memosCollection[i].ValidFrom).getTime() <= new Date(flight.ScheduledDeparture).getTime() && new Date(memosCollection[i].ValidTo).getTime() >= new Date(flight.ScheduledArrival).getTime()) {\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\n var item = memosCollection[i].MemoCriteria[j];\n\n if (item.AcRegistration == flight.AcTailNo || item.QueryType == \"Airport\" && isValid(item.Airport, flight.Departure, flight.Arrival, item.Special) || item.FlightNo == flight.FlightNo || item.AcType == flight.AcType || isValidZone(item, flight.Zones) || item.RouteStart == flight.Departure && item.RouteEnd == flight.Arrival || item.ViceVersa && item.RouteStart == flight.Arrival && item.RouteEnd == flight.Departure || item.QueryType == \"Country\" && isValid(item.Country, flight.DepartureCountry, flight.ArrivalCountry, item.Special) || item.QueryType == \"Schengen\" && ValidateCountryCategory(item, flight.DepartureSchengen, flight.ArrivalSchengen) || item.QueryType == \"European\" && ValidateCountryCategory(item, flight.DepartureEU, flight.ArrivalEU) || paxInfo && item.QueryType == \"SsrCode\" && PassengersHasSsrCode(paxInfo, item) || item.QueryType == \"TrainingId\" && item.Field == flight.TrainingIndicatorId) {\n flightMemos.push(memosCollection[i]);\n break;\n }\n }\n }\n }\n\n callback(flightMemos);\n });\n });\n }\n /**\r\n * Get Memos that are related to this crew route, by combining multiple flight and groundDuty memos \r\n * @memberof MemoFactory\r\n * @param {number} DutyNo Crew Route Identifier\r\n * @param {number} DutyDay Crew Route Day\r\n * @param {function} callback The callback function\r\n */\n\n\n function getMemosForCrewRoute(DutyNo, DutyDay, callback) {\n var groundDuties = GroundDutyFactory.getGroundDutiesByDutyNo(DutyNo, DutyDay);\n var flights = FlightFactory.getFlightsByDutyNo(DutyNo, DutyDay);\n PaxInfoFactory.getAllPaxInfoFromStorage(function (paxInfoResult) {\n getMemosFromStorage(function (results) {\n var memosCollection = results;\n var allMemos = [];\n\n for (var i = 0; i < memosCollection.length; i++) {\n var inserted = false; //first check if memo is connected with any groundDuties\n\n for (var g = 0; g < groundDuties.length; g++) {\n var fromDutyDate = new Date(groundDuties[g].DutyDate).getTime();\n var toDutyDate = new Date(groundDuties[g].DutyDate).getTime();\n\n if (new Date(memosCollection[i].ValidFrom).getTime() <= fromDutyDate && new Date(memosCollection[i].ValidTo).getTime() >= toDutyDate) {\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\n var item = memosCollection[i].MemoCriteria[j];\n\n if (item.QueryType == \"GroundDutyCode\" && (item.Field == groundDuties[g].DutyNo || item.Field == groundDuties[g].GroundDutyNo)) {\n allMemos.push(memosCollection[i]);\n inserted = true;\n break;\n }\n }\n }\n\n if (inserted) break; //don't check other groundDuties - memo is already inserted\n } //if memo was checked for all groundDuties and was not connected with any, check in flights\n\n\n if (!inserted) {\n for (var f = 0; f < flights.length; f++) {\n var paxInfo = null;\n\n if (new Date(memosCollection[i].ValidFrom).getTime() < new Date(flights[f].ScheduledDeparture).getTime() && new Date(memosCollection[i].ValidTo).getTime() > new Date(flights[f].ScheduledArrival).getTime()) {\n //check if flight has paxInfo \n for (var p = 0; p < paxInfoResult.length; p++) {\n if (paxInfoResult[p].FlightId == flights[f].FlightId) {\n paxInfo = paxInfoResult[p];\n break;\n }\n }\n\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\n var item = memosCollection[i].MemoCriteria[j];\n\n if (item.AcRegistration == flights[f].AcTailNo || item.QueryType == \"Airport\" && isValid(item.Airport, flights[f].Departure, flights[f].Arrival, item.Special) || item.FlightNo == flights[f].FlightNo || item.AcType == flights[f].AcType || isValidZone(item.Zone, flights[f].Zones) || item.RouteStart == flights[f].Departure && item.RouteEnd == flights[f].Arrival || item.ViceVersa && item.RouteStart == flights[f].Arrival && item.RouteEnd == flights[f].Departure || item.QueryType == \"Country\" && isValid(item.Country, flights[f].DepartureCountry, flights[f].ArrivalCountry, item.Special) || item.QueryType == \"Schengen\" && ValidateCountryCategory(item, flights[f].DepartureSchengen, flights[f].ArrivalSchengen) || item.QueryType == \"European\" && ValidateCountryCategory(item, flights[f].DepartureEU, flights[f].ArrivalEU) || paxInfo && item.QueryType == \"SsrCode\" && PassengersHasSsrCode(paxInfo, item) || item.QueryType == \"TrainingId\" && item.Field == flights[f].TrainingIndicatorId) {\n allMemos.push(memosCollection[i]);\n inserted = true;\n break;\n }\n }\n }\n\n if (inserted) break; //don't check other flights - memo is already inserted\n }\n }\n }\n\n callback(allMemos);\n });\n });\n }\n\n function PassengersHasSsrCode(paxInfo, memoCriterion) {\n var retVal = false;\n\n for (var key in paxInfo.PassengerSummaryY) {\n if (key === memoCriterion.Field && paxInfo.PassengerSummaryY[key] > 0) {\n retVal = true;\n break;\n }\n }\n\n for (var key in paxInfo.PassengerSummaryX) {\n if (key === memoCriterion.Field && paxInfo.PassengerSummaryY[key] > 0) {\n retVal = true;\n break;\n }\n }\n\n return retVal;\n }\n /**\r\n * Check if the zone is valid\r\n * @memberof MemoFactory\r\n * @param {CriteriaZone} Zone from MemoCriteria\r\n * @param {FlightZones} List of Zones from flight\r\n */\n\n\n function isValidZone(CriteriaZone, FlightZones) {\n if (!CriteriaZone || CriteriaZone.Type != \"Zone\" || !FlightZones || FlightZones.length == 0) {\n return false;\n } else {\n // some is equivalent to Any()\n var zoneExist = FlightZones.some(function (item) {\n return item.Title.toUpperCase() == CriteriaZone.Field.toUpperCase() && item.Class.toUpperCase() == CriteriaZone.FieldOptional.toUpperCase();\n });\n return zoneExist;\n }\n }\n /**\r\n * Get Stored Memos \r\n * @memberof MemoFactory\r\n * @param {function} callback The callback function\r\n */\n\n\n function getStoredMemosIds(callback) {\n getMemosFromStorage(function (memos) {\n var memoIds = [];\n\n for (var i = 0; i < memos.length; i++) {\n var memoIdRead = {\n Id: memos[i].Id,\n ReadDt: memos[i].ReadDt\n };\n memoIds.push(memoIdRead);\n }\n\n callback(memoIds);\n });\n }\n /**\r\n * set memos from server api \r\n * @memberof MemoFactory\r\n * @param {array} memos The memos \r\n * @param {array} memoIdsToSend The old memos of the storage\r\n * @param {string} lastSyncDate The last Sync Date \r\n */\n\n\n function setMemosFromServer(memos, memoIdsToSend, lastSyncDate) {\n if (!memoIdsToSend || memoIdsToSend.length == 0 || !lastSyncDate) {\n setMemosToStorage(memos);\n } else {\n for (var j = 0; j < memos.length; j++) {\n var IsMemoIncluded = false;\n\n for (var h = 0; h < memoIdsToSend.length; h++) {\n if (memos[j].Id == memoIdsToSend[h].Id) {\n IsMemoIncluded = true;\n break;\n }\n }\n\n if (IsMemoIncluded) {\n memos[j].IsUpdated = true;\n memos[j].IsNew = false;\n saveOneMemoToStorage(memos[j]);\n } else {\n memos[j].IsNew = true;\n memos[j].IsUpdated = false;\n addMemoToStorage(memos[j]);\n }\n }\n }\n }\n /**\r\n * Get Unread Memos \r\n * @memberof MemoFactory\r\n */\n\n\n function getUnreadMemos(callback) {\n getMemosFromStorage(function (memos) {\n if (!memos) return [];\n var result = [];\n var arrayLength = memos.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (!memos[i].ReadDt) {\n result.push(memos[i]);\n }\n }\n\n callback(result);\n });\n }\n /**\r\n * Get Unread Mandatory Memos\r\n * @memberof MemoFactory\r\n */\n\n\n function getMandatoryUnreadMemos(callback) {\n getMemosFromStorage(function (memos) {\n if (!memos) return [];\n var result = [];\n var arrayLength = memos.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (!memos[i].ReadDt && memos[i].IsMandatory) {\n result.push(memos[i]);\n }\n }\n\n callback(result);\n });\n }\n /**\r\n * Gets all unread memos related to a Ground Duty\r\n * @memberof MemoFactory\r\n */\n\n\n function getAllUnreadGroundDutyMemos(callback) {\n getMemosFromStorage(function (results) {\n var memosCollection = results;\n var unreadGroundDutyMemos = [];\n\n for (var i = 0; i < memosCollection.length; i++) {\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\n var item = memosCollection[i].MemoCriteria[j];\n\n if (item.QueryType == \"GroundDutyCode\" && memosCollection[i].ReadDt == null) {\n unreadGroundDutyMemos.push(memosCollection[i]);\n break;\n }\n }\n }\n\n callback(unreadGroundDutyMemos);\n });\n }\n /**\r\n * Flags Ground Duties if they have at least one unread memo\r\n * @memberof MemoFactory\r\n */\n\n\n function markGroundDutiesUnread() {\n getAllUnreadGroundDutyMemos(function (groundDutyMemos) {\n var groundDuties = GroundDutyFactory.getGroundDutiesFromStorage();\n\n if (groundDuties != null) {\n for (var i = 0; i < groundDuties.length; i++) {\n groundDuties[i].Unread = false; //check if this ground duty has any unread ground duty memo\n\n var fromDutyDate = new Date(groundDuties[i].DutyDate).getTime();\n var toDutyDate = new Date(groundDuties[i].DutyDate).getTime();\n\n for (var j = 0; j < groundDutyMemos.length; j++) {\n if (new Date(groundDutyMemos[j].ValidFrom).getTime() <= fromDutyDate && new Date(groundDutyMemos[j].ValidTo).getTime() >= toDutyDate) {\n for (var z = 0; z < groundDutyMemos[j].MemoCriteria.length; z++) {\n var item = groundDutyMemos[j].MemoCriteria[z];\n\n if (item.Field == groundDuties[i].DutyNo || item.Field == groundDuties[i].GroundDutyNo) {\n groundDuties[i].Unread = true;\n break;\n }\n }\n }\n }\n }\n\n GroundDutyFactory.setGroundDutiesToStorage(groundDuties);\n }\n });\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('MemoImagesFactory', MemoImagesFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name MemoImagesFactory\r\n * @description \r\n * Add, Update, Delete and Get Memo's Images.\r\n * @ngInject\r\n */\n\n function MemoImagesFactory(GenericService, IndexedDBService) {\n /**\r\n * Initialize the MemoImage\r\n * @memberof MemoImagesFactory\r\n */\n function MemoImage() {\n this.Id = null;\n }\n\n var objType = 'MemoImages';\n var objCallback = MemoImage;\n var service = {\n getMemoImagesFromStorage: getMemoImagesFromStorage,\n setMemoImagesToStorage: setMemoImagesToStorage,\n saveOneMemoImageToStorage: saveOneMemoImageToStorage,\n addMemoImageToStorage: addMemoImageToStorage,\n deleteMemoImageFromStorage: deleteMemoImageFromStorage,\n deleteMemoImageByMemoId: deleteMemoImageByMemoId,\n setImagesToServer: setImagesToServer,\n clearMemoImagesFromStorage: clearMemoImagesFromStorage,\n getMemoImagesByIndex: getMemoImagesByIndex\n };\n /**\r\n * Get Memo Images \r\n * @memberof MemoImagesFactory\r\n * @param {function} callback \r\n */\n\n function getMemoImagesFromStorage(callback) {\n //return GenericService.list(objType,objCallback);\n IndexedDBService.getAll(objType).then(function (results) {\n callback(results);\n });\n }\n\n ;\n /**\r\n * Get Memo Images by memo Id\r\n * @memberof MemoImagesFactory\r\n * @param {number} id Memo Id \r\n * @param {function} callback \r\n */\n\n function getMemoImagesByIndex(id, callback) {\n //return GenericService.list(objType,objCallback);\n IndexedDBService.getByIndex(objType, 'memoId', id).then(function (results) {\n callback(results);\n });\n }\n\n ;\n /**\r\n * Add Memo Images \r\n * @memberof MemoImagesFactory\r\n * @param {array} MemoImages List of memo images\r\n */\n\n function setMemoImagesToStorage(MemoImages) {\n //GenericService.saveAll(Memos,objType,objCallback);\n IndexedDBService.addAll(objType, MemoImages);\n }\n\n ;\n /**\r\n * Update Memo Images \r\n * @memberof MemoImagesFactory\r\n * @param {object} MemoImage a memo image\r\n */\n\n function saveOneMemoImageToStorage(MemoImage) {\n IndexedDBService.put(objType, MemoImage);\n }\n\n ;\n /**\r\n * Add Memo Image\r\n * @memberof MemoImagesFactory\r\n * @param {object} MemoImage a memo image\r\n */\n\n function addMemoImageToStorage(MemoImage) {\n IndexedDBService.add(objType, MemoImage);\n }\n\n ;\n /**\r\n * Delete Memo Image\r\n * @memberof MemoImagesFactory\r\n * @param {number} MemoImageId a memo image Id\r\n */\n\n function deleteMemoImageFromStorage(MemoImageId) {\n IndexedDBService.remove(objType, MemoImageId);\n }\n\n ;\n /**\r\n * Delete Memo Image by MemoId\r\n * @memberof MemoImagesFactory\r\n * @param {number} MemoId a memo Id\r\n */\n\n function deleteMemoImageByMemoId(MemoId) {\n IndexedDBService.removeByIndex(objType, 'memoId', MemoId);\n }\n\n ;\n /**\r\n * Set Memo Image by api call\r\n * @memberof MemoImagesFactory\r\n * @param {array} images List of memo images\r\n */\n\n function setImagesToServer(images) {\n for (var i = 0; i < images.length; i++) {\n addMemoImageToStorage(images[i]);\n }\n }\n /**\r\n * Remove Memo Images from storage\r\n * @memberof MemoImagesFactory\r\n */\n\n\n function clearMemoImagesFromStorage() {\n IndexedDBService.removeAll(objType);\n }\n\n ;\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('MemoModalCtrl', MemoModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name MemoModalCtrl\r\n * @description \r\n * Manages the Memo Modal\r\n * @ngInject\r\n */\n\n function MemoModalCtrl($scope, memo, $uibModalInstance, $sce, MemoImagesFactory) {\n $scope.memo = memo;\n $scope.cancel = cancel;\n $scope.hasCountry = false;\n $scope.hasFlightNo = false;\n $scope.hasAirport = false;\n $scope.hasRoute = false;\n $scope.hasAcType = false;\n $scope.hasZone = false;\n $scope.hasEuropean = false;\n $scope.hasSchengen = false;\n $scope.hasAcRegistration = false;\n $scope.hasSsrCode = false;\n $scope.hasTrainingIndicator = false;\n $scope.hasGroundDuties = false;\n $scope.hasNone = true;\n $scope.images = [];\n $scope.showImage = showImage;\n $scope.body = $sce.trustAsHtml(memo.Body);\n MemoImagesFactory.getMemoImagesByIndex(memo.Id, function (results) {\n $scope.images = results;\n });\n /**\r\n * Open A new Tab and show the image \r\n * @memberof MemoModalCtrl\r\n * @param {string} src Base64 endode string of Image\r\n */\n\n function showImage(src) {\n var image = new Image();\n image.src = src;\n var w = window.open(\"\");\n w.document.write(image.outerHTML);\n }\n /**\r\n * Show the criteria of the memo \r\n * @memberof MemoModalCtrl\r\n */\n\n\n (function changeFlags() {\n angular.forEach(memo.MemoCriteria, function (criteria) {\n if (criteria.Country || criteria.Type == \"Country\" && criteria.Field) {\n $scope.hasCountry = true;\n $scope.hasNone = false;\n }\n\n if (criteria.FlightNo || criteria.Type == \"FlightNo\" && criteria.Field) {\n $scope.hasFlightNo = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Airport || criteria.Type == \"Airport\" && criteria.Field) {\n $scope.hasAirport = true;\n $scope.hasNone = false;\n }\n\n if (criteria.RouteStart || criteria.Type == \"RouteStart\" && criteria.Field) {\n $scope.hasRoute = true;\n $scope.hasNone = false;\n }\n\n if (criteria.AcType || criteria.Type == \"AcType\" && criteria.Field) {\n $scope.hasAcType = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Zone || criteria.Type == \"Zone\" && criteria.Field) {\n $scope.hasZone = true;\n $scope.hasNone = false;\n }\n\n if (criteria.AcRegistration || criteria.Type == \"AcRegistration\" && criteria.Field) {\n $scope.hasAcRegistration = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Type == \"SsrCode\" && criteria.Field) {\n $scope.hasSsrCode = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Type == \"TrainingId\" && criteria.Field) {\n $scope.hasTrainingIndicator = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Type == \"European\" && criteria.Field) {\n $scope.hasEuropean = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Type == \"Schengen\" && criteria.Field) {\n $scope.hasSchengen = true;\n $scope.hasNone = false;\n }\n\n if (criteria.Type == \"GroundDutyCode\" && criteria.Field) {\n $scope.hasGroundDuties = true;\n $scope.hasNone = false;\n }\n });\n })();\n /**\r\n * Close the modal\r\n * @memberof MemoModalCtrl\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('close');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('MemosCtrl', MemosCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name MemosCtrl\r\n * @description \r\n * Manages the Memos View\r\n * @ngInject\r\n */\n\n function MemosCtrl($scope, MemoFactory, $uibModal, $routeParams) {\n $scope.memosByCategory = [];\n $scope.openMemo = openMemo;\n $scope.searchText = '';\n $scope.searchMemos = searchMemos;\n $scope.state = 'memos';\n $scope.select = select;\n $scope.toggleSidePanel = toggleSidePanel;\n $scope.searchResultsCount = searchResultsCount;\n $scope.shownSideMenu = false;\n $scope.active = 1;\n MemoFactory.getMemosFromStorage(function (results) {\n var tommorowTimestamp = new Date().getTime() + 86400000;\n\n for (var i = 0; i < results.length; i++) {\n results[i].expired = new Date(results[i].ValidTo).getTime() < tommorowTimestamp;\n } //Remove from Library memos that belong in \"Training Surveys\" category\n\n\n var memos = [];\n\n for (var i = 0; i < results.length; i++) {\n if (results[i].Category != \"Training Surveys\") {\n memos.push(results[i]);\n }\n }\n\n $scope.memos = memos;\n var memosByCategory = MemosByCategories(memos);\n\n if ($routeParams.filter == 'unread') {\n $scope.radioModel = 'Unread';\n searchMemos($scope.searchText, 'Unread');\n } else if ($routeParams.filter == 'unreadMandatory') {\n $scope.radioModel = 'UnreadMandatory';\n searchMemos($scope.searchText, 'UnreadMandatory');\n } else {\n $scope.radioModel = 'All'; //default category on load\n\n $scope.selected = memosByCategory[0];\n $scope.memosByCategory = memosByCategory;\n searchResultsCount();\n }\n });\n\n function searchResultsCount() {\n var sum = 0;\n\n for (var i = 0; i < $scope.memosByCategory.length; i++) {\n sum += $scope.memosByCategory[i].memoList.length;\n }\n\n $scope.searchResults = sum;\n }\n\n function MemosByCategories(memoList) {\n var memos = [];\n\n for (var i = 0; i < memoList.length; i++) {\n var memo = memoList[i];\n\n if (!memos.filter(function (e) {\n return e.Category == memo.Category;\n }).length > 0) {\n memos.push({\n Category: memo.Category,\n memoList: [memo],\n filterList: [memo]\n });\n } else if (memos.filter(function (e) {\n return e.Category == memo.Category;\n }).length > 0) {\n memos.filter(function (object) {\n if (object.Category == memo.Category) {\n return object;\n }\n\n ;\n })[0].memoList.push(memo);\n }\n }\n\n return memos.dynamicSort(\"Category\", true);\n }\n\n function select(category) {\n selectMemoCategory(category);\n toggleSidePanel();\n }\n\n function selectMemoCategory(category) {\n var memosByCategory = $scope.memosByCategory;\n\n for (var i = 0; i < memosByCategory.length; i++) {\n if (memosByCategory[i].Category == category.Category) {\n $scope.selected = memosByCategory[i];\n break;\n }\n }\n }\n\n function toggleSidePanel() {\n $scope.shownSideMenu = !$scope.shownSideMenu;\n } //Pagination\n\n\n $scope.pageOptions = [{\n name: '5',\n value: '5'\n }, {\n name: '8',\n value: '8'\n }, {\n name: '15',\n value: '15'\n }, {\n name: '30',\n value: '30'\n }, {\n name: '50',\n value: '50'\n }];\n $scope.viewby = $scope.pageOptions[1].value;\n $scope.currentPage = 1;\n $scope.itemsPerPage = $scope.viewby;\n $scope.maxSize = 5; //Number of pager buttons to show\n\n $scope.setPage = setPage;\n $scope.setItemsPerPage = setItemsPerPage; //Controller functions\n\n /**\r\n * Set pagination page number\r\n * @memberof MemosCtrl\r\n * @param {number} pageNo list page number\r\n */\n\n function setPage(pageNo) {\n $scope.currentPage = pageNo;\n }\n /**\r\n * Set items per page \r\n * @memberof MemosCtrl\r\n * @param {number} num the Number of items to show per page\r\n */\n\n\n function setItemsPerPage(num) {\n $scope.itemsPerPage = num;\n $scope.currentPage = 1; //reset to first paghe\n }\n /**\r\n * View Selected Memo\r\n * @memberof MemosCtrl\r\n * @param {object} memo The selected Memo\r\n */\n\n\n function openMemo(_memo) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Memos/dlgMemo.html',\n controller: 'MemoModalCtrl',\n size: 'lg',\n keyboard: false,\n resolve: {\n memo: function memo() {\n return _memo;\n }\n }\n });\n modalInstance.result.then(function () {\n if (_memo.ReadDt == null) {\n _memo.ReadDt = new Date();\n MemoFactory.saveOneMemoToStorage(_memo); //check if memo is connected to a ground duty\n\n for (var i = 0; i < _memo.MemoCriteria.length; i++) {\n var item = _memo.MemoCriteria[i];\n\n if (item.QueryType == \"GroundDutyCode\") {\n MemoFactory.markGroundDutiesUnread();\n break;\n }\n }\n\n searchMemos($scope.searchText, '');\n }\n });\n }\n\n function redirectModal() {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Memos/dlgCalendarRedirect.html',\n controller: 'CalendarRedirectModalCtrl',\n backdrop: 'static',\n size: 'md',\n keyboard: false\n });\n }\n /**\r\n * Search the selected text In Memo Title and body\r\n * @memberof MemosCtrl\r\n * @param {string} text The desired search text\r\n */\n\n\n function searchMemos(text, filter) {\n if (filter != '') {\n $scope.radioModel = filter;\n }\n\n var filteredMemos = [];\n var searchText = text.toLowerCase();\n var newList = $scope.memos;\n\n for (var i = 0; i < newList.length; i++) {\n if ($scope.radioModel == 'General') {\n if (newList[i].MemoCriteria.length > 0) {\n continue;\n }\n } else if ($scope.radioModel == 'Unread') {\n if (newList[i].ReadDt) {\n continue;\n }\n } else if ($scope.radioModel == 'Mandatory') {\n if (!newList[i].IsMandatory) {\n continue;\n }\n } else if ($scope.radioModel == 'UnreadMandatory') {\n if (newList[i].ReadDt || !newList[i].IsMandatory) {\n continue;\n }\n }\n\n var memoTitle = newList[i].Title.toLowerCase();\n var memoBody = newList[i].Body.toLowerCase();\n\n if (memoTitle.indexOf(searchText) > -1) {\n filteredMemos.push(newList[i]);\n continue;\n }\n\n if (memoBody.indexOf(searchText) > -1) {\n filteredMemos.push(newList[i]);\n }\n }\n\n var memosByCategory = MemosByCategories(filteredMemos);\n $scope.memosByCategory = memosByCategory;\n searchResultsCount();\n\n if (!memosByCategory.length) {\n $scope.selected == null; //selected could be null if search didn't return any results\n\n if ($scope.radioModel == 'UnreadMandatory') {\n //all mandatory memos were read\n // $scope.radioModel = 'All';\n // searchMemos(searchText, '');\n redirectModal();\n }\n } else if ($scope.selected == null) {\n //search now returns results\n $scope.selected = memosByCategory[0];\n }\n\n var select = false;\n\n for (var i = 0; i < memosByCategory.length; i++) {\n if ($scope.selected.Category == memosByCategory[i].Category) {\n selectMemoCategory(memosByCategory[i]);\n select = true;\n break;\n }\n }\n\n if (!select) $scope.selected = memosByCategory[0];\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('MessageCtrl', MessageCtrl);\n /* @ngInject */\n\n function MessageCtrl($scope, $location, MessageFactory, $filter, $sce) {\n var messages = [];\n $scope.messages = MessageFactory.getMessagesFromStorage();\n messages = $scope.messages;\n $scope.state = 'messages'; //Initialized scope variables\n\n $scope.openMessage = openMessage;\n $scope.isEnabled = false;\n $scope.messageCount = messages.length;\n $scope.trustAsHtml = trustAsHtml;\n $scope.setupView = setupView;\n /**\r\n * Trust this html style text\r\n * @memberof MessageCtrl\r\n * @param {string} body The body message\r\n */\n\n function trustAsHtml(body) {\n return $sce.trustAsHtml(body);\n }\n /**\r\n * Setup the message View\r\n * @memberof MessageCtrl\r\n * @param {boolean} isEnabled Show only unread messages\r\n */\n\n\n function setupView(isEnabled) {\n $scope.messages = $filter('messageFilter')(messages, isEnabled);\n }\n /**\r\n * View Selected message\r\n * @memberof MessageCtrl\r\n * @param {object} message The selected Message\r\n */\n\n\n function openMessage(message) {\n if (message.ReadDt == null) {\n MessageFactory.markReaden(message.Id);\n message.ReadDt = new Date();\n }\n }\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.filter('messageFilter', messageFilter);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name messageFilter\r\n * @description \r\n * Filters messages in order to show only the unread.\r\n * @ngInject\r\n */\n\n function messageFilter() {\n return function (input, isEnable) {\n if (isEnable) {\n var result = [];\n\n for (var i = 0; i < input.length; i++) {\n if (input[i].ReadDt == null) {\n result.push(input[i]);\n }\n }\n\n return result;\n } else {\n return input;\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('MessageFactory', MessageFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name MessageFactory\r\n * @description \r\n * Add, Update, Delete and Get Messages.\r\n * @ngInject\r\n */\n\n function MessageFactory(GenericService) {\n /**\r\n * Initialize the Message\r\n * @memberof MessageFactory\r\n */\n function Message() {\n this.Id = null;\n this.Title = null;\n this.AuthorName = null;\n this.Body = null;\n this.AcType = null;\n this.AirportA = null;\n this.AirportB = null;\n this.Country = null;\n this.FlightDirection = null;\n this.FlightNo = null;\n this.ValidFrom = null;\n this.ValidTo = null;\n this.PositionCP = true;\n this.PositionFA = true;\n this.PositionFO = true;\n this.PositionSA = true;\n this.QueryType = null;\n this.ReadDt = null;\n this.Registration = null;\n this.FeedbackCause = null;\n }\n\n var objType = 'messages';\n var objCallback = Message;\n var service = {\n fromObjectList: fromObjectList,\n getMessagesFromStorage: getMessagesFromStorage,\n setMessagesToStorage: setMessagesToStorage,\n clearMessagesFromStorage: clearMessagesFromStorage,\n getCountOfUnreadMessages: getCountOfUnreadMessages,\n getMessagesFromIds: getMessagesFromIds,\n getUnreadMessages: getUnreadMessages,\n markReaden: markReaden,\n markReadAsSynched: markReadAsSynched,\n getUnsynchedReadMessages: getUnsynchedReadMessages,\n storeMessagesFromServer: storeMessagesFromServer\n };\n /**\r\n * Extend an array of Objects from the default message Object\r\n * @memberof MessageFactory\r\n * @param {Array} objList an Array Of messages\r\n * @returns {Array} messages\r\n */\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n /**\r\n * Get messages\r\n * @memberof MessageFactory\r\n * @returns {Array} messages \r\n */\n\n\n function getMessagesFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Save messages to storage\r\n * @memberof MessageFactory\r\n * @param {Array} messages A list of messages\r\n */\n\n\n function setMessagesToStorage(messages) {\n GenericService.saveAll(messages, objType, objCallback);\n }\n /**\r\n * Remove the messages of the local storage\r\n * @memberof MessageFactory\r\n */\n\n\n function clearMessagesFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get count of unread messages\r\n * @memberof MessageFactory\r\n * @returns {number} result \r\n */\n\n\n function getCountOfUnreadMessages() {\n var messages = getMessagesFromStorage();\n if (!messages) return 0;\n var result = 0;\n var arrayLength = messages.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (!messages[i].ReadDt) {\n result++;\n }\n }\n\n return result;\n }\n /**\r\n * Get messages from given ids\r\n * @memberof MessageFactory\r\n * @param {Ids} List of Ids\r\n * @returns {Array} selectedMessages \r\n */\n\n\n function getMessagesFromIds(Ids) {\n var messages = getMessagesFromStorage();\n var selectedMessages = [];\n\n if (Ids != undefined || Ids != null) {\n for (var i = 0; i < Ids.length; i++) {\n for (var j = 0; j < messages.length; j++) {\n if (Ids[i] == messages[j].Id) {\n selectedMessages.push(messages[j]);\n break;\n }\n }\n }\n }\n\n return selectedMessages;\n }\n /**\r\n * Get unread messages\r\n * @memberof MessageFactory\r\n * @returns {Array} filteredMessages \r\n */\n\n\n function getUnreadMessages() {\n var messages = getMessagesFromStorage();\n filteredMessages = [];\n\n for (var i = 0; i < messages.length; i++) {\n if (!messages[i].ReadDt == null) {\n filteredMessages.push(messages[i]);\n }\n }\n\n return filteredMessages;\n }\n /**\r\n * Get unread messages\r\n * @memberof MessageFactory\r\n * @returns {Array} filteredMessages \r\n */\n\n\n function markReaden(messageId) {\n // get the Message array from storage\n var messages = getMessagesFromStorage();\n if (messages == null) messages = []; // find the current Message from the array (if present)\n\n var arrayLength = messages.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (messages[i].Id == messageId) {\n messages[i].ReadDt = new Date();\n break;\n }\n }\n\n setMessagesToStorage(messages);\n }\n /**\r\n * Mark the messages as synched and save it\r\n * @memberof MessageFactory\r\n * @param {array} readMessages A list of synced messages\r\n */\n\n\n function markReadAsSynched(readMessages) {\n var messages = getMessagesFromStorage();\n\n if (readMessages && messages) {\n var id;\n\n for (var i = 0; i < readMessages.length; i++) {\n id = readMessages[i].Id;\n\n for (var x = 0; x < messages.length; x++) {\n if (messages[x].Id === id) {\n messages[x].Synched = true;\n }\n }\n }\n\n setMessagesToStorage(messages);\n }\n }\n /**\r\n * Get the messages that are unsynched and not read and save them\r\n * @memberof MessageFactory\r\n * @param {array} readMessages A list of synced messages\r\n */\n\n\n function getUnsynchedReadMessages() {\n var messages = getMessagesFromStorage();\n var data = fromObjectList(messages);\n var filtered = null;\n\n if (data && data.length > 0) {\n filtered = [];\n\n for (var i = 0; i < data.length; i++) {\n if (data[i].ReadDt && !data[i].Synched) {\n filtered.push({\n Id: data[i].Id,\n ReadDt: data[i].ReadDt\n });\n }\n }\n }\n\n return filtered;\n }\n /**\r\n * Store the messages from the sync api\r\n * @memberof MessageFactory\r\n * @param {array} readMessages A list of messages\r\n */\n\n\n function storeMessagesFromServer(messages) {\n if (messages) {\n for (var i = 0; i < messages.length; i++) {\n messages[i].AuthorName = messages[i].AuthorName.replace(\"GATEWAY\\\\\", \"\");\n messages[i].AuthorName = messages[i].AuthorName.replace(\".\", \" \"); //messages already saved as Read in the server, should not be send to the server again\n\n if (messages[i].ReadDt) messages[i].Synched = true;else messages[i].Synched = false;\n }\n }\n\n setMessagesToStorage(messages);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('MessageModalCtrl', MessageModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name MessageModalCtrl\r\n * @description \r\n * Manages the message Modal\r\n * @ngInject\r\n */\n\n function MessageModalCtrl($scope, message, $uibModalInstance, $sce) {\n $scope.message = message;\n $scope.cancel = cancel;\n $scope.messageBody = $sce.trustAsHtml(message.Body);\n /**\r\n * Close the modal\r\n * @memberof MemoModalCtrl\r\n */\n\n function cancel() {\n $uibModalInstance.close('close');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('PassengerCtrl', PassengerCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name PassengerCtrl\r\n * @description \r\n * Manages the passenger information view\r\n * @ngInject\r\n */\n\n function PassengerCtrl(passenger, arrival, $scope, $uibModalInstance) {\n $scope.passenger = passenger;\n $scope.arrival = arrival;\n $scope.cancel = cancel;\n $scope.IsOld = IsOld;\n /**\r\n * Checks if the data are new\r\n * @memberof PassengerCtrl\r\n * @param {string} time timestamp\r\n * @return {boolean} IsOld\r\n */\n\n function IsOld(time) {\n IsOld = false;\n\n if (time) {\n var now = new Date();\n var timeDate = new Date(time);\n var diff = now.getTime() - timeDate.getTime();\n\n if (diff > 3600000) {\n IsOld = true;\n }\n }\n\n return IsOld;\n }\n /**\r\n * Close the modal\r\n * @memberof PassengerCtrl\r\n */\n\n\n function cancel() {\n $uibModalInstance.dismiss('');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('PaxCtrl', PaxCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name PaxCtrl\r\n * @description \r\n * Manages the passenger seatmap and information view\r\n * @ngInject\r\n */\n\n function PaxCtrl($scope, FlightFactory, PaxInfoFactory, $routeParams, $uibModal, $location) {\n var flightId = $routeParams.flightId;\n var flight = FlightFactory.getFlightFromStorage(flightId);\n var paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flightId);\n $scope.state = 'pax';\n $scope.flight = flight;\n $scope.showMobileMenuFilters = false;\n $scope.filterPax = filterPax;\n $scope.viewMode = viewMode;\n $scope.filterRow = filterRow;\n $scope.filterCol = filterCol;\n $scope.paxInfo = paxInfo;\n $scope.howClose = '';\n $scope.IsOld = IsOld;\n $scope.openPassenger = openPassenger;\n $scope.resetFilters = resetFilters;\n $scope.isConnectedFlightClose = isConnectedFlightClose;\n $scope.TimeDifference = TimeDifference;\n $scope.IsProvisional = true;\n $scope.specialMeals = 0;\n\n if (flight == null) {\n flight = FlightFactory.getLocalFlightFromStorage(flightId);\n }\n\n if (flight != null) {\n if (paxInfo) {\n var connectingPax = 0;\n\n for (var i = 0; i < paxInfo.ConnectingFlights.length; i++) {\n connectingPax = connectingPax + paxInfo.ConnectingFlights[i].PassengerSummaryC.Passengers + paxInfo.ConnectingFlights[i].PassengerSummaryY.Passengers;\n }\n\n $scope.connectingPax = connectingPax;\n\n for (var i = 0; i < paxInfo.Seatmap.length; i++) {\n for (var j = 0; j < paxInfo.Seatmap[i].Columns.length; j++) {\n if (paxInfo.Seatmap[i].Columns[j].SpecialMeal) {\n $scope.specialMeals++;\n }\n\n if (paxInfo.Seatmap[i].Columns[j].SpecialMealB) {\n $scope.specialMeals++;\n }\n\n if (paxInfo.Seatmap[i].Columns[j].ConnectingFlightId && paxInfo.Seatmap[i].Columns[j].ConnectingFlightId != 0) {\n for (var h = 0; h < paxInfo.ConnectingFlights.length; h++) {\n if (paxInfo.Seatmap[i].Columns[j].ConnectingFlightId == paxInfo.ConnectingFlights[h].FlightId) {\n paxInfo.Seatmap[i].Columns[j].Connection = paxInfo.ConnectingFlights[h];\n }\n }\n }\n }\n }\n\n var listSentTimestamp = new Date(paxInfo.LastRun).getTime();\n var DepartureTimestamp = new Date(flight.ScheduledDeparture).getTime(); //20 minutes before takeoff\n\n if (DepartureTimestamp - listSentTimestamp <= 1200000) {\n $scope.IsProvisional = false;\n }\n }\n\n var flightArrivalTime = new Date(flight.ScheduledArrival).getTime();\n $scope.flightETA = flight.ETA ? new Date(flight.ETA).getTime() : flightArrivalTime;\n initializeFilters();\n initializeViewMode();\n } else {\n $location.path(\"/\");\n }\n /**\r\n * Initialize Passenger Filters\r\n * @memberof PaxCtrl\r\n */\n\n\n function initializeFilters() {\n $scope.filterPaxC = false;\n $scope.filterPaxY = false;\n $scope.filterAdults = false;\n $scope.filterChildren = false;\n $scope.filterInfants = false;\n $scope.filterUMs = false;\n $scope.filterFqtv = false;\n $scope.filterConnections = false;\n $scope.filterSpecialMeals = false;\n $scope.filterFqtvSilver = false;\n $scope.filterFqtvGold = false;\n $scope.filterWheelchair = false;\n $scope.filterAssistance = false;\n $scope.filterDeportees = false;\n $scope.filterDHC = false;\n }\n /**\r\n * Filter Passenger by given filter\r\n * @memberof PaxCtrl\r\n * @param {string} criteria The selected filter criteria\r\n */\n\n\n function filterPax(criteria) {\n if (criteria == \"PaxC\") {\n var val = !$scope.filterPaxC;\n initializeFilters();\n $scope.filterPaxC = val;\n } else if (criteria == \"PaxY\") {\n var val = !$scope.filterPaxY;\n initializeFilters();\n $scope.filterPaxY = val;\n } else if (criteria == \"Adults\") {\n var val = !$scope.filterAdults;\n initializeFilters();\n $scope.filterAdults = val;\n } else if (criteria == \"Children\") {\n var val = !$scope.filterChildren;\n initializeFilters();\n $scope.filterChildren = val;\n } else if (criteria == \"Infants\") {\n var val = !$scope.filterInfants;\n initializeFilters();\n $scope.filterInfants = val;\n } else if (criteria == \"Fqtv-silver\") {\n var val = !$scope.filterFqtvSilver;\n initializeFilters();\n $scope.filterFqtvSilver = val;\n } else if (criteria == \"Fqtv-gold\") {\n var val = !$scope.filterFqtvGold;\n initializeFilters();\n $scope.filterFqtvGold = val;\n } else if (criteria == \"Connections\") {\n var val = !$scope.filterConnections;\n $scope.showConnections = true;\n initializeFilters();\n $scope.filterConnections = val;\n } else if (criteria == \"UMs\") {\n var val = !$scope.filterUMs;\n initializeFilters();\n $scope.filterUMs = val;\n } else if (criteria == \"SpecialMeals\") {\n var val = !$scope.filterSpecialMeals;\n initializeFilters();\n $scope.showMeals = true;\n $scope.filterSpecialMeals = val;\n } else if (criteria == \"Wheelchair\") {\n var val = !$scope.filterWheelchair;\n initializeFilters();\n $scope.filterWheelchair = val;\n } else if (criteria == \"Assistance\") {\n var val = !$scope.filterAssistance;\n initializeFilters();\n $scope.filterAssistance = val;\n } else if (criteria == \"Deportees\") {\n var val = !$scope.filterDeportees;\n initializeFilters();\n $scope.filterDeportees = val;\n } else if (criteria == \"DHC\") {\n var val = !$scope.filterDHC;\n initializeFilters();\n $scope.filterDHC = val;\n }\n }\n /**\r\n * Initialize View Mode\r\n * @memberof PaxCtrl\r\n */\n\n\n function initializeViewMode() {\n $scope.showPaxName = true;\n $scope.showDetails = true;\n $scope.showConnections = false;\n $scope.showMeals = false;\n }\n /**\r\n * Set the desired view style\r\n * @memberof PaxCtrl\r\n * @param {string} mode The view mode\r\n */\n\n\n function viewMode(mode) {\n if (mode == \"PaxName\") {\n $scope.showPaxName = !$scope.showPaxName;\n } else if (mode == \"Details\") {\n $scope.showDetails = !$scope.showDetails;\n } else if (mode == \"Connections\") {\n $scope.showConnections = !$scope.showConnections;\n } else if (mode == \"Meals\") {\n $scope.showMeals = !$scope.showMeals;\n }\n }\n /**\r\n * Show only the Rows that have a passenger that is valid with the current filters\r\n * @memberof PaxCtrl\r\n * @param {object} row The passenger row\r\n */\n\n\n function filterRow(row) {\n var isValid = false;\n\n if ($scope.filterPaxC || $scope.filterPaxY || $scope.filterAdults || $scope.filterChildren || $scope.filterInfants || $scope.filterUMs || $scope.filterFqtv || $scope.filterConnections || $scope.filterSpecialMeals || $scope.filterFqtvSilver || $scope.filterFqtvGold || $scope.filterWheelchair || $scope.filterAssistance || $scope.filterDeportees || $scope.filterDHC) {\n for (var i = 0; i < row.Columns.length; i++) {\n if (filterCol(row.Columns[i])) {\n isValid = true;\n }\n }\n } else {\n isValid = true;\n }\n\n return isValid;\n }\n /**\r\n * Disable the passenger seats that is not valid with the current filters\r\n * @memberof PaxCtrl\r\n * @param {object} col The passenger seat\r\n */\n\n\n function filterCol(col) {\n var IsValid = true;\n\n if ($scope.filterPaxC && col.Cabin != \"C\") {\n IsValid = false;\n } else if ($scope.filterPaxY && col.Cabin != \"Y\") {\n IsValid = false;\n } else if ($scope.filterAdults && col.Type != 'A') {\n IsValid = false;\n } else if ($scope.filterChildren && col.Type != 'C') {\n IsValid = false;\n } else if ($scope.filterInfants && col.Type != 'I' && !(col.Type == 'A' && col.InfantName)) {\n IsValid = false;\n } else if ($scope.filterFqtv && col.Fqtv == null) {\n IsValid = false;\n } else if ($scope.filterConnections && col.Connection == null) {\n IsValid = false;\n } else if ($scope.filterUMs && !(col.SSR != null && col.SSR.IsUMNR)) {\n IsValid = false;\n } else if ($scope.filterSpecialMeals && col.SpecialMeal == null && col.SpecialMealB == null) {\n IsValid = false;\n } else if ($scope.filterFqtvSilver && !(col.Fqtv != null && (col.Fqtv.TierLevel == 'BLUT' || col.Fqtv.TierLevel == 'SLVT'))) {\n IsValid = false;\n } else if ($scope.filterFqtvGold && !(col.Fqtv != null && col.Fqtv.TierLevel == 'GLDT')) {\n IsValid = false;\n } else if ($scope.filterWheelchair && !(col.SSR != null && col.SSR.IsGroupPRM)) {\n IsValid = false;\n } else if ($scope.filterAssistance && !(col.SSR != null && (col.SSR.IsDEAF || col.SSR.IsBLND || col.SSR.IsDPNA))) {\n IsValid = false;\n } else if ($scope.filterDeportees && !(col.SSR != null && (col.SSR.IsINAD || col.SSR.IsGroupDEP))) {\n IsValid = false;\n } else if ($scope.filterDHC && !col.IsDHC) {\n IsValid = false;\n }\n\n return IsValid;\n }\n /**\r\n * Initialize Passenger Filters and the desired view style\r\n * @memberof PaxCtrl\r\n */\n\n\n function resetFilters() {\n initializeFilters();\n initializeViewMode();\n }\n /**\r\n * Open Passenger Modal View\r\n * @memberof PaxCtrl\r\n * @param {object} inputObject The passenger informations\r\n * @param {string} arrival The flights Arrival\r\n */\n\n\n function openPassenger(inputObject, _arrival) {\n if (inputObject.IsEmptySeat == 0 && (inputObject.SeatMode == 'Seat' || inputObject.SeatMode == 'Jumpseat')) {\n $uibModal.open({\n templateUrl: 'views/Dialogs/dlgPassenger.html',\n controller: 'PassengerCtrl',\n size: 'md',\n backdrop: 'static',\n keyboard: false,\n resolve: {\n passenger: function passenger() {\n return inputObject;\n },\n arrival: function arrival() {\n return _arrival;\n }\n }\n });\n }\n }\n /**\r\n * Checks if the data are new\r\n * @memberof PaxCtrl\r\n * @param {string} time timestamp\r\n * @return {boolean} IsOld\r\n */\n\n\n function IsOld(time) {\n IsOld = false;\n\n if (time) {\n var now = new Date();\n var timeDate = new Date(time);\n var diff = now.getTime() - timeDate.getTime();\n\n if (diff > 3600000) {\n IsOld = true;\n }\n }\n\n return IsOld;\n }\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof PaxCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\n\n\n function isConnectedFlightClose(connection) {\n if (!connection) {\n return '';\n }\n\n var connFlightDate = new Date(connection.STD).getTime();\n if ($scope.flightETA > connFlightDate) return '';\n\n if (connFlightDate - $scope.flightETA < connection.MCT * 60000) {\n return 'bg-bisque';\n }\n\n if (connFlightDate - $scope.flightETA < (connection.MCT + 15) * 60000) {\n return 'bg-cornsilk';\n }\n\n return '';\n }\n /**\r\n * Returns the time difference\r\n * @memberof PaxCtrl\r\n * @param {string} time Connection STD\r\n * @return {string} timeDifference\r\n */\n\n\n function TimeDifference(time) {\n var timeString = '';\n var sign = '';\n var dayString = null;\n\n if (time) {\n var connFlightDate = new Date(time);\n var ms = connFlightDate.getTime() - $scope.flightETA; // this is a time in milliseconds\n\n if (ms < 0) {\n ms = -ms;\n sign = \"-\";\n }\n\n var days = Math.floor(ms / (24 * 60 * 60 * 1000));\n days = days < 0 ? days + 1 : days;\n var daysms = ms % (24 * 60 * 60 * 1000);\n var hours = Math.floor(daysms / (60 * 60 * 1000));\n var hoursms = ms % (60 * 60 * 1000);\n var minutes = Math.floor(hoursms / (60 * 1000));\n timeString = '' + sign + (hours > 0 ? (\"0\" + hours).substr(-2) + \":\" : '') + (\"0\" + minutes).substr(-2) + '\\'' + '';\n dayString = ' ' + days + 'd';\n }\n\n return timeString + (days && days != 0 ? dayString : '');\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PaxInfoFactory', PaxInfoFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PaxInfoFactory\r\n * @description \r\n * Add, Update, Delete and Get Passenger information.\r\n * @ngInject\r\n */\n\n function PaxInfoFactory(GenericService, FlightGateFactory, SyncLogFactory) {\n /**\r\n * Initialize the PaxInfo\r\n * @memberof PaxInfoFactory\r\n */\n function PaxInfo() {\n this.Id = null;\n this.STD_utc = null;\n this.STD_lcl = null;\n this.STA_utc = null;\n this.STA_lcl = null;\n this.AcType = null;\n this.Registration = null;\n this.ConfigurationC = null;\n this.ConfigurationY = null;\n this.PaxTotalC = null;\n this.PaxTotalY = null;\n this.MarketingFlightNos = null;\n this.SupplementaryInfo = null;\n this.LastRun = null;\n this.Offpoints = [];\n this.ConnFlights = [];\n this.Seatmap = [];\n this.curtainRows = [];\n this.Statistics = {};\n this.GetId = GetId;\n }\n\n var objType = 'PaxInfo';\n var objCallback = PaxInfo;\n var service = {\n getAllPaxInfoFromStorage: getAllPaxInfoFromStorage,\n savePaxInfoToStorage: savePaxInfoToStorage,\n setPaxInfoToStorage: setPaxInfoToStorage,\n getPaxInfoFromStorage: getPaxInfoFromStorage,\n updatePaxInfo: updatePaxInfo\n };\n /**\r\n * Overide default get Id\r\n * @memberof PaxInfoFactory\r\n * @returns {number} Id \r\n */\n\n function GetId() {\n return this.FlightId;\n }\n /**\r\n * Overide default get Id\r\n * @memberof PaxInfoFactory\r\n * @returns {number} Id \r\n */\n\n\n function GetStatistics(paxInfo) {\n var statistics = {};\n var syncLog = SyncLogFactory.getSyncLog();\n\n if (paxInfo && paxInfo.Seatmap) {\n paxInfo.curtainRows = [];\n var cabinType;\n\n for (var i = 0; i < paxInfo.Seatmap.length; i++) {\n for (var j = 0; j < paxInfo.Seatmap[i].Columns.length; j++) {\n if (paxInfo.Seatmap[i].Columns[j].Cabin == 'J') {\n paxInfo.Seatmap[i].Columns[j].Cabin = 'Y';\n }\n\n if (cabinType == null) {\n cabinType = paxInfo.Seatmap[i].Columns[j].Cabin;\n } else if (cabinType != paxInfo.Seatmap[i].Columns[j].Cabin && paxInfo.Seatmap[i - 1] && paxInfo.Seatmap[i].Columns[j].Cabin != null) {\n cabinType = paxInfo.Seatmap[i].Columns[j].Cabin;\n paxInfo.curtainRows.push(paxInfo.Seatmap[i - 1].RowNo);\n }\n }\n }\n }\n\n return statistics;\n }\n /**\r\n * Set Passenger informations\r\n * @memberof PaxInfoFactory\r\n * @param {Array} paxInfos The passenger informations \r\n */\n\n\n function setPaxInfoToStorage(paxInfos) {\n if (paxInfos) {\n for (var i = 0; i < paxInfos.length; i++) {\n paxInfos[i].Statistics = GetStatistics(paxInfos[i]);\n }\n }\n\n GenericService.saveAll(paxInfos, objType, objCallback);\n }\n /**\r\n * Set a Passenger information list\r\n * @memberof PaxInfoFactory\r\n * @param {object} paxInfo A passenger information list\r\n */\n\n\n function savePaxInfoToStorage(paxInfo) {\n paxInfo.Statistics = GetStatistics(paxInfo);\n paxInfos[i].Seatmap = [];\n GenericService.save(paxInfo, objType, objCallback);\n }\n /**\r\n * Get Passenger information for the selected flight\r\n * @memberof PaxInfoFactory\r\n * @param {Array} paxInfos The passenger informations \r\n */\n\n\n function getPaxInfoFromStorage(flightId) {\n return GenericService.get(flightId, objType, objCallback);\n } //factory functions\n\n /**\r\n * Update Passenger information\r\n * @memberof PaxInfoFactory\r\n * @param {object} paxInfo The passenger informations \r\n */\n\n\n function updatePaxInfo(paxInfo) {\n if (paxInfo) {\n paxInfo.Statistics = GetStatistics(paxInfo);\n if (GenericService.get(paxInfo.FlightId, objType, objCallback)) GenericService.save(paxInfo, objType, objCallback);else GenericService.add(paxInfo, objType, objCallback);\n }\n }\n /**\r\n * Get Passenger information for the selected flights\r\n * @memberof PaxInfoFactory\r\n */\n\n\n function getAllPaxInfoFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('AircraftTypeFactory', AircraftTypeFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AircraftTypeFactory\r\n * @description \r\n * Manage Aircraft Types.\r\n * @ngInject\r\n */\n\n function AircraftTypeFactory($log, GenericValuesFactory) {\n /**\r\n * Initialiaze AircraftType object \r\n * @memberof AircraftTypeFactory\r\n */\n function AircraftType() {\n this.Code = null;\n }\n\n var callback = AircraftType;\n var type = 'aircraftTypes';\n var service = {\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n toObjectList: toObjectList,\n getAircraftTypesFromStorage: getAircraftTypesFromStorage,\n setAircraftTypesToStorage: setAircraftTypesToStorage,\n clearAircraftTypesFromStorage: clearAircraftTypesFromStorage\n };\n /**\r\n * Extend given AircraftType object \r\n * @memberof AircraftTypeFactory\r\n * @param {object} obj The AircraftType object that will be extended\r\n * @returns {object} AircraftType\r\n */\n\n function fromObject(obj) {\n return GenericValuesFactory.fromObject(obj, callback);\n }\n /**\r\n * Extend given AircraftType object list\r\n * @memberof AircraftTypeFactory\r\n * @param {array} objList The list of AircraftType objects that will be extended\r\n * @returns {object} AircraftTypes\r\n */\n\n\n function fromObjectList(objList) {\n return GenericValuesFactory.fromObjectList(objList, callback);\n }\n /**\r\n * Extend given AircraftType object list\r\n * @memberof AircraftTypeFactory\r\n * @param {array} objList The list of AircraftType objects that will be extended\r\n * @returns {object} AircraftTypes\r\n */\n\n\n function toObjectList(objList) {\n return GenericValuesFactory.objList(objList);\n }\n /**\r\n * Get all the AircraftType objects\r\n * @memberof AircraftTypeFactory\r\n * @returns {array} AircraftTypes\r\n */\n\n\n function getAircraftTypesFromStorage() {\n return GenericValuesFactory.getValuesFromStorage(callback, type);\n }\n /**\r\n * Set all the AircraftTypes\r\n * @memberof AircraftTypeFactory\r\n * @param {array} objects A list of AircraftTypes.\r\n */\n\n\n function setAircraftTypesToStorage(objList) {\n GenericValuesFactory.setValuesToStorage(objList, type);\n }\n /**\r\n * Clear all the AircraftTypes\r\n * @memberof AircraftTypeFactory\r\n */\n\n\n function clearAircraftTypesFromStorage() {\n GenericValuesFactory.clearValuesFromStorage(type);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.filter('byCategory', byCategory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name byCategory\r\n * @description \r\n * Filter questions by catecory and search text\r\n * @ngInject\r\n */\n\n function byCategory() {\n return function (questions, obj) {\n var items = {\n category: obj.category,\n searchText: obj.query ? obj.query.toLowerCase() : \"\",\n out: []\n };\n angular.forEach(questions, function (value, key) {\n if (this.category === value.CategoryLabel && (value.Label.toLowerCase().indexOf(this.searchText) >= 0 || value.Description.toLowerCase().indexOf(this.searchText) >= 0)) {\n this.out.push(value);\n }\n }, items);\n return items.out.dynamicSort('OrderNo');\n };\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('OpenReportDialogCtrl', OpenReportDialogCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name OpenReportDialogCtrl\r\n * @description \r\n * Manages the open report modal functionality \r\n * @ngInject\r\n */\n\n function OpenReportDialogCtrl($scope, $uibModalInstance, $location, apiUrl, UserFactory, FlightFactory, PilotReportLocalEditFactory, flightId) {\n // load the user\n var user = UserFactory.getUser(); // load the flight\n\n var flight = FlightFactory.getFlightFromStorage(flightId);\n if (flight == null) return; // load the reports\n\n var serverReportForThisUser = flight.getServerPilotReportForUser(user.aimsId);\n var serverReportsByAnotherUser = flight.getServerPilotReportsByAnotherUser(user.aimsId);\n var localReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId); // the user can create a new report only if there is not an existing one and there is not a server report by him\n\n if (localReport != null || serverReportForThisUser != null) $scope.canCreateNewLocalReport = false;else $scope.canCreateNewLocalReport = true;\n var allServerReports = new Array();\n\n if (serverReportForThisUser != null) {\n serverReportForThisUser.IsSameUser = \" (YOU)\";\n allServerReports.push(serverReportForThisUser);\n }\n\n for (var i = 0; i < serverReportsByAnotherUser.length; i++) {\n allServerReports.push(serverReportsByAnotherUser[i]);\n }\n\n $scope.localReport = localReport;\n $scope.serverReports = allServerReports;\n $scope.cancel = cancel;\n $scope.createNewLocalReport = createNewLocalReport;\n $scope.openLocalReport = openLocalReport;\n $scope.openServerReport = openServerReport;\n /**\r\n * Close Modal\r\n * @memberof OpenReportDialogCtrl\r\n */\n\n function cancel() {\n $uibModalInstance.dismiss('');\n }\n\n ;\n /**\r\n * Create new report and close modal\r\n * @memberof OpenReportDialogCtrl\r\n */\n\n function createNewLocalReport() {\n $location.path(\"report/new:\" + -1 + \"/\" + flightId);\n $uibModalInstance.dismiss('');\n }\n\n ;\n /**\r\n * Open Local Report\r\n * @memberof OpenReportDialogCtrl\r\n * @param {object} report\r\n */\n\n function openLocalReport(report) {\n $location.path(\"report/\" + report.ReportGuid);\n $uibModalInstance.dismiss('');\n }\n\n ;\n /**\r\n * Open Server stored Report\r\n * @memberof OpenReportDialogCtrl\r\n * @param {object} report\r\n */\n\n function openServerReport(report) {\n //get user token and send it as a parameter on the call\n var token = '';\n\n if (user != null) {\n token = user.token;\n token = encodeURIComponent(token);\n $location.path(\"reportsHistory/\" + report.ReportId + \"/\" + flightId + \"/Pilot\");\n }\n\n $uibModalInstance.dismiss('');\n }\n\n ;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PilotReportLocalEditFactory', PilotReportLocalEditFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportLocalEditFactory\r\n * @description \r\n * Manage Local Pilot Reports.\r\n * @ngInject\r\n */\n\n function PilotReportLocalEditFactory($log, localStorageMD5Service, GenericService, GroundServicesFactory) {\n /**\r\n * Initialiaze PilotReportLocalEdit object \r\n * @memberof PilotReportLocalEditFactory\r\n */\n function PilotReportLocalEdit() {\n this.ReportGuid = null;\n this.AuthorId = null;\n this.AuthorAimsId = null;\n this.AuthorName = null;\n this.Created = null;\n this.FlightAimsId = null;\n this.FlightId = null;\n this.LastUpdated = null;\n this.Departure = null;\n this.Arrival = null;\n this.AcType = null;\n this.AcTailNo = null;\n this.FlightDate = null;\n this.FlightNo = null;\n this.ScheduledDeparture = null;\n this.ScheduledDepartureDateUTC = null;\n this.ScheduledDepartureTimeUTC = null;\n this.Departure = null;\n this.Arrival = null;\n this.ReportId = null;\n this.NothingToReport = null;\n this.Status = null; // pending, draft, completed, synched\n\n this.Sections = [];\n this.ActiveItems = 0;\n this.WarningItems = 0;\n this.IsValid = false; //v1.1 added pax and dep/arr details\n\n this.BookedC = null;\n this.BookedY = null;\n this.BookedInf = null;\n this.BookedPad = null;\n this.BookedChld = null;\n this.ActualC = null;\n this.ActualY = null;\n this.ActualInf = null;\n this.ActualPad = null;\n this.ActualChld = null;\n this.DepartureICAO = null;\n this.DepartureCountry = null;\n this.DepartureName = null;\n this.ArrivalICAO = null;\n this.ArrivalCountry = null;\n this.ArrivalName = null;\n this.crew = null;\n this.AutolandSatisfactory = false;\n this.AutolandUnsatisfactory = false;\n this.AutolandWorkOrderNo = null;\n this.AutolandWorkOrderNoIsValid = null;\n this.catApproachUnsatisfactory = false;\n this.catApproachSatisfactory = false;\n this.GroundServicesSectionHasValue = false;\n this.ArrivalGroundServices = [];\n this.DepartureGroundServices = []; //new fields \n\n this.DepartureGate = null;\n this.DepartureTimezone = null;\n this.ArrivalTimezone = null;\n this.CallSign = null;\n this.ScheduledArrival = null;\n this.getDescription = getDescription;\n this.getRoute = getRoute;\n this.updateTotals = updateTotals;\n this.saveReport = saveReport;\n this.saveReportAsTemp = saveReportAsTemp;\n }\n\n var objType = 'pilotReportLocalEdits';\n var objCallback = PilotReportLocalEdit;\n var service = {\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n getPilotReportsFromStorage: getPilotReportsFromStorage,\n setPilotReportsToStorage: setPilotReportsToStorage,\n deleteTempReport: deleteTempReport,\n deleteReport: deleteReport,\n getPilotReportLocalEditFromTemp: getPilotReportLocalEditFromTemp,\n getPilotReportLocalEditForFlight: getPilotReportLocalEditForFlight,\n getPilotReportLocalEdit: getPilotReportLocalEdit,\n getPilotReportLocalEditCountThatNeedToBeSynched: getPilotReportLocalEditCountThatNeedToBeSynched,\n getPilotReportLocalEditThatNeedToBeSynched: getPilotReportLocalEditThatNeedToBeSynched,\n getNewReport: getNewReport,\n markReportAsSynched: markReportAsSynched,\n setPilotReportToStorage: setPilotReportToStorage,\n checkForNewGroundServices: checkForNewGroundServices\n };\n /**\r\n * Get a short Description of this Pilot report\r\n * @memberof PilotReportLocalEditFactory\r\n * @returns {string} Description \r\n */\n\n function getDescription() {\n var s = this.FlightNo + ' ' + this.Departure + '-' + this.Arrival + ' ' + this.ScheduledDepartureDateUTC + ' by ' + this.AuthorName;\n return s;\n }\n /**\r\n * Get the Route of this Pilot report\r\n * @memberof PilotReportLocalEditFactory\r\n * @returns {string} Route \r\n */\n\n\n function getRoute() {\n if (this.Departure == null && this.Arrival == null) return '-';else return (this.Departure || '?') + '-' + (this.Arrival || '?');\n }\n /**\r\n * Update the totals of all the section of the report\r\n * @memberof PilotReportLocalEditFactory\r\n */\n\n\n function updateTotals() {\n var allActiveItems = 0;\n var allWarningItems = 0;\n var sectionCount = this.Sections.length;\n\n for (var i = 0; i < sectionCount; i++) {\n var sectionActiveItems = 0;\n var sectionWarningItems = 0;\n var itemCount = this.Sections[i].Items.length;\n\n for (var j = 0; j < itemCount; j++) {\n if (this.Sections[i].Items[j].ItemHasValue == true) {\n if (this.Sections[i].Items[j].ItemValue != null && this.Sections[i].Items[j].ItemValue != '') {\n allActiveItems++;\n sectionActiveItems++;\n } else {\n allWarningItems++;\n sectionWarningItems++;\n }\n }\n }\n\n this.Sections[i].ActiveItems = sectionActiveItems;\n this.Sections[i].WarningItems = sectionWarningItems;\n }\n\n this.ActiveItems = allActiveItems;\n this.WarningItems = allWarningItems;\n this.GroundServicesSectionHasValue = false; // if(this.ArrivalGroundServices){\n // \tfor (var i = 0; i < this.ArrivalGroundServices.length; i++) {\n // \t\tif (this.ArrivalGroundServices[i].Used) {\n // \t\t\tthis.GroundServicesSectionHasValue = true;\n // \t\t}\n // \t}\n // }\n\n if (this.DepartureGroundServices) {\n for (var i = 0; i < this.DepartureGroundServices.length; i++) {\n if (this.DepartureGroundServices[i].Used) {\n this.GroundServicesSectionHasValue = true;\n }\n }\n }\n\n this.IsValid = false;\n\n if (this.NothingToReport == true && (!this.AutolandUnsatisfactory || this.AutolandUnsatisfactory && this.AutolandWorkOrderNoIsValid)) {\n this.IsValid = true;\n } else {\n if (this.ActiveItems > 0 && this.WarningItems == 0 && (!this.AutolandUnsatisfactory || this.AutolandUnsatisfactory && this.AutolandWorkOrderNoIsValid)) {\n this.IsValid = true;\n }\n }\n }\n /**\r\n * Save the Pilot Report\r\n * @memberof PilotReportLocalEditFactory\r\n */\n\n\n function saveReport() {\n // update the LastUpdated field\n this.LastUpdated = new Date(); // get the reports array from storage\n\n var allReports = getPilotReportsFromStorage();\n if (allReports == null) allReports = []; // find the current report from the array (if present)\n\n var arrayLength = allReports.length;\n var reportIndex = -1;\n\n for (var i = 0; i < arrayLength; i++) {\n if (allReports[i].ReportGuid == this.ReportGuid) {\n reportIndex = i;\n break;\n }\n } // add or update a copy of the current report\n\n\n if (reportIndex >= 0) allReports[reportIndex] = this;else allReports.push(this); // save\n\n setPilotReportsToStorage(allReports);\n }\n /**\r\n * Save the Report As Temp\r\n * @memberof PilotReportLocalEditFactory\r\n */\n\n\n function saveReportAsTemp() {\n // update the LastUpdated field\n this.LastUpdated = new Date(); // save as temp\n\n localStorageMD5Service.remove('pilotReportLocalEdit_TEMP');\n localStorageMD5Service.set('pilotReportLocalEdit_TEMP', this);\n } //Factory Functions\n\n /**\r\n * Extend Object from the default local Pilot Report Object\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {Object} obj a PilotReportLocalEdit\r\n * @returns {Object} PilotReportLocalEdit\r\n */\n\n\n function fromObject(obj) {\n return GenericService.fromObject(obj, objCallback);\n }\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n /**\r\n * Get Pilot Reports from storage\r\n * @memberof PilotReportLocalEditFactory\r\n * @returns {Array} PilotReports\r\n */\n\n\n function getPilotReportsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Get Pilot Reports from storage\r\n * @memberof PilotReportLocalEditFactory\r\n * @returns {Array} PilotReports\r\n */\n\n\n function setPilotReportsToStorage(pilotReportLocalEdits) {\n GenericService.saveAll(pilotReportLocalEdits, objType, objCallback);\n }\n /**\r\n * Delete Pilot Temporary Report from storage\r\n * @memberof PilotReportLocalEditFactory\r\n */\n\n\n function deleteTempReport() {\n localStorageMD5Service.remove('pilotReportLocalEdit_TEMP');\n }\n /**\r\n * Delete Selected repport\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {string} reportGuid The report's Identifier\r\n */\n\n\n function deleteReport(reportGuid) {\n var allReports = getPilotReportsFromStorage();\n if (allReports == null) return false;\n var updatedReports = [];\n var arrayLength = allReports.length;\n var reportIndex = -1;\n\n for (var i = 0; i < arrayLength; i++) {\n if (allReports[i].ReportGuid == reportGuid) {\n reportIndex = i; // break;\n } else {\n updatedReports.push(allReports[i]); // copy report in new array\n }\n }\n\n if (reportIndex = -1) {\n setPilotReportsToStorage(updatedReports);\n }\n }\n /**\r\n * Get the Pilot repport of this flight\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {number} flightId A flight Id\r\n * @return {Object} report \r\n */\n\n\n function getPilotReportLocalEditFromTemp() {\n var pilotReportLocalEdit = localStorageMD5Service.get('pilotReportLocalEdit_TEMP');\n pilotReportLocalEdit = checkForNewGroundServices(pilotReportLocalEdit);\n return fromObject(pilotReportLocalEdit);\n }\n /**\r\n * Get the Pilot repport of this flight\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {number} flightId A flight Id\r\n * @return {Object} report \r\n */\n\n\n function getPilotReportLocalEditForFlight(flightId) {\n var pilotReportLocalEdits = getPilotReportsFromStorage();\n if (pilotReportLocalEdits == null) return null;\n var result = null;\n var arrayLength = pilotReportLocalEdits.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (pilotReportLocalEdits[i].FlightId == flightId) {\n result = pilotReportLocalEdits[i];\n break;\n }\n }\n\n result = checkForNewGroundServices(result);\n return result;\n }\n /**\r\n * Get the Pilot repport\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {string} reportGuid A report Id\r\n * @return {Object} report \r\n */\n\n\n function getPilotReportLocalEdit(reportGuid) {\n var pilotReportLocalEdits = getPilotReportsFromStorage();\n if (pilotReportLocalEdits == null) return null;\n var result = null;\n var arrayLength = pilotReportLocalEdits.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (pilotReportLocalEdits[i].ReportGuid == reportGuid) {\n result = pilotReportLocalEdits[i];\n break;\n }\n }\n\n result = checkForNewGroundServices(result);\n return result;\n }\n /**\r\n * add any new ground services from storage to the existing report\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {Object} report\r\n * @return {Object} report \r\n */\n\n\n function checkForNewGroundServices(report) {\n if (report == null) return report;\n var depStorageGroundServices = GroundServicesFactory.getGroundServicesByStation(report.Departure); //var arrStorageGroundServices = GroundServicesFactory.getGroundServicesByStation(report.Arrival);\n\n for (var i = 0; i < depStorageGroundServices.length; i++) {\n var found = false;\n\n for (var j = 0; j < report.DepartureGroundServices.length; j++) {\n if (depStorageGroundServices[i].ServiceType === report.DepartureGroundServices[j].ServiceType) {\n //this ground service is available according to the localstorage but its not in the report\n found = true;\n break;\n }\n }\n\n if (!found) {\n report.DepartureGroundServices.push(depStorageGroundServices[i]);\n }\n } // for (var i = 0; i < arrStorageGroundServices.length; i++) {\n // \tvar found = false;\n // \tfor (var j = 0; j < report.ArrivalGroundServices.length; j++){\n // \t\tif (arrStorageGroundServices[i].ServiceType === report.ArrivalGroundServices[j].ServiceType){\n // \t\t\t//this ground service is available according to the localstorage but its not in the report\n // \t\t\tfound = true;\n // \t\t\tbreak;\n // \t\t}\n // \t}\n // \tif (!found){\n // \t\treport.ArrivalGroundServices.push(arrStorageGroundServices[i]);\n // \t}\n // }\n\n\n return report;\n }\n /**\r\n * Get the number of reports that need to be synched\r\n * @memberof PilotReportLocalEditFactory\r\n * @return {number} result A Pilot Report\r\n */\n\n\n function getPilotReportLocalEditCountThatNeedToBeSynched() {\n var pilotReportLocalEdits = getPilotReportsFromStorage();\n if (pilotReportLocalEdits == null) return 0;\n var result = 0;\n var arrayLength = pilotReportLocalEdits.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (pilotReportLocalEdits[i].Status === 'completed') {\n result++;\n }\n }\n\n return result;\n }\n\n function getPilotReportLocalEditThatNeedToBeSynched() {\n var result = new Array();\n var pilotReportLocalEdits = getPilotReportsFromStorage();\n if (pilotReportLocalEdits == null) return result;\n var arrayLength = pilotReportLocalEdits.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (pilotReportLocalEdits[i].Status === 'completed') {\n result.push(pilotReportLocalEdits[i]);\n }\n }\n\n return result;\n }\n /**\r\n * Gonstructor for a new Pilot Report\r\n * @memberof PilotReportLocalEditFactory\r\n * @return {array} result \r\n */\n\n\n function getNewReport() {\n return new PilotReportLocalEdit();\n }\n /**\r\n * Mark selected report As Synched\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {string} reportGuid The report Guid\r\n * @return {boolean} isSuccess \r\n */\n\n\n function markReportAsSynched(reportGuid) {\n var report = getPilotReportLocalEdit(reportGuid);\n if (report == null) return false;\n report.Status = 'synched';\n report.saveReport();\n return true;\n }\n /**\r\n * Save Selected Pilot repport\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {Object} report A Pilot Report\r\n */\n\n\n function setPilotReportToStorage(report) {\n var allReports = getPilotReportsFromStorage();\n if (allReports == null) return false; // cannot delete a report, if none exist\n // find the current report from the array (if present)\n\n var updatedReports = [];\n var arrayLength = allReports.length;\n var reportIndex = -1;\n\n for (var i = 0; i < arrayLength; i++) {\n if (allReports[i].ReportGuid == report.ReportGuid) {\n updatedReports.push(report);\n reportIndex = i;\n } else {\n updatedReports.push(allReports[i]); // copy report in new array\n }\n }\n\n if (reportIndex != -1) {\n setPilotReportsToStorage(updatedReports);\n }\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PilotReportLocalEditCreatorFactory', PilotReportLocalEditCreatorFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportLocalEditCreatorFactory\r\n * @description \r\n * Create a new local Report\r\n * @ngInject\r\n */\n\n function PilotReportLocalEditCreatorFactory($log, localStorageMD5Service, FlightFactory, ReportGuidFactory, PilotReportTemplateFactory, PilotReportLocalEditFactory, UserFactory, GroundServicesFactory) {\n var service = {\n createNewLocalReportForFlight: createNewLocalReportForFlight\n };\n /**\r\n * Create a new Local Report For the Selected Flight\r\n * @memberof PilotReportLocalEditCreatorFactory\r\n * @param {number} flightId \r\n * @returns {object} report \r\n */\n\n function createNewLocalReportForFlight(flightId, flightAimsId) {\n // load the user\n var user = UserFactory.getUser();\n if (user == null) return null; // check if a report exists for this flight and user\n\n var existingReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\n if (existingReport != null) return existingReport; // get a guid for the report\n\n var newReportGuid = ReportGuidFactory.getNextGuid();\n if (newReportGuid == null) return null; // load the pilot report template\n\n var reportTemplate = PilotReportTemplateFactory.getPilotReportTemplateFromStorage();\n if (reportTemplate == null) return null; // load the flight\n\n var flight = FlightFactory.getFlightFromStorage(flightId, flightAimsId);\n\n if (flight == null) {\n // if not found, also check the local flights\n var flight = FlightFactory.getLocalFlightFromStorage(flightId, flightAimsId); // if still not found, then return null\n\n if (flight == null) return null;\n } // create the new report\n\n\n var newReport = PilotReportLocalEditFactory.getNewReport(); // assign data on the new report\n\n newReport.AuthorId = user.id;\n newReport.AuthorAimsId = user.aimsId;\n newReport.AuthorName = user.name;\n newReport.Created = new Date();\n newReport.FlightAimsId = flight.FlightAimsId;\n newReport.FlightId = flight.FlightId;\n newReport.LastUpdated = new Date();\n newReport.AcType = flight.AcType;\n newReport.AcTailNo = flight.AcTailNo;\n newReport.FlightDate = flight.FlightDate;\n newReport.FlightNo = flight.FlightNo;\n newReport.Departure = flight.Departure;\n newReport.Arrival = flight.Arrival;\n newReport.ScheduledDeparture = flight.ScheduledDeparture;\n newReport.ScheduledDepartureDateUTC = flight.ScheduledDepartureDateUTC;\n newReport.ScheduledDepartureTimeUTC = flight.ScheduledDepartureTimeUTC;\n newReport.ReportGuid = newReportGuid;\n newReport.ReportId = null;\n newReport.NothingToReport = false;\n newReport.Status = 'pending';\n newReport.Sections = reportTemplate.Sections; //details from flight (assuming flight contains these fields)\n\n if (flight.DepartureName) {\n newReport.DepartureICAO = flight.DepartureICAO;\n newReport.DepartureCountry = flight.DepartureCountry;\n newReport.DepartureName = flight.DepartureName;\n newReport.ArrivalICAO = flight.ArrivalICAO;\n newReport.ArrivalCountry = flight.ArrivalCountry;\n newReport.ArrivalName = flight.ArrivalName;\n } //pax figures from flight (assuming flight contains these figures)\n\n\n if (typeof flight.BookedY != 'undefined') {\n newReport.BookedC = flight.BookedC;\n newReport.BookedY = flight.BookedY;\n newReport.BookedInf = flight.BookedInf;\n newReport.BookedPad = flight.BookedPad;\n newReport.BookedChld = flight.BookedChld;\n newReport.ActualC = flight.ActualC;\n newReport.ActualY = flight.ActualY;\n newReport.ActualInf = flight.ActualInf;\n newReport.ActualPad = flight.ActualPad;\n newReport.ActualChld = flight.ActualChld;\n }\n\n newReport.crew = flight.crew; //new values\n\n newReport.DepartureTimezone = flight.DepartureTimezone;\n newReport.ArrivalTimezone = flight.ArrivalTimezone;\n newReport.CallSign = flight.CallSign;\n newReport.ScheduledArrival = flight.ScheduledArrival;\n newReport.DepartureGate = flight.DepartureGate; //add ground services\n\n newReport.DepartureGroundServices = GroundServicesFactory.getGroundServicesByStation(flight.Departure); //We don't show Arrival Services any more...\n //newReport.ArrivalGroundServices = GroundServicesFactory.getGroundServicesByStation(flight.Arrival);\n\n newReport.updateTotals(); // return the new report\n\n return newReport;\n }\n\n return service;\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PilotReportSendToServerFactory', PilotReportSendToServerFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportSendToServerFactory\r\n * @description \r\n * Transform Pilot Reports in order to send them to the server\r\n * @ngInject\r\n */\n\n function PilotReportSendToServerFactory($log) {\n /**\r\n * Initialize the PilotReportSendToServer\r\n * @memberof PilotReportSendToServerFactory\r\n */\n function PilotReportSendToServer() {\n this.Created = null;\n this.LastUpdated = null;\n this.FlightAimsId = null;\n this.FlightId = null;\n this.FlightDate = null;\n this.FlightNo = null;\n this.Departure = null;\n this.Arrival = null;\n this.ReportGuid = null;\n this.AuthorCrewId = null;\n this.AuthorCrewAimsId = null;\n this.Items = [];\n this.Autoland = 'manual';\n this.AutolandWorkOrderNo = null;\n this.ArrivalGroundServices = [];\n this.DepartureGroundServices = [];\n }\n /**\r\n * Initialize the PilotReportSendToServerItem\r\n * @memberof PilotReportSendToServerFactory\r\n */\n\n\n function PilotReportSendToServerItem() {\n this.ReportGuid = null;\n this.TemplateItemId = null;\n this.Value = 0;\n this.Remarks = '';\n }\n\n var service = {\n getCompletedListFromPilotReportLocalEdits: getCompletedListFromPilotReportLocalEdits\n };\n /**\r\n * Transform all cabin local reports in order to be sent to the server\r\n * @memberof PilotReportSendToServerFactory\r\n * @param {Array} pilotReportLocalEdits\r\n * @returns {Array} PilotReportsSendToServer \r\n */\n\n function getCompletedListFromPilotReportLocalEdits(pilotReportLocalEdits) {\n var result = [];\n if (pilotReportLocalEdits == null) return result;\n var arrayLength = pilotReportLocalEdits.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (pilotReportLocalEdits[i].Status === 'completed') {\n result.push(getReportFromPilotReportLocalEdit(pilotReportLocalEdits[i]));\n }\n } //Temporary: fix: Ground Services: Used values (true/false) from local storage.\n\n\n var resultChecked = fixUsedValueLS(result);\n return resultChecked;\n } //Temporary: fix - Ground Services - local storage from true/false values. (int Used: 0:false, 1:true, 2:inop) \n\n\n function fixUsedValueLS(cabinReportLocalEdits) {\n for (var i = 0; i < cabinReportLocalEdits.length; i++) {\n if (cabinReportLocalEdits[i].DepartureGroundServices.length > 0) {\n for (var j = 0; j < cabinReportLocalEdits[i].DepartureGroundServices.length; j++) {\n if (cabinReportLocalEdits[i].DepartureGroundServices[j]) {\n if (cabinReportLocalEdits[i].DepartureGroundServices[j].Used === true) {\n cabinReportLocalEdits[i].DepartureGroundServices[j].Used = 1;\n } else if (cabinReportLocalEdits[i].DepartureGroundServices[j].Used === false) {\n cabinReportLocalEdits[i].DepartureGroundServices[j].Used = 0;\n }\n }\n }\n }\n }\n\n return cabinReportLocalEdits;\n }\n /**\r\n * Transform a pilot local reports in order to be sent to the server\r\n * @memberof PilotReportSendToServerFactory\r\n * @param {object} pilotReportLocalEdit\r\n * @returns {object} PilotReportSendToServer \r\n */\n\n\n function getReportFromPilotReportLocalEdit(pilotReportLocalEdit) {\n var result = new PilotReportSendToServer();\n result.Created = pilotReportLocalEdit.Created;\n result.LastUpdated = pilotReportLocalEdit.LastUpdated;\n result.FlightAimsId = pilotReportLocalEdit.FlightAimsId;\n result.FlightId = pilotReportLocalEdit.FlightId;\n result.FlightDate = pilotReportLocalEdit.FlightDate;\n result.FlightNo = pilotReportLocalEdit.FlightNo;\n result.Departure = pilotReportLocalEdit.Departure;\n result.Arrival = pilotReportLocalEdit.Arrival;\n result.ReportGuid = pilotReportLocalEdit.ReportGuid;\n result.AuthorCrewId = pilotReportLocalEdit.AuthorId;\n result.AuthorCrewAimsId = pilotReportLocalEdit.AuthorAimsId;\n result.Items = new Array(); //result.ArrivalGroundServices = pilotReportLocalEdit.ArrivalGroundServices;\n\n result.DepartureGroundServices = pilotReportLocalEdit.DepartureGroundServices;\n\n if (pilotReportLocalEdit.AutolandSatisfactory) {\n result.Autoland = 'AutolandSatisfactory';\n } else if (pilotReportLocalEdit.AutolandUnsatisfactory) {\n result.Autoland = 'AutolandUnsatisfactory';\n result.AutolandWorkOrderNo = pilotReportLocalEdit.AutolandWorkOrderNo;\n } else if (pilotReportLocalEdit.catApproachUnsatisfactory) {\n result.Autoland = 'CATApproachUnsatisfactory';\n } else if (pilotReportLocalEdit.catApproachSatisfactory) {\n result.Autoland = 'CATApproachSatisfactory';\n }\n\n var sectionCount = pilotReportLocalEdit.Sections.length;\n\n for (var i = 0; i < sectionCount; i++) {\n var itemCount = pilotReportLocalEdit.Sections[i].Items.length;\n\n for (var j = 0; j < itemCount; j++) {\n var newItem = new PilotReportSendToServerItem();\n newItem.ReportGuid = pilotReportLocalEdit.ReportGuid;\n newItem.TemplateItemId = pilotReportLocalEdit.Sections[i].Items[j].Id;\n newItem.Value = pilotReportLocalEdit.Sections[i].Items[j].ItemHasValue ? 1 : 0;\n if (newItem.Value == 1) newItem.Remarks = pilotReportLocalEdit.Sections[i].Items[j].ItemValue;\n result.Items.push(newItem);\n }\n }\n\n return result;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PilotReportSyncResultFactory', PilotReportSyncResultFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportSyncResultFactory\r\n * @description \r\n * Manage Pilot Report Sync Results\r\n * @ngInject\r\n */\n\n function PilotReportSyncResultFactory($log, GenericService) {\n /**\r\n * Initialize the PilotReportSyncResult\r\n * @memberof PilotReportSyncResultFactory\r\n */\n function PilotReportSyncResult() {\n this.reportGuid = null;\n this.message = null;\n this.success = null;\n this.FlightAimsId = null;\n this.FlightId = null;\n this.ScheduledDepartureDateUTC = null;\n this.FlightNo = null;\n this.Departure = null;\n this.Arrival = null;\n this.ScheduledDepartureTimeUTC = null;\n this.AcTailNo = null;\n this.Result = null;\n this.getRoute = getRoute;\n }\n\n var objType = 'pilotReportSyncResult';\n var objCallback = PilotReportSyncResult;\n var service = {\n fromObjectList: fromObjectList,\n getSyncResult: getSyncResult,\n getPilotReportSyncResultsFromStorage: getPilotReportSyncResultsFromStorage,\n setPilotReportSyncResultsToStorage: setPilotReportSyncResultsToStorage,\n clearPilotReportSyncResultsFromStorage: clearPilotReportSyncResultsFromStorage,\n getSuccesses: getSuccesses,\n getFailures: getFailures\n };\n /**\r\n * Get Report Route\r\n * @memberof PilotReportSyncResultFactory\r\n * @return {string} route\r\n */\n\n function getRoute() {\n if (this.Departure == null && this.Arrival == null) return '-null-';else return (this.Departure || '?') + '-' + (this.Arrival || '?');\n }\n /**\r\n * Extend an array of Objects from the default PilotReportSyncResult Object\r\n * @memberof PilotReportSyncResultFactory\r\n * @param {Array} objList an Array Of Pilot Report Sync Results\r\n * @returns {Array} PilotReportSyncResults\r\n */\n\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n /**\r\n * Get Sync Result from given list\r\n * @memberof PilotReportSyncResultFactory\r\n * @param {Array} syncResults an Array Of Pilot Report Sync Results\r\n * @param {string} reportGuid The report's Guid\r\n * @returns {object} PilotReportSyncResult\r\n */\n\n\n function getSyncResult(syncResults, reportGuid) {\n var result = null;\n var arrayLength = syncResults.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (syncResults[i].reportGuid == reportGuid) {\n result = syncResults[i];\n break;\n }\n }\n\n return result;\n }\n /**\r\n * Get Sync Results\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} PilotReportSyncResults\r\n */\n\n\n function getPilotReportSyncResultsFromStorage() {\n return GenericService.list(objType, objCallback);\n }\n /**\r\n * Get Sync Results\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} PilotReportSyncResults\r\n */\n\n\n function setPilotReportSyncResultsToStorage(pilotReportSyncResults) {\n GenericService.saveAll(pilotReportSyncResults, objType, objCallback);\n }\n /**\r\n * Clear all Pilot Sync Results\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} PilotReportSyncResults\r\n */\n\n\n function clearPilotReportSyncResultsFromStorage() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Get Successfull Sync Results from given syncResult\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} successes\r\n */\n\n\n function getSuccesses(syncResults) {\n var result = 0;\n\n for (var i = 0; i < syncResults.length; i++) {\n if (syncResults[i].success == true) {\n result = result + 1;\n }\n }\n\n return result;\n }\n /**\r\n * Get Failed Sync Results from given syncResults\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} failures\r\n */\n\n\n function getFailures(syncResults) {\n var result = 0;\n\n for (var i = 0; i < syncResults.length; i++) {\n if (syncResults[i].success == false) {\n result = result + 1;\n }\n }\n\n return result;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PilotReportTemplateFactory', PilotReportTemplateFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportTemplateItemFactory\r\n * @description \r\n * Manage Pilot Report Template Item.\r\n * @ngInject\r\n */\n\n function PilotReportTemplateFactory($log, localStorageMD5Service, GenericService) {\n /**\r\n * Initialize the PilotReportTemplate\r\n * @memberof PilotReportTemplateFactory\r\n */\n function PilotReportTemplate() {\n this.Sections = new Array();\n this.getDescription = getDescription;\n }\n /**\r\n * Initialize the PilotReportTemplateItem\r\n * @memberof PilotReportTemplateFactory\r\n */\n\n\n function PilotReportTemplateItem() {\n this.Id = null;\n this.Description = null;\n this.Label = null;\n this.OrderNo = null;\n this.CategoryLabel = null;\n this.PresetComments = null;\n }\n /**\r\n * Initialize the PilotReportTemplateSection\r\n * @memberof PilotReportTemplateFactory\r\n */\n\n\n function PilotReportTemplateSection() {\n this.Id = null;\n this.Label = null;\n this.OrderNo = null;\n this.Items = new Array();\n }\n\n function getDescription() {\n if (this.Sections == null) return '-null-';else return this.Sections.length;\n }\n\n var service = {\n getPilotReportTemplateFromStorage: getPilotReportTemplateFromStorage,\n setPilotReportTemplateToStorage: setPilotReportTemplateToStorage,\n clearPilotReportTemplateFromStorage: clearPilotReportTemplateFromStorage\n };\n\n function fromObject(obj) {\n if (obj == null) return null;\n var rptt = new PilotReportTemplate();\n angular.extend(rptt, obj); // extend sections\n\n var sectionsTemp = rptt.Sections.slice();\n rptt.Sections = new Array();\n var sectionCount = sectionsTemp.length;\n\n for (var i = 0; i < sectionCount; i++) {\n var sct = new PilotReportTemplateSection();\n angular.extend(sct, sectionsTemp[i]);\n rptt.Sections.push(sct); // extend section items\n\n var itemsTemp = sectionsTemp[i].Items.slice();\n sct.Items = new Array();\n var itemCount = itemsTemp.length;\n\n for (var j = 0; j < itemCount; j++) {\n var itm = new PilotReportTemplateItem();\n angular.extend(itm, sectionsTemp[i].Items[j]);\n sct.Items.push(itm);\n }\n }\n\n return rptt;\n }\n\n ;\n /**\r\n * Get Pilot Report Template Items\r\n * @memberof PilotReportTemplateItemFactory\r\n * @returns {Array} PilotReportTemplateItems \r\n */\n\n function getPilotReportTemplateFromStorage() {\n var pilotReportTemplate = localStorageMD5Service.get('pilotReportTemplate');\n return fromObject(pilotReportTemplate);\n }\n /**\r\n * Save Pilot Report Template Items to storage\r\n * @memberof PilotReportTemplateItemFactory\r\n * @param {Array} PilotReportTemplateItems A list of Pilot Report Template Items\r\n */\n\n\n function setPilotReportTemplateToStorage(pilotReportTemplate) {\n localStorageMD5Service.set('pilotReportTemplate', pilotReportTemplate);\n }\n /**\r\n * Clear Pilot Report Template from storage\r\n * @memberof PilotReportTemplateItemFactory\r\n * @param {Array} PilotReportTemplateItems A list of Pilot Report Template Items\r\n */\n\n\n function clearPilotReportTemplateFromStorage() {\n localStorageMD5Service.remove('pilotReportTemplate');\n } // Return constructor - this is what defines the actual\n // injectable in the DI framework.\n\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ReportCtrl', ReportCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ReportCtrl\r\n * @description \r\n * Manages the Report View\r\n * @ngInject\r\n */\n\n function ReportCtrl($scope, $routeParams, UserFactory, AircaftPositionsFactory, FlightFactory, PilotReportLocalEditFactory, PilotReportLocalEditCreatorFactory, $location, SettingsMain, $timeout, ReportGuidFactory, $route, aircraftLateArrivalReportId, inadequateGroundTimeReportId, autolandSupportingAcTypes, showCatIIApprachAcTypes) {\n $scope.discard = discard;\n $scope.infoSaveOperation = infoSaveOperation;\n $scope.setCategory = setCategory;\n $scope.state = 'report';\n $scope.deleteReportClicked = deleteReportClicked;\n $scope.autoAdjustTarget = null;\n $scope.autoAdjustTimer = null;\n $scope.autoAdjustRun = autoAdjustRun;\n $scope.saveDraftClicked = saveDraftClicked;\n $scope.saveClicked = saveClicked;\n $scope.cancelClicked = cancelClicked;\n $scope.reportItemValueChanged = reportItemValueChanged;\n $scope.adjustTextarea = adjustTextarea;\n $scope.clearRemarks = clearRemarks;\n $scope.reportChanged = reportChanged;\n $scope.AutolandChanged = AutolandChanged;\n $scope.CatApproachChanged = CatApproachChanged;\n $scope.isValidWorkOrderNo = false;\n $scope.workOrderNo = null;\n $scope.validationWorkOrderNo = validationWorkOrderNo;\n $scope.logIt = logIt;\n\n function logIt(x) {\n console.log(\"User = \" + JSON.stringify(x));\n } // get the report id\n\n\n var reportId = $routeParams.reportId;\n var report = null; // show logged user info\n\n var user = UserFactory.getUser();\n $scope.logged_user_info = user.aimsId + ' - ' + user.name;\n $scope.isSecure = UserFactory.isSecure(); // new / edit existing / load from temp\n\n if (reportId.startsWith('new:')) {\n // get the flight id\n var flightAimsId = reportId.substring(4, reportId.length);\n var flightId = $routeParams.flightId; // create a new report\n\n var newLocalReport = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight(flightId, flightAimsId);\n\n if (newLocalReport == null) {\n bootbox.alert(\"

Attention

Unable to create a new log!
Available pool of resources has been depleted and you need to synchronize with the server to renew it.\", function () {\n $location.path(\"/\");\n $scope.$apply();\n });\n return;\n } else {\n // load the new report\n report = newLocalReport;\n }\n } else if (reportId == 'temp') {\n // load the report from the temp place\n report = PilotReportLocalEditFactory.getPilotReportLocalEditFromTemp();\n\n if (report == null) {\n // since we could not load the temp report, delete it\n PilotReportLocalEditFactory.deleteTempReport();\n bootbox.alert(\"

Warning

Unable to load temporary log.
No temporary log found in this device\", function () {\n $location.path(\"/\");\n $scope.$apply();\n });\n return;\n }\n } else {\n // load the report\n report = PilotReportLocalEditFactory.getPilotReportLocalEdit(reportId);\n\n if (report == null) {\n bootbox.alert(\"

Warning

Unable to load the requested log.
This entry does not exist in this device, our its data are corrupted and the entry is unusable.\", function () {\n $location.path(\"/\");\n $scope.$apply();\n });\n return;\n }\n } //flight\n\n\n var flight = FlightFactory.getFlightFromTotalFlights(report.FlightId);\n\n if (!flight) {\n // go to dashboard if no flight\n $location.path(\"/\");\n }\n\n $scope.showAutolandSection = autolandSupportingAcTypes.includes(flight.AcType);\n $scope.showCatIIApprachSection = showCatIIApprachAcTypes.includes(flight.AcType);\n /* //find late arrival report item and fill it with previous Late Aircraft Arrival\r\n var lateArrivalreportItem = null; \r\n report.Sections.forEach(\r\n function(section){\r\n var filteredItems = section.Items.filter(\r\n function(item){\r\n return item.Id == aircraftLateArrivalReportId\r\n });\r\n if(filteredItems.length==1){\r\n lateArrivalreportItem = filteredItems[0];\r\n }\r\n }\r\n );\r\n \r\n var inadequateGroundTimeReportItem = null; \r\n report.Sections.forEach(\r\n function(section){\r\n var filteredItems = section.Items.filter(\r\n function(item){\r\n return item.Id == inadequateGroundTimeReportId\r\n });\r\n if(filteredItems.length==1){\r\n inadequateGroundTimeReportItem = filteredItems[0];\r\n }\r\n }\r\n );*/\n\n /* var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId(flight.FlightId);\r\n if(aircaftPositions && aircaftPositions.PreviousSTA && !$scope.isTurboProp){\r\n var startofTAT = moment.utc(flight.ScheduledDeparture).add(-45, 'm');\r\n var prevATA = moment.utc(aircaftPositions.PreviousATA);\r\n var prevSTA = moment.utc(aircaftPositions.PreviousSTA);\r\n var lateArrival = 0;\r\n var inadequateGroundTime = 0;\r\n if(startofTAT.diff(prevSTA, 'm')>=0 && aircaftPositions.PreviousATA){\r\n \r\n var comparedValue = startofTAT;\r\n if(lateArrival > 0){\r\n var comparedValue = prevATA;\r\n }\r\n lateArrival = prevATA.diff(comparedValue, 'm');\r\n }else{\r\n lateArrival = aircaftPositions.PreviousATA ? prevATA.diff(prevSTA, 'm') : 0;\r\n inadequateGroundTime = prevSTA.diff(startofTAT, 'm');\r\n if(lateArrival<0){\r\n inadequateGroundTime = inadequateGroundTime + lateArrival;\r\n }\r\n }\r\n \r\n if(lateArrival>0 && lateArrivalreportItem && !lateArrivalreportItem.ItemHasValue){\r\n lateArrivalreportItem.ItemValue = \"Late Aircraft Arrival \" + lateArrival + \" minutes\";\r\n lateArrivalreportItem.ItemHasValue= true;\r\n }\r\n \r\n if(inadequateGroundTime>0 && inadequateGroundTimeReportItem && !inadequateGroundTimeReportItem.ItemHasValue){\r\n inadequateGroundTimeReportItem.ItemValue = \"Inadequate Ground Time \" + inadequateGroundTime + \" minutes\";\r\n inadequateGroundTimeReportItem.ItemHasValue= true;\r\n }\r\n }\r\n */\n\n $scope.flight = flight;\n $scope.panels = {\n showOnlyOne: true,\n report: {\n visible: true,\n open: true,\n cssClass: function cssClass() {\n return report.IsValid ? 'panel-green' : 'panel-orange';\n }\n },\n autoland: {\n open: report.AutolandSatisfactory || report.AutolandUnsatisfactory\n },\n catApproach: {\n open: report.catApproachSatisfactory || report.catApproachUnsatisfactory\n },\n Flight: {\n visible: true,\n open: false,\n cssClass: function cssClass(report) {\n if (report.WarningItems > 0) return 'panel-orange';else if (report.ActiveItems > 0) return 'panel-green';else return 'panel-default';\n }\n },\n groundServices: {\n visible: true,\n open: false,\n cssClass: function cssClass() {\n if (report.GroundServicesSectionHasValue) return 'panel-green';else return 'panel-default';\n }\n }\n };\n $scope.GetCategoryCSS = GetCategoryCSS;\n\n function GetCategoryCSS(items, category) {\n var itemsInCategory = items.filter(function (item) {\n return item.CategoryLabel == category;\n });\n var completed = itemsInCategory.some(function (item) {\n return item.ItemHasValue == true && item.ItemValue && item.ItemValue.length > 0;\n });\n var draft = itemsInCategory.some(function (item) {\n return item.ItemHasValue == true && (!item.ItemValue || item.ItemValue == \"\");\n });\n if (draft) return 'panel-orange';else if (completed) return 'panel-green';else return 'panel-gray';\n }\n\n $scope.countDHC = 0;\n if (report.crew) $scope.countDHC = report.crew.filter(function (item) {\n return item.isDHC == true;\n }).length;\n\n if (report && report.ScheduledArrival) {\n var nowTimeStamp = new Date().getTime();\n var schedullDepartureTimestamp = new Date(report.ScheduledArrival).getTime();\n $scope.isFuture = nowTimeStamp < schedullDepartureTimestamp;\n }\n\n $scope.showCompleted = showCompleted;\n $scope.showAll = showAll;\n $scope.compressedMode = false;\n\n function showCompleted() {\n $scope.panels.report.open = !$scope.panels.report.open;\n $scope.compressedMode = true;\n }\n\n function showAll() {\n $scope.panels.report.open = !$scope.panels.report.open;\n $scope.compressedMode = false;\n } // update totals and set to scope\n\n\n report.updateTotals();\n $scope.report = report;\n var categoryFilter = null;\n var categoryFilters = [];\n\n for (var i = 0; i < report.Sections.length; i++) {\n categoryFilter = {\n category: '',\n section: report.Sections[i].Label\n };\n categoryFilters.push(categoryFilter);\n }\n\n $scope.categoryfilters = categoryFilters; // save the report to a temp place\n\n if (report.Status != 'synched') report.saveReportAsTemp(); // set editing page to report\n\n SettingsMain.setEditingPage('report');\n /**\r\n * When report changes run to update the item\r\n * @memberof ReportCtrl\r\n */\n\n function reportChanged(item) {\n // put preset comments\n if (item != null) {\n if (item.PresetComments != null) {\n if (item.ItemValue == null || item.ItemValue == '') {\n item.ItemValue = item.PresetComments;\n }\n }\n } // update the report totals\n\n\n report.updateTotals(); // save the report to a temp place\n\n if (report.Status != 'synched') report.saveReportAsTemp();\n }\n\n function AutolandChanged(result) {\n if (result == true && report.AutolandSatisfactory) {\n report.AutolandUnsatisfactory = false;\n } else if (result == false && report.AutolandUnsatisfactory) {\n report.AutolandSatisfactory = false;\n }\n\n reportChanged();\n }\n\n function CatApproachChanged(result) {\n if (result == true && report.catApproachSatisfactory) {\n report.catApproachUnsatisfactory = false;\n } else if (result == false && report.catApproachUnsatisfactory) {\n report.catApproachSatisfactory = false;\n }\n\n reportChanged();\n }\n /**\r\n * Clear Remarks\r\n * @memberof ReportCtrl\r\n * @param {object} item Report s question\r\n */\n\n\n function clearRemarks(item) {\n // put preset comments\n if (item != null) {\n item.ItemValue = null;\n reportChanged(item);\n }\n }\n\n function autoAdjustRun() {\n var t = $scope.autoAdjustTarget;\n t.style.overflow = 'hidden';\n t.style.height = 0;\n t.style.height = t.scrollHeight + 'px';\n if (t.style.height < 40) t.style.height = 40;\n $scope.autoAdjustTarget = null;\n $scope.autoAdjustTimer = null; // also, update the report and save it to a temp place\n\n report.updateTotals();\n if (report.Status != 'synched') report.saveReportAsTemp();\n }\n\n function adjustTextarea($event) {\n //$event.keyCode = 13\n //performing adjusts using a timer, to minimize times it executes, and make it faster on ipad2\n if ($scope.autoAdjustTimer != null) {\n clearTimeout($scope.autoAdjustTimer); //old object pending... execute its adjustment and then plan new object's adjustment\n\n if ($event.target != $scope.autoAdjustTarget) {\n $scope.autoAdjustRun();\n }\n }\n\n $scope.autoAdjustTarget = $event.target;\n $scope.autoAdjustTimer = setTimeout($scope.autoAdjustRun, 500);\n }\n /**\r\n * When the user types a value into a report item updates totals of the report\r\n * @memberof ReportCtrl\r\n */\n\n\n function reportItemValueChanged() {\n // update the report totals\n report.updateTotals();\n }\n /**\r\n * Go to calendar and reset report\r\n * @memberof ReportCtrl\r\n */\n\n\n function cancelClicked() {\n // delete the temp report\n PilotReportLocalEditFactory.deleteTempReport(); // set editing page to none\n\n SettingsMain.setEditingPage(null); // go to dashboard\n\n $location.path(\"/\");\n }\n /**\r\n * Save Completed and Go to calendar\r\n * @memberof ReportCtrl\r\n */\n\n\n function saveClicked() {\n // save the report\n report.Status = 'completed';\n report.saveReport();\n FlightFactory.updateFlightFromReport(report); // delete the temp report\n\n PilotReportLocalEditFactory.deleteTempReport(); //set editing page to none\n\n SettingsMain.setEditingPage(null);\n infoSaveOperation(report.Status); // go to flight info\n\n $location.path('/flightinfo/' + report.FlightId);\n }\n /**\r\n * Save Draft\r\n * @memberof ReportCtrl\r\n */\n\n\n function saveDraftClicked() {\n // save the report\n report.Status = 'draft';\n report.saveReport();\n FlightFactory.updateFlightFromReport(report); // delete the temp report\n\n PilotReportLocalEditFactory.deleteTempReport(); // set editing page to none\n\n SettingsMain.setEditingPage(null);\n infoSaveOperation(report.Status); // go to dashboard\n //$location.path(\"/\");\n }\n\n function setCategory(category, section) {\n console.log(category);\n var newCategoryFilters = [];\n\n for (var i = 0; i < categoryFilters.length; i++) {\n if (categoryFilters[i].section == section) {\n categoryFilters[i] = {\n category: category,\n section: section\n };\n }\n\n newCategoryFilters.push(categoryFilters[i]);\n }\n\n categoryFilters = newCategoryFilters;\n $scope.categoryfilters = categoryFilters;\n }\n /**\r\n * Save Draft\r\n * @memberof ReportCtrl\r\n */\n\n\n function deleteReportClicked() {\n var status = report.status;\n var title = \"Warning\";\n\n if (status == 'synched') {\n title = \"Attention\";\n }\n\n bootbox.dialog({\n message: \"Please confirm that you wish to permanently reset this CP Flight Log.\",\n title: \"\" + title + \"\",\n buttons: {\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\"\n },\n danger: {\n label: \"Reset CP Flight Log\",\n className: \"btn-warning\",\n callback: function callback() {\n //add code here to remove report from temp location and possibly from permanent location\n //TODO:\n PilotReportLocalEditFactory.deleteReport(report.ReportGuid); // delete the temp report\n\n PilotReportLocalEditFactory.deleteTempReport();\n FlightFactory.updateFlightFromReport(report); // set editing page to none\n\n SettingsMain.setEditingPage(null); //next code moves user to main page\n\n $timeout(function () {\n if ($location.path() == \"/report/temp\") {\n $scope.openReport();\n } else {\n $route.reload();\n }\n });\n }\n }\n }\n });\n }\n /**\r\n * Show information about the save action\r\n * @memberof ReportCtrl\r\n * @param {string} state The action of the save completed or draft or discard\r\n */\n\n\n function infoSaveOperation(state) {\n if (state == 'completed') {\n $scope.infosaveactiontype = state;\n $scope.infosaveaction = true;\n } else if (state == 'draft') {\n $scope.infosaveactiontype = state;\n $scope.infosaveaction = true;\n } else if (state == 'discard') {\n $scope.infosaveactiontype = state;\n $scope.infosaveaction = true;\n }\n\n $timeout(function () {\n $scope.infosaveaction = false;\n }, 5000);\n }\n\n function discard() {\n if (report == null) {\n report = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\n }\n\n var guid = report.ReportGuid;\n var status = report.Status; // delete the temp report\n\n PilotReportLocalEditFactory.deleteTempReport(); //reuse guid if this was a new report\n\n if (status == 'pending') ReportGuidFactory.restoreGuid(report.ReportGuid); // new / edit existing / load from temp\n\n if (reportId.startsWith('new:')) {\n var flightId = $routeParams.flightId; // create a new report\n\n var newLocalReport = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight(flightId);\n\n if (newLocalReport == null) {\n bootbox.alert(\"

Attention

Unable to create a new log!
Available pool of resources has been depleted and you need to synchronize with the server to renew it.\", function () {\n $location.path(\"/\");\n $scope.$apply();\n });\n } else {\n // load the new report\n report = newLocalReport;\n }\n } else if (reportId == 'temp') {\n // load the report from the temp place\n report = PilotReportLocalEditFactory.getPilotReportLocalEditFromTemp();\n\n if (report == null && status != 'pending') {\n // since we could not load the temp report, delete it\n PilotReportLocalEditFactory.deleteTempReport();\n bootbox.alert(\"

Warning

Unable to load temporary log.
No temporary log found in this device or the report was corrupted\", function () {\n $location.path(\"/\");\n $scope.$apply();\n });\n }\n\n if (report == null) {\n report = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight($scope.flight.FlightId);\n }\n } else {\n // load the report\n report = PilotReportLocalEditFactory.getPilotReportLocalEdit(reportId);\n\n if (report == null) {\n bootbox.alert(\"

Warning

Unable to load the requested log.
This entry does not exist in this device, our its data are corrupted and the entry is unusable.\", function () {\n $location.path(\"/\");\n $scope.$apply();\n });\n }\n }\n\n $scope.report = report;\n infoSaveOperation('discard');\n }\n\n function validationWorkOrderNo() {\n if (!isNaN(+report.AutolandWorkOrderNo) && report.AutolandWorkOrderNo.length == 6) {\n report.AutolandWorkOrderNoIsValid = true;\n report.updateTotals();\n if (report.Status != 'synched') report.saveReportAsTemp();\n } else {\n report.AutolandWorkOrderNoIsValid = false;\n report.IsValid = false;\n }\n }\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('ReportGuidFactory', ReportGuidFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name ReportGuidFactory\r\n * @description \r\n * Manages ReportGuid\r\n * @ngInject\r\n */\n\n function ReportGuidFactory($log, localStorageMD5Service) {\n /**\r\n * Initialize the ReportGuid\r\n * @memberof ReportGuidFactory\r\n */\n function ReportGuid() {\n this.Guid = null;\n }\n\n var objType = 'reportGuids';\n var objCallback = ReportGuid;\n var service = {\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n toObjectList: toObjectList,\n getReportGuidsFromStorage: getReportGuidsFromStorage,\n setReportGuidsToStorage: setReportGuidsToStorage,\n clearReportGuidsFromStorage: clearReportGuidsFromStorage,\n getNextGuid: getNextGuid,\n getRemainingReportGuids: getRemainingReportGuids,\n restoreGuid: restoreGuid\n };\n /**\r\n * Extend Object from the default ReportGuid Object\r\n * @memberof ReportGuidFactory\r\n * @param {Object} obj a ReportGuid\r\n * @returns {Object} ReportGuid\r\n */\n\n function fromObject(obj) {\n if (obj == null) return null;\n var reportGuid = new ReportGuid();\n reportGuid.Guid = obj;\n return reportGuid;\n }\n\n ;\n /**\r\n * Extend an array of Objects from the default ReportGuid Object\r\n * @memberof ReportGuidFactory\r\n * @param {Array} objList an Array Of ReportGuids\r\n * @returns {Array} ReportGuids\r\n */\n\n function fromObjectList(objList) {\n if (objList == null) return null;\n var arrayLength = objList.length;\n var reportGuids = new Array();\n\n for (var i = 0; i < arrayLength; i++) {\n var reportGuid = new ReportGuid();\n reportGuid.Guid = objList[i];\n reportGuids.push(reportGuid);\n }\n\n return reportGuids;\n }\n /**\r\n * Extend an array of Objects from the default ReportGuid Object\r\n * @memberof ReportGuidFactory\r\n * @param {Array} objList an Array Of ReportGuids\r\n * @returns {Array} ReportGuids\r\n */\n\n\n function toObjectList(guidList) {\n if (guidList == null) return null;\n var arrayLength = guidList.length;\n var objList = new Array();\n\n for (var i = 0; i < arrayLength; i++) {\n objList.push(guidList[i].Guid);\n }\n\n return objList;\n }\n /**\r\n * Get all the reportGuid objects\r\n * @memberof reportGuid\r\n * @returns {array} ACSupplies\r\n */\n\n\n function getReportGuidsFromStorage() {\n var reportGuids = localStorageMD5Service.get('reportGuids');\n return fromObjectList(reportGuids);\n }\n /**\r\n * Set all the reportGuid objects\r\n * @memberof ReportGuidFactory\r\n * @return {string} reportGuid\r\n */\n\n\n function setReportGuidsToStorage(reportGuids) {\n localStorageMD5Service.set('reportGuids', reportGuids);\n }\n /**\r\n * Delete all the reportGuid objects\r\n * @memberof ReportGuidFactory\r\n */\n\n\n function clearReportGuidsFromStorage() {\n localStorageMD5Service.remove('reportGuids');\n }\n /**\r\n * Get the next available guid and remove it from pool\r\n * @memberof ReportGuidFactory\r\n * @return {string} reportGuid\r\n */\n\n\n function getNextGuid() {\n var reportGuids = getReportGuidsFromStorage();\n if (reportGuids == null) return null;\n var validGuidIndex = -1;\n var resultingGuid = null;\n var arrayLength = reportGuids.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (reportGuids[i].Guid != null && reportGuids[i].Guid != '') {\n validGuidIndex = i;\n resultingGuid = reportGuids[i].Guid;\n break;\n }\n }\n\n if (validGuidIndex >= 0) {\n // remove the guid from the array\n reportGuids.splice(validGuidIndex, 1); // save the new array\n\n setReportGuidsToStorage(toObjectList(reportGuids));\n }\n\n return resultingGuid;\n }\n /**\r\n * Get the count of remaining reportGuid objects\r\n * @memberof reportGuid\r\n * @returns {number} reportGuidsLength\r\n */\n\n\n function getRemainingReportGuids() {\n var reportGuids = getReportGuidsFromStorage();\n if (reportGuids == null) return 0;\n return reportGuids.length;\n }\n /**\r\n * Restore previously used guid into the pool of guids,Used when a report is being cancelled or deleted (and it has not been sent to the server)\r\n * @memberof ReportGuidFactory\r\n * @param {string} reportGuid\r\n */\n\n\n function restoreGuid(guid) {\n //reject incorrect values\n if (typeof guid == 'undefined' || guid == null || guid == '') return false;\n var reportGuids = getReportGuidsFromStorage();\n if (reportGuids == null) reportGuids = [];\n var arrayLength = reportGuids.length;\n\n for (var i = 0; i < arrayLength; i++) {\n if (reportGuids[i].Guid == guid) {\n return false;\n }\n } //add the guid into the pool of guids\n\n\n var repGuid = fromObject(guid);\n reportGuids.push(repGuid); // save the new array\n\n setReportGuidsToStorage(toObjectList(reportGuids));\n return true;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ReportsHistoryCtrl', ReportsHistoryCtrl);\n\n function ReportsHistoryCtrl($scope, $routeParams, $timeout, ReportsHistoryFactory, FlightFactory) {\n var reportId = $routeParams.reportId;\n var flightId = $routeParams.flightId;\n var reportType = $routeParams.reportType;\n var flight = FlightFactory.getFlightFromStorage(flightId);\n window.addEventListener('online', function (e) {\n $timeout(checkConnectionStatus());\n });\n $scope.reports = [];\n $scope.flight = flight;\n $scope.contentToShow = \"loading\";\n $scope.errorMessage = \"\";\n $scope.showImage = showImage;\n $scope.imageData = \"\";\n $scope.closeImage = closeImage;\n\n $scope.init = function () {\n checkConnectionStatus();\n };\n\n $scope.init();\n /**\r\n * Fetches the reports\r\n * @memberof ReportsHistoryCtrl \r\n */\n\n function fetchReports() {\n ReportsHistoryFactory.getReportsHistory(reportId, reportType).then(function (response) {\n return handleResponse(response);\n })[\"catch\"](function () {\n showError(\"We could not get any reports!\");\n });\n }\n /**\r\n * Displays the error message\r\n * @memberof ReportsHistoryCtrl \r\n * @param {string} message message to display\r\n */\n\n\n function showError(message) {\n $scope.contentToShow = \"error\";\n $scope.errorMessage = message;\n }\n /**\r\n * Checks if the client is online or offline \r\n * if is online fetches the reports else displays relative message\r\n * @memberof ReportsHistoryCtrl \r\n */\n\n\n function checkConnectionStatus() {\n var isOnline = window.navigator.onLine;\n\n if (isOnline) {\n fetchReports();\n } else {\n showError(\"Please check the internet connection!\");\n }\n }\n /**\r\n * Handles the response from the API \r\n * if is success displays the reports else shows the error message.\r\n * @memberof ReportsHistoryCtrl \r\n * @param {object} response the response object from API\r\n */\n\n\n function handleResponse(response) {\n if (response.data.success) {\n if (response.data.data.length > 0) {\n $scope.contentToShow = \"reports\";\n $scope.reports = response.data.data;\n } else {\n showError(\"There are no reports for this flight!\");\n }\n } else {\n showError(\"We could not get any reports!\");\n }\n }\n /**\r\n * Displays the image in bootbox dialog box\r\n * @memberof ReportsHistoryCtrl \r\n * @param {object} ImageData The\r\n */\n\n\n function showImage(ImageData) {\n $scope.contentToShow = \"image\";\n $scope.imageData = ImageData;\n }\n /**\r\n * The function that closes the image and displays the reports again\r\n * @memberof ReportsHistoryCtrl \r\n */\n\n\n function closeImage() {\n $scope.contentToShow = \"reports\";\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('ReportsHistoryFactory', ReportsHistoryFactory);\n /* @ngInject */\n\n function ReportsHistoryFactory($http, apiUrl) {\n /**\r\n * Fetches the ReportIncidents from API\r\n * @memberof ReportsHisReportsHistoryFactorytoryCtrl \r\n */\n function getReportsHistory(reportId, reportType) {\n return $http.get(apiUrl + '/reports/GetHistoryReport?reportId=' + reportId + '&type=' + reportType, {\n 'Content-Type': 'application/json'\n }).then(function (x) {\n return x;\n });\n }\n\n var service = {\n getReportsHistory: getReportsHistory\n };\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.filter('searchTextFilterforCategories', searchTextFilterforCategories);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name searchTextFilterforCategories\r\n * @description \r\n * Filter questions by search text\r\n * @ngInject\r\n */\n\n function searchTextFilterforCategories() {\n return function (input, obj) {\n var items = {\n searchText: obj.searchText ? obj.searchText.toLowerCase() : \"\",\n out: []\n };\n\n if (!items.searchText || items.searchText == '') {\n items.out = input;\n } else {\n angular.forEach(input, function (value, key) {\n if (value.Label.toLowerCase().indexOf(this.searchText) >= 0 || value.Description.toLowerCase().indexOf(this.searchText) >= 0) {\n this.out.push(value);\n }\n }, items);\n }\n\n var categoryLabels = items.out.dynamicSort('CategoryOrderNo').map(function (r) {\n return r.CategoryLabel;\n });\n return categoryLabels.unique();\n };\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('ServerCabinReportFactory', ServerCabinReportFactory);\n /* @ngInject */\n\n function ServerCabinReportFactory($log, GenericService) {\n function ServerCabinReport() {\n this.AuthorAimsId = null;\n this.AuthorName = null;\n this.Created = null;\n this.FlightAimsId = null;\n this.FlightId = null;\n this.LastUpdated = null;\n this.ReportGuid = null;\n this.ReportId = null;\n this.getDescription = getDescription;\n }\n\n function getDescription() {\n if (this.Created == null && this.AuthorName == null) return '-null-';else return (this.Created || '?') + ' - ' + (this.AuthorName || '?');\n }\n\n var objCallback = ServerCabinReport;\n var service = {\n fromObjectList: fromObjectList\n };\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('ServerPilotReportFactory', ServerPilotReportFactory);\n /* @ngInject */\n\n function ServerPilotReportFactory(GenericService) {\n // Define the constructor function.\n function ServerPilotReport() {\n this.AuthorAimsId = null;\n this.AuthorName = null;\n this.Created = null;\n this.FlightAimsId = null;\n this.FlightId = null;\n this.LastUpdated = null;\n this.ReportGuid = null;\n this.ReportId = null;\n this.ReportedItems = null;\n this.Source = null; // use ServerPilotReport.constSource* values\n\n this.getDescription = getDescription;\n this.isNothingToReport = isNothingToReport;\n }\n\n var objCallback = ServerPilotReport;\n\n function getDescription() {\n if (this.Created == null && this.AuthorName == null && this.ReportedItems == null) return '-null-';else return (this.AuthorAimsId || '?') + ' ' + (this.AuthorName || '?') + ' @ ' + (this.Created || '?') + (this.ReportedItems || 0) == 0 ? ' :: Nothing to report' : (this.ReportedItems || 0) + ' items logged';\n }\n\n function isNothingToReport() {\n return (this.ReportedItems || 0) == 0;\n }\n\n var service = {\n fromObjectList: fromObjectList,\n constSourceLocalOwn: 'localOwn',\n // stored locally by this user\n constSourceLocalOther: 'localOther',\n // stored locally by another user\n constSourceStoredOwn: 'storedOwn',\n // stored on the server by this user\n constSourceStoredOther: 'storedOther' // stored on the server by another user\n\n };\n\n function fromObjectList(objList) {\n return GenericService.fromObjectList(objList, objCallback);\n }\n\n ;\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.filter('unique', unique);\n /* @ngInject */\n\n function unique() {\n return function (input, key) {\n var unique = {};\n var uniqueList = [];\n\n for (var i = 0; i < input.length; i++) {\n if (typeof unique[input[i][key]] == \"undefined\") {\n unique[input[i][key]] = \"\";\n uniqueList.push(input[i]);\n }\n }\n\n return uniqueList;\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('FatigueCtrl', FatigueCtrl);\n\n function FatigueCtrl($scope, $routeParams, FlightFactory, SafetyReportFactory, $location) {\n var flightId = $routeParams.flightId;\n var flight = FlightFactory.getFlightFromStorage(flightId);\n $scope.flight = flight;\n $scope.responseMessage = \"\";\n $scope.showPanel = \"submit\";\n $scope.formData = {\n flightId: $routeParams.flightId,\n flightNo: flight.FlightNo,\n flightDate: flight.ScheduledDeparture,\n flightDep: flight.Departure,\n flightArr: flight.Arrival,\n flightRegistration: flight.AcTailNo,\n occurenceTitle: \"\",\n description: \"\",\n attachedFiles: []\n };\n $scope.sizeLimitKb = 25000;\n $scope.fileTooLargeMsg = false;\n $scope.confirmCreateFatigueReport = confirmCreateFatigueReport;\n $scope.fileUploaded = fileUploaded;\n $scope.removeFile = removeFile;\n $scope.isIFileTooLarge = isFileTooLarge;\n $scope.submitFatigueReport = submitFatigueReport;\n\n function submitFatigueReport() {\n if ($scope.fatigueReport.$valid) {\n confirmCreateFatigueReport();\n } else {\n bootbox.alert(\"Please fill in all the required fields.\");\n }\n }\n\n function confirmCreateFatigueReport() {\n bootbox.dialog({\n message: \"Would you like to proceed with the Fatigue Report?

\",\n title: \"Send Report\",\n buttons: {\n confirm: {\n label: 'Confirm',\n className: \"btn-success\",\n callback: function callback() {\n $scope.showPanel = \"loading\";\n SafetyReportFactory.saveFatigueReport($scope.formData).then(function (res) {\n return handleSubmitResponse(res);\n });\n }\n },\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n\n function handleSubmitResponse(res) {\n var alertStyle = res.success ? \"success\" : \"warning\";\n bootbox.dialog({\n message: \"
\" + res.message + \"
\",\n title: \"Response Message\",\n buttons: {\n cancel: {\n label: \"Close\",\n className: \"btn-default\",\n callback: function callback() {\n if (res.success) {\n $timeout(gotoFlightInfo(flightId));\n } else {\n $timeout($scope.showPanel = \"submit\");\n }\n }\n }\n }\n });\n }\n\n function isFileTooLarge(image) {\n var isLarge = false;\n\n if (image && image.dataURL != null) {\n isLarge = image.dataURL.length > $scope.sizeLimitKb * 1024;\n }\n\n return isLarge;\n }\n\n function fileUploaded(data) {\n var fileResult = data; //$scope.imageBrowsed;\n\n var uploadedFile = {};\n uploadedFile.fileBlobb = fileResult.dataURL;\n uploadedFile.description = fileResult.fileType || fileResult.file.type;\n uploadedFile.fileName = fileResult.fileName; // var files = $scope.formData.attachedFiles;\n\n if ($scope.formData.attachedFiles.length < 5) {\n // var n = Object.create(attachedFile);\n $scope.formData.attachedFiles.push(uploadedFile);\n } else {\n $scope.showMaxFiles = true;\n }\n }\n\n function removeFile(attachedFile) {\n var files = $scope.formData.attachedFiles;\n var arrayLenght = files.length;\n var itemIndex = -1;\n\n for (var i = 0; i < arrayLenght; i++) {\n if (files[i].fileName == attachedFile.fileName) {\n itemIndex = i;\n break;\n }\n }\n\n if (itemIndex >= 0) {\n files.splice(itemIndex, 1);\n return attachedFile;\n }\n\n if ($scope.showMaxImages) {\n appendPhoto();\n }\n\n $scope.showMaxImages = false;\n }\n\n function gotoFlightInfo(flightId) {\n $location.path('/flightinfo/' + flightId);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('SafetyCtrl', SafetyCtrl);\n\n function SafetyCtrl($scope, $timeout, operationalPhases, $routeParams, FlightFactory, SafetyReportFactory, UserFactory, $location) {\n var flightId = $routeParams.flightId;\n var flight = FlightFactory.getFlightFromStorage(flightId);\n var user = UserFactory.getUser();\n $scope.flight = flight;\n $scope.tcas = false;\n $scope.egpws = false;\n $scope.bird = false;\n $scope.selectedCategory = \"General\";\n $scope.operationalPhases = angular.fromJson(operationalPhases);\n $scope.categories = [\"General\", \"TCAS\", \"Bird Strike\", \"EGPWS\"];\n $scope.usefulnesses = [\"NECESSARY\", \"NUISANCE\", \"USEFUL\"];\n $scope.showMaxImages = false;\n $scope.responseMessage = \"\";\n $scope.showPanel = \"submit\";\n $scope.formData = {\n flightId: $routeParams.flightId,\n flightNo: flight.FlightNo,\n flightDate: flight.ScheduledDeparture,\n flightDep: flight.Departure,\n flightArr: flight.Arrival,\n flightRegistration: flight.AcTailNo,\n occurenceTitle: \"\",\n description: \"\",\n selectedPhase: \"\",\n meteo: \"\",\n trainingFlight: findTrainingFlight(),\n attachedFiles: [],\n // tcasType: {}, \n atcCallsign: \"\",\n alertType: \"\",\n usefulness: \"\",\n originalRa: \"\",\n subsequentRa: \"\",\n isRaFollowed: \"\",\n eventLocation: \"\",\n airMiss: \"\",\n trafficBearing: null,\n distance: null,\n altitude: null,\n relativeAltitude: null,\n visualContact: \"\",\n seatbeltSign: \"\",\n paxNo: null,\n // birdStrikeType: {},\n birdSpecies: \"\",\n numberSeen: \"\",\n birdNo: null,\n birdSize: \"\",\n areaOfDamage: \"\",\n speed: null,\n height: null,\n hasPilotWarned: \"\",\n birdEventLocation: \"\",\n runwayUsed: \"\",\n //egpwsType: {}\n eqpwsEventLocation: \"\"\n };\n $scope.confirmCreateReport = confirmCreateReport;\n $scope.fileUploaded = fileUploaded;\n $scope.removeFile = removeFile;\n $scope.showSelectedCategory = showSelectedCategory;\n $scope.submitForm = submitForm;\n\n function findTrainingFlight() {\n return flight.crew.some(function (item) {\n return item.aimsId == user.aimsId && item.TrainingIndicatorCode != null && item.TrainingIndicatorCode.length > 0;\n });\n }\n\n function showSelectedCategory() {\n if ($scope.selectedCategory == \"TCAS\") {\n $scope.tcas = true;\n $scope.egpws = false;\n $scope.bird = false;\n clearForm();\n } else if ($scope.selectedCategory == \"EGPWS\") {\n $scope.egpws = true;\n $scope.tcas = false;\n $scope.bird = false;\n clearForm();\n } else if ($scope.selectedCategory == \"Bird Strike\") {\n $scope.bird = true;\n $scope.tcas = false;\n $scope.egpws = false;\n clearForm();\n } else {\n $scope.tcas = false;\n $scope.egpws = false;\n $scope.bird = false;\n clearForm();\n }\n }\n\n function clearForm() {\n // tcas type fields\n $scope.formData.atcCallsign = \"\";\n $scope.formData.alertType = \"\";\n $scope.formData.usefulness = \"\";\n $scope.formData.originalRa = \"\";\n $scope.formData.subsequentRa = \"\";\n $scope.formData.isRaFollowed = \"\";\n $scope.formData.eventLocation = \"\";\n $scope.formData.airMiss = \"\";\n $scope.formData.trafficBearing = null;\n $scope.formData.distance = null;\n $scope.formData.altitude = null;\n $scope.formData.relativeAltitude = null;\n $scope.formData.visualContact = \"\";\n $scope.formData.seatbelt = \"\";\n $scope.formData.paxNo = null; // bird strike type fields\n\n $scope.formData.birdSpecies = \"\";\n $scope.formData.numberSeen = \"\";\n $scope.formData.birdNo = null;\n $scope.formData.birdSize = \"\";\n $scope.formData.areaOfDamage = \"\";\n $scope.formData.speed = null;\n $scope.formData.height = null;\n $scope.formData.hasPilotWarned = \"\";\n $scope.formData.birdEventLocation = \"\";\n $scope.formData.runwayUsed = \"\"; // egpws type field\n\n $scope.formData.eqpwsEventLocation = \"\";\n }\n\n function submitForm() {\n if ($scope.formFlightReport.$valid) {\n confirmCreateReport(); //console.log($scope.formData.attachedFiles); \n } else {\n bootbox.alert(\"Please fill in all the required fields.\");\n }\n }\n\n function confirmCreateReport() {\n bootbox.dialog({\n message: \"Would you like to proceed with the Safety Report?

\",\n title: \"Send Report\",\n buttons: {\n confirm: {\n label: 'Confirm',\n className: \"btn-success\",\n callback: function callback() {\n $scope.showPanel = \"loading\";\n SafetyReportFactory.saveSafetyReport($scope.formData).then(function (res) {\n return handleSubmitResponse(res);\n });\n }\n },\n cancel: {\n label: \"Cancel\",\n className: \"btn-default\",\n callback: function callback() {}\n }\n }\n });\n }\n\n function handleSubmitResponse(res) {\n var alertStyle = res.success ? \"success\" : \"warning\";\n bootbox.dialog({\n message: \"
\" + res.message + \"
\",\n title: \"Response Message\",\n buttons: {\n cancel: {\n label: \"Close\",\n className: \"btn-default\",\n callback: function callback() {\n if (res.success) {\n $timeout(gotoFlightInfo(flightId));\n } else {\n $timeout($scope.showPanel = \"submit\");\n }\n }\n }\n }\n });\n }\n\n function isFileTooLarge(image) {\n var isLarge = false;\n\n if (image && image.dataURL != null) {\n isLarge = image.dataURL.length > $scope.sizeLimitKb * 1024;\n }\n\n return isLarge;\n }\n\n function fileUploaded(data) {\n var fileResult = data; //$scope.imageBrowsed;\n\n var uploadedFile = {};\n\n if (isFileTooLarge(data)) {\n $scope.fileTooLargeMsg = true;\n } else {\n $scope.fileTooLargeMsg = false;\n uploadedFile.fileBlobb = fileResult.dataURL;\n uploadedFile.description = fileResult.fileType || fileResult.file.type;\n uploadedFile.fileName = fileResult.fileName; // var files = $scope.formData.attachedFiles;\n\n if ($scope.formData.attachedFiles.length < 5) {\n // var n = Object.create(attachedFile);\n $scope.formData.attachedFiles.push(uploadedFile);\n } else {\n $scope.showMaxFiles = true;\n }\n }\n }\n\n function removeFile(attachedFile) {\n var files = $scope.formData.attachedFiles;\n var arrayLenght = files.length;\n var itemIndex = -1;\n\n for (var i = 0; i < arrayLenght; i++) {\n if (files[i].fileName == attachedFile.fileName) {\n itemIndex = i;\n break;\n }\n }\n\n if (itemIndex >= 0) {\n files.splice(itemIndex, 1);\n return attachedFile;\n }\n\n if ($scope.showMaxImages) {\n appendPhoto();\n }\n\n $scope.showMaxImages = false;\n }\n\n function gotoFlightInfo(flightId) {\n $location.path('/flightinfo/' + flightId);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('SafetyReportFactory', SafetyReportFactory);\n\n function SafetyReportFactory($http, apiUrl) {\n var submitResponseObj = {\n success: false,\n message: ''\n };\n var service = {\n saveSafetyReport: saveSafetyReport,\n saveFatigueReport: saveFatigueReport\n };\n\n function saveSafetyReport(safetyReport) {\n var aqdBaseURL = apiUrl + '/SafetyReports/SaveSafetyReport';\n return $http.post(aqdBaseURL, safetyReport, {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return getResponse(res);\n })[\"catch\"](function (res) {\n return getResponseFailed(res);\n });\n }\n\n function saveFatigueReport(fatigueReport) {\n var aqdBaseURL = apiUrl + '/SafetyReports/SaveFatigueReport';\n return $http.post(aqdBaseURL, fatigueReport, {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return getResponse(res);\n })[\"catch\"](function (res) {\n return getResponseFailed(res);\n });\n }\n\n function getResponse(res) {\n submitResponseObj.success = res.data.success;\n\n if (res.data.success) {\n submitResponseObj.message = \"Safety Report Submited successfully\";\n } else {\n submitResponseObj.message = res.data.errorMessage;\n }\n\n return submitResponseObj;\n }\n\n function getResponseFailed(res) {\n submitResponseObj.success = false;\n submitResponseObj.message = \"Something went wrong!\";\n return submitResponseObj;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('AcknowledgeModalCtrl', AcknowledgeModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name AcknowledgeModalCtrl\r\n * @description \r\n * Warning Modal about unread mandatory memos\r\n * @ngInject\r\n */\n\n function AcknowledgeModalCtrl($scope, ScheduleAcknowledgeFactory, $route, $uibModalInstance) {\n $scope.ConfirmAcknowledge = ConfirmAcknowledge;\n $scope.cancel = cancel;\n $scope.showContent = 'confirm';\n $scope.responseObj = {\n success: false,\n message: '',\n Results: []\n };\n $scope.results = [];\n\n function ConfirmAcknowledge() {\n $scope.showContent = 'loading';\n ScheduleAcknowledgeFactory.acknowledgeChanges().then(function (res) {\n return handleSubmitResponse(res);\n })[\"catch\"](function (res) {\n return handleSubmitResponse(res);\n });\n }\n\n function handleSubmitResponse(res) {\n $scope.showContent = 'results';\n $scope.responseObj = res;\n }\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\n\n\n function cancel() {\n $uibModalInstance.close('cancel');\n\n if ($scope.responseObj.success) {\n $route.reload();\n }\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('ScheduleAcknowledgeFactory', ScheduleAcknowledgeFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name ScheduleAcknowledgeFactory\r\n * @description \r\n * Get list, Update list & Acknowledge schedule changes\r\n * @ngInject\r\n */\n\n function ScheduleAcknowledgeFactory(localStorageMD5Service, GenericService, $http, apiUrl, defaultCalendarDate) {\n /**\r\n * Initialize the ScheduleChanges\r\n * @memberof ScheduleAcknowledgeFactory\r\n */\n function ScheduleChanges() {\n this.dates = [];\n this.showScheduleChangesModal = false;\n }\n\n var objType = 'ScheduleChanges';\n var objCallback = ScheduleChanges;\n var response = {\n success: false,\n message: '',\n Results: []\n };\n var service = {\n setAllScheduleChangesToStorage: setAllScheduleChangesToStorage,\n getScheduleChangesFromStorage: getScheduleChangesFromStorage,\n updateShowScheduleChangesModal: updateShowScheduleChangesModal,\n showScheduleChangesModal: showScheduleChangesModal,\n hasScheduleChanges: hasScheduleChanges,\n acknowledgeChanges: acknowledgeChanges\n };\n /**\r\n * Save All Schedule changes\r\n * @param {array} objList \r\n */\n\n function setAllScheduleChangesToStorage(objList) {\n if (objList == null || !objList.length > 0) {\n GenericService.removeAll(objType);\n } else {\n var scheduleChanges = {\n dates: objList,\n showScheduleChangesModal: true\n };\n GenericService.saveOne(scheduleChanges, objType, objCallback); //GenericService.saveAll(objList,objType);\n }\n }\n /**\r\n * Get all Schedule changes\r\n */\n\n\n function getScheduleChangesFromStorage() {\n var dateList = [];\n var scheduleChanges = GenericService.getOne(objType, objCallback);\n\n if (scheduleChanges != null && scheduleChanges.dates != null) {\n scheduleChanges.dates.forEach(function (dateS) {\n var stringToDate = moment.utc(dateS);\n dateList.push(stringToDate);\n });\n }\n\n return dateList;\n }\n /* Update scheduleChanges object to storage\r\n * @memberof ScheduleAcknowledgeFactory\r\n * @param {bool} canShowModal whether the modal can be display\r\n */\n\n\n function updateShowScheduleChangesModal(canShowModal) {\n var scheduleChanges = GenericService.getOne(objType, objCallback);\n scheduleChanges.showScheduleChangesModal = canShowModal;\n GenericService.saveOne(scheduleChanges, objType, objCallback);\n }\n /**\r\n * ShowScheduleChangesModal check\r\n * @memberof ScheduleAcknowledgeFactory\r\n * @returns {bool} returns the value of showAutolandModal property\r\n */\n\n\n function showScheduleChangesModal() {\n var scheduleChanges = GenericService.getOne(objType, objCallback);\n\n if (scheduleChanges && scheduleChanges.dates != null && scheduleChanges.dates.length > 0) {\n var fistChange = moment.utc(scheduleChanges.dates[0]);\n var today = moment.utc();\n\n if (defaultCalendarDate) {\n today = moment.utc(defaultCalendarDate);\n }\n\n var datediff = fistChange.diff(today, 'days');\n return datediff <= 1 && scheduleChanges.showScheduleChangesModal;\n } else {\n return false;\n }\n }\n\n function hasScheduleChanges() {\n var dates = getScheduleChangesFromStorage();\n return dates != null && dates.length > 0;\n }\n /**\r\n * Acknowledge Changes \r\n * @param {date} dateFrom The first schedule change date\r\n * @param {date} dateTo The last schedule change date\r\n * @returns {promise} response\r\n */\n\n\n function acknowledgeChanges() {\n //get dates from local storage\n var datesToAcknowledge = getScheduleChangesFromStorage();\n return $http.post(apiUrl + '/ScheduleAcknowledge/AcknowledgeScheduleChanges', datesToAcknowledge, {\n 'Content-Type': 'application/json'\n }).then(function (res) {\n return updateScheduleChangesCallBack(res);\n })[\"catch\"](function (res) {\n return acknowledgeFailedCallBack(res);\n });\n }\n /**\r\n * Update Schedule changes dates\r\n * @param {object} res \r\n * @param {object} objectToAdd \r\n * @returns {object} response\r\n */\n\n\n function updateScheduleChangesCallBack(res) {\n response.success = res.data.success;\n\n if (res.data.success) {\n //update local storage\n setAllScheduleChangesToStorage(res.data.data.DatesWithChanges);\n response.message = \"Success! Your Acknowledge has been sent\";\n response.Results = res.data.data.Results;\n } else {\n response.message = res.data.errorMessage;\n }\n\n return response;\n }\n /**\r\n * The callback function upon failure on submit\r\n * @returns {object} response\r\n */\n\n\n function acknowledgeFailedCallBack(res) {\n response.success = false;\n response.message = \"Oops! Something went wrong\"; //TODO::Check status=500 error: returns res = {data: {…}, status: 500, config: {…}, statusText: \"Internal Server Error\", headers: ƒ}\n // res.data.data is null\n\n if (res.data.data && res.data.data.Results) {\n response.Results = res.data.data.Results;\n } else {\n //log results\n console.log(res);\n }\n\n return response;\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"SWUpdateService\", SWUpdateService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name SWUpdateService\r\n * @description \r\n * manages the service-worker update\r\n * @ngInject\r\n */\n\n function SWUpdateService(LogService) {\n /**\r\n * initialize service worker\r\n * @memberof SWUpdateService\r\n */\n function initialize() {\n // Delay registration until after the page has loaded\n window.addEventListener('load', function () {\n //kill switch. uncomment this and comment out everything else sw related\n // navigator.serviceWorker.getRegistrations().then(function (registrations) {\n // //returns installed service workers\n // if (registrations.length) {\n // for(var registration of registrations) {\n // registration.unregister();\n // }\n // }\n // });\n //register the service worker and work with the promise it returns\n navigator.serviceWorker.register('service-worker.js').then(function (reg) {\n // use a variable to make sure we refresh the page only once\n var refreshing; //fires when a new Service Worker takes control of the current page (refreshes the page)\n\n navigator.serviceWorker.addEventListener('controllerchange', function () {\n if (refreshing) return;\n refreshing = true;\n window.location.reload();\n });\n })[\"catch\"](function (e) {\n LogService.error(e, 'Tried to register the service worker');\n });\n });\n }\n /**\r\n * poll the server for new service worker file (new app version)\r\n * @memberof SWUpdateService\r\n */\n\n\n function checkUpdates(reg) {\n if (reg == null) return; //ask server for new service worker\n\n reg.update();\n }\n /**\r\n * If new service worker has been waiting too long, force update\r\n * @memberof SWUpdateService\r\n */\n\n\n function checkVersionExpiration(reg) {\n if (reg == null) return;\n reg.waiting.postMessage('checkVersionExpiration');\n }\n /**\r\n * Activate the new service worker that was waiting\r\n * @memberof SWUpdateService\r\n */\n\n\n function update(reg) {\n reg.waiting.postMessage('skipWaiting');\n }\n\n return {\n initialize: initialize,\n checkUpdates: checkUpdates,\n checkVersionExpiration: checkVersionExpiration,\n update: update\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"InfoAPIService\", InfoAPIService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name InfoAPIService\r\n * @description \r\n * Information service which gets latest pax and gate data\r\n * @ngInject\r\n */\n\n function InfoAPIService($http, $q, apiUrl, LogService, SyncAPIService, UserFactory, FlightGateFactory, FlightFactory, PaxInfoFactory, AircaftPositionsFactory, GroundDutyFactory, FlightCheckInsFactory) {\n /**\r\n * get latest Passenger information\r\n * @memberof InfoAPIService\r\n * @return {object} promise\r\n */\n function getPax(flightId) {\n //Prepare to request training courses fetch\n var flight = FlightFactory.getFlightFromTotalFlights(flightId);\n var flightInfo = {\n FlightId: flightId,\n FlightCourses: flight ? flight.Courses : []\n };\n var user = UserFactory.getUser();\n var call = $q.defer();\n $http.post(apiUrl + '/info/Pax', flightInfo, {\n 'Content-Type': 'application/json'\n }).then(function (responseData) {\n if (responseData == undefined || responseData.data == undefined || responseData.data.data == undefined) {\n var err = new Error();\n err.status = -1;\n var msg = \"ResponseData error in info/gates :\" + JSON.stringify(responseData);\n LogService.debug(msg, err);\n call.reject(err);\n return;\n }\n\n var newDutyInfo = responseData.data.data;\n newDutyInfo.FlightId = flightId;\n updateFlightLocalStorage(newDutyInfo);\n updateCrewCheckIn(newDutyInfo); // return true\n\n call.resolve(responseData);\n }, function (err) {\n call.reject(err);\n });\n return call.promise;\n }\n /**\r\n * Gets latest info for each duty in a crew route\r\n * @memberof InfoAPIService\r\n * @param {object} crewRouteDuty \r\n * @param {function} callback \r\n */\n\n\n function refreshCrewRoute(crewRouteDuty, callback) {\n var crewRouteInfo = {\n dutyNo: crewRouteDuty.DutyNo,\n dutyDay: crewRouteDuty.DutyDay,\n from: crewRouteDuty.DutyBegin,\n to: crewRouteDuty.DutyEnd,\n FlightCourses: crewRouteDuty.Courses\n };\n return $http.post(apiUrl + '/info/RefreshCrewRoute', crewRouteInfo, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Updates Flight's Data Status depending on Refresh respond\r\n * @memberof InfoAPIService\r\n * @param {object} newDuty - Refresh respond\r\n * @param {array} dataStatus \r\n */\n\n\n function updateFlightStatusSetter(newDuty, dataStatus) {\n if (newDuty.FlightInfo) {\n updateStatusSetter(dataStatus, [\"Flight Status\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Flight Status\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.AircraftPositions && newDuty.AircraftPositions.length > 0) {\n updateStatusSetter(dataStatus, [\"Aircraft Movement\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Aircraft Movement\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.FlightInfo && newDuty.FlightInfo.crew && newDuty.FlightInfo.crew.length > 0) {\n updateStatusSetter(dataStatus, [\"Crew Info\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Crew Info\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.FlightInfo && newDuty.FlightInfo.crew && newDuty.FlightInfo.crew.length > 0 && newDuty.FlightInfo.crew.filter(function (x) {\n return x.PhoneNumber != null;\n }).length > 0) {\n updateStatusSetter(dataStatus, [\"Crew Contacts\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Crew Contacts\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.CabinServiceManagementLists && newDuty.CabinServiceManagementLists.length > 0) {\n updateStatusSetter(dataStatus, [\"Meals\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Meals\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.CabinServiceManagementLists && newDuty.CabinServiceManagementLists.length > 0 && newDuty.CabinServiceManagementLists[0].ConnectingFlights && newDuty.CabinServiceManagementLists[0].ConnectingFlights.length > 0) {\n updateStatusSetter(dataStatus, [\"Connections\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Connections\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.CabinServiceManagementLists && newDuty.CabinServiceManagementLists.length > 0 && newDuty.CabinServiceManagementLists[0].ConnectingFlights && newDuty.CabinServiceManagementLists.length > 0) {\n updateStatusSetter(dataStatus, [\"Pax Info\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Pax Info\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty.TrainingCourses && newDuty.TrainingCourses.length > 0) {\n updateStatusSetter(dataStatus, [\"Training Info\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Training Info\"], \"N/A\", \"No available data\");\n }\n }\n /**\r\n * Updates Ground Duty's Data Status depending on Refresh respond\r\n * @memberof InfoAPIService\r\n * @param {array} newDuty - Refresh respond\r\n * @param {array} dataStatus \r\n */\n\n\n function updateGroundStatusSetter(newDuty, dataStatus) {\n if (newDuty) {\n updateStatusSetter(dataStatus, [\"Duty Info\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Duty\"], \"N/A\", \"No available data\");\n }\n\n if (newDuty && newDuty.RelatedGroundDuties && newDuty.RelatedGroundDuties.length > 1) {\n updateStatusSetter(dataStatus, [\"Instructors\"], \"SUCCESS\", \"Successfully updated\");\n updateStatusSetter(dataStatus, [\"Trainees\"], \"SUCCESS\", \"Successfully updated\");\n } else {\n updateStatusSetter(dataStatus, [\"Instructors\"], \"N/A\", \"No available data\");\n updateStatusSetter(dataStatus, [\"Trainees\"], \"N/A\", \"No available data\");\n }\n }\n /**\r\n * Changes the state of Data Status\r\n * @memberof InfoAPIService\r\n * @param {array} dataStatus \r\n * @param {array} array - Datatype to change\r\n * @param {string} status - New status\r\n * @param {string} text - New text\r\n */\n\n\n function updateStatusSetter(dataStatus, array, status, text) {\n var objsTochange = dataStatus.filter(function (x) {\n var res = array.filter(function (s) {\n return s == x.datatype;\n });\n return res.length > 0 ? true : false;\n });\n objsTochange.forEach(function (x) {\n x.status = status;\n x.text = text;\n var index = dataStatus.map(function (x) {\n return x.datatype;\n }).indexOf(x.datatype);\n dataStatus[index] = x;\n });\n }\n /**\r\n * Update Flight Info in Local Storage\r\n * @memberof InfoAPIService\r\n * @param {object} duty \r\n */\n\n\n function updateFlightLocalStorage(duty) {\n // save flight gates to local storage\n //var flightGates = duty.FlightGates;\n //FlightGateFactory.processUpdatedData(flightGates);\n //Update Aircraft positions\n if (duty.AircraftPositions != null && duty.AircraftPositions.length > 0) {\n AircaftPositionsFactory.updateAircraftPositionsToStorage(duty.AircraftPositions[0], duty.FlightId);\n } // update flight to local storage\n\n\n FlightFactory.mergeFlightInfo(duty.FlightInfo); //Enrich flight info after sync\n\n SyncAPIService.updatePilotReportLocalEditFromSynch(); // update paxinfo to local storage\n\n if (duty.CabinServiceManagementLists && duty.CabinServiceManagementLists.length > 0) {\n PaxInfoFactory.updatePaxInfo(duty.CabinServiceManagementLists[0]);\n } // update messages to local storage\n // MessageFactory.markReadAsSynched(duty.Messages);\n // MessageFactory.storeMessagesFromServer(duty.Messages);\n\n }\n /**\r\n * Update Flight crew check-in Info in Local Storage\r\n * @memberof InfoAPIService\r\n * @param {object} duty \r\n */\n\n\n function updateCrewCheckIn(duty) {\n if (duty.FlightInfo) {\n FlightCheckInsFactory.updateFlightCrewCheckInToStorage(duty);\n }\n }\n /**\r\n * Update Ground Duty Info in Local Storage\r\n * @memberof InfoAPIService\r\n * @param {object} duty \r\n */\n\n\n function updateGroundDutyLocalStorage(duty) {\n GroundDutyFactory.mergeGroundDutyInfo(duty);\n }\n\n return {\n getPax: getPax,\n refreshCrewRoute: refreshCrewRoute,\n updateFlightStatusSetter: updateFlightStatusSetter,\n updateGroundStatusSetter: updateGroundStatusSetter,\n updateStatusSetter: updateStatusSetter,\n updateFlightLocalStorage: updateFlightLocalStorage,\n updateGroundDutyLocalStorage: updateGroundDutyLocalStorage\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"SyncAPIService\", SyncAPIService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name SyncAPIService\r\n * @description \r\n * Generic Sync service which sends all your reports and Get all the latest data\r\n * @ngInject\r\n */\n\n function SyncAPIService($http, $q, apiUrl, FlightFactory, ReportGuidFactory, PilotReportTemplateFactory, SyncLogFactory, PilotReportLocalEditFactory, PilotReportSendToServerFactory, PilotReportSyncResultFactory, AircraftTypeFactory, DataCleanerFactory, MessageFactory, LogService, GroundDutyFactory, FlightGateFactory, MemoFactory, PaxInfoFactory, CrewRouteFactory, CrewMealFactory, MemoImagesFactory, AircaftPositionsFactory, AirportContactFactory, AirportHotelFactory, AimsCrewMemosFactory, GroundServicesFactory, LeaveRequestFactory, AutolandFactory, CrewHotelFactory, CourseFactory, ScheduleAcknowledgeFactory, CrewCallFactory, PreviousDutyFactory, LogCallFactory, CheckInFactory, FlightCheckInsFactory) {\n /**\r\n * Find if a relative old flight exists and if exists update it \r\n * @memberof SyncAPIService\r\n * @param {object} oldflight\r\n * @param {array} flights\r\n * @return {boolean} hasRelativeFlight\r\n */\n function relativeFlightMatcher(oldflight, flights) {\n var relativeReports = [];\n var relativeFlights = [];\n var found = false;\n\n for (var i = 0; i < flights.length; i++) {\n if (oldflight.FlightNo == flights[i].FlightNo && oldflight.FlightDate == flights[i].FlightDate && oldflight.Departure == flights[i].Departure) {\n relativeFlights.push(flights[i]);\n found = true;\n break;\n }\n }\n\n if (!found) {\n var flight = null;\n var oldFlightNo = null;\n var lastDigit = oldflight.FlightNo.substr(oldflight.FlightNo.length - 1, 1);\n oldFlightNo = !isNaN(lastDigit) ? oldflight.FlightNo : oldflight.FlightNo.substr(0, oldflight.FlightNo.length - 1);\n\n for (var i = 0; i < flights.length; i++) {\n lastDigit = flights[i].FlightNo.substr(flights[i].FlightNo.length - 1, 1);\n flight = !isNaN(lastDigit) ? flights[i].FlightNo : flights[i].FlightNo.substr(0, flights[i].FlightNo.length - 1);\n\n if (oldFlightNo == flight && oldflight.FlightDate == flights[i].FlightDate && oldflight.Departure == flights[i].Departure) {\n relativeFlights.push(flights[i]);\n }\n }\n }\n\n if (relativeFlights.length == 1) {\n var pilotReportLocalEdit = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(oldflight.FlightId);\n pilotReportLocalEdit.FlightAimsId = relativeFlights[0].FlightAimsId;\n pilotReportLocalEdit.FlightId = relativeFlights[0].FlightId;\n PilotReportLocalEditFactory.setPilotReportToStorage(pilotReportLocalEdit);\n return true;\n } else if (relativeFlights.length > 1) {\n for (var i = 1; i < relativeFlights.length; i++) {\n for (var j = 0; j < relativeFlights.length - i; j++) {\n if (relativeFlights[j].FlightNo > relativeFlights[j + 1].FlightNo) {\n var a = relativeFlights[j];\n relativeFlights[j] = relativeFlights[j + 1];\n relativeFlights[j + 1] = a;\n }\n }\n }\n\n var pilotReportLocalEdit = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(oldflight.FlightId);\n pilotReportLocalEdit.FlightAimsId = relativeFlights[0].FlightAimsId;\n pilotReportLocalEdit.FlightId = relativeFlights[0].FlightId;\n PilotReportLocalEditFactory.setPilotReportReportToStorage(pilotReportLocalEdit);\n return true;\n } else {\n return false;\n }\n }\n\n ;\n return {\n /**\r\n * Send and get the latest information \r\n * @memberof SyncAPIService\r\n * @param {object} aimsId\r\n * @param {array} memoIdsToSend \r\n */\n doSync: function doSync(aimsId, memoIdsToSend) {\n //clear CrewMeal ratings from local storage that have timestamp older than 20 days\n DataCleanerFactory.deleteOldCrewMealsRatings(); // get the saved pilot reports\n\n var allSavedReports = PilotReportLocalEditFactory.getPilotReportsFromStorage(); // keep only the ones that are ready to be sent\n\n var reportsToSend = PilotReportSendToServerFactory.getCompletedListFromPilotReportLocalEdits(allSavedReports);\n var messagesToSend = MessageFactory.getMessagesFromStorage();\n var lastLog = SyncLogFactory.getSyncLog();\n var lastSyncDate = lastLog.date; //Get call requests made while offline\n\n var phoneCallLog = {\n CrewCallReports: LogCallFactory.getLogCallsFromStorage()\n };\n var syncData = {\n \"SyncPilotReports\": reportsToSend,\n \"Messages\": messagesToSend,\n \"MemoIds\": memoIdsToSend,\n \"CrewCallLog\": phoneCallLog,\n \"LastSyncDate\": lastSyncDate\n };\n var call = $q.defer();\n $http.post(apiUrl + '/sync', syncData, {\n 'Content-Type': 'application/json'\n }).then(function (responseData) {\n if (responseData == undefined || responseData.data == undefined || responseData.data.data == undefined || responseData.data.data.SyncPilotData == undefined) {\n var err = new Error();\n err.status = -1;\n var msg = \"ResponseData error in sync :\" + JSON.stringify(responseData);\n LogService.debug(msg, err);\n call.reject(err);\n return;\n }\n\n var response = responseData.data.data; //keep flights, will be used to retain a flight for old unsynched reports\n\n var orgFlights = FlightFactory.getFlightsFromStorage(); // clear existing server data\n\n FlightFactory.clearFlightsFromStorage();\n ReportGuidFactory.clearReportGuidsFromStorage();\n PilotReportTemplateFactory.clearPilotReportTemplateFromStorage();\n AircraftTypeFactory.clearAircraftTypesFromStorage();\n PilotReportSyncResultFactory.clearPilotReportSyncResultsFromStorage();\n MessageFactory.clearMessagesFromStorage(); // save flight data to local storage\n\n var flightData = response.SyncPilotData.flights;\n var flights = FlightFactory.markScheduleChangedFlights(flightData, orgFlights);\n var pilotReports = response.SyncPilotData.pilotReports;\n var cabinReports = response.SyncPilotData.cabinReports;\n var messages = response.SyncPilotData.messages;\n\n for (var i = 0; i < messages.length; i++) {\n messages[i].AuthorName = messages[i].AuthorName.replace(\"GATEWAY\\\\\", \"\");\n messages[i].AuthorName = messages[i].AuthorName.replace(\".\", \" \");\n }\n\n MessageFactory.setMessagesToStorage(messages);\n GroundDutyFactory.mergeGroundDutiesToStorage(response.SyncPilotData.groundDuties);\n CrewRouteFactory.setCrewRoutesToStorage(response.SyncPilotData.CrewRoutes);\n CrewMealFactory.setCrewMealsToStorage(response.SyncPilotData.CateringCrewMeals);\n CrewHotelFactory.setCrewHotelsToStorage(response.SyncPilotData.CrewHotels);\n CheckInFactory.setCheckInInfoToStorage(response.CrewCheckInInfo); //Save schedule changes dates \n\n ScheduleAcknowledgeFactory.setAllScheduleChangesToStorage(response.SyncPilotData.ScheduleChanges); //clean crew call logs\n\n if (response.SyncPilotData.CrewCallLog && response.SyncPilotData.CrewCallLog.ResponseSuccess) {\n LogCallFactory.cleanLogsFromStorage();\n } //save training courses\n\n\n var rawTrainingCourses = response.SyncPilotData.TrainingCourses;\n var courses = [];\n rawTrainingCourses.forEach(function (course) {\n courses.push({\n Id: course.Id,\n Title: course.Title,\n HasLimitedInfo: true\n });\n });\n CourseFactory.setCoursesFromServer(courses); //clean crew member info\n\n CrewCallFactory.cleanOldData(response.SyncPilotData.flights);\n PreviousDutyFactory.cleanOldData(response.SyncPilotData.flights);\n FlightCheckInsFactory.cleanOldData(response.SyncPilotData.flights);\n FlightGateFactory.processUpdatedData(response.SyncPilotData.flightGates);\n AircaftPositionsFactory.setAircaftPositionsToStorage(response.SyncPilotData.AircaftPositions);\n AirportContactFactory.setAirportContactsToStorage(response.SyncPilotData.AirportContacts);\n AirportHotelFactory.setAirportHotelsToStorage(response.SyncPilotData.AirportHotels);\n AutolandFactory.setAutolandToStorage(response.SyncPilotData.AutolandOperations, flightData); //save, update or add memos\n\n var memos = response.SyncPilotData.memos;\n MemoFactory.setMemosFromServer(memos, memoIdsToSend, lastSyncDate); //delete leftover memos\n\n var serverMemoIds = response.SyncPilotData.memoIds;\n\n for (var i = 0; i < serverMemoIds.length; i++) {\n MemoFactory.deleteMemoFromStorage(serverMemoIds[i]);\n }\n\n for (var i = 0; i < memos.length; i++) {\n MemoImagesFactory.deleteMemoImageByMemoId(memos[i].Id);\n }\n\n var images = response.SyncPilotData.Images;\n MemoImagesFactory.setImagesToServer(images);\n\n for (var i = 0; i < serverMemoIds.length; i++) {\n MemoImagesFactory.deleteMemoImageByMemoId(serverMemoIds[i]);\n }\n\n PaxInfoFactory.setPaxInfoToStorage(response.SyncPilotData.cabinServiceManagementLists); // save guids to local storage\n\n var reportGuids = response.SyncPilotData.guids;\n ReportGuidFactory.setReportGuidsToStorage(reportGuids); // save pilot report template to storage\n\n var pilotReportTemplate = response.SyncPilotData.pilotReportTemplate;\n PilotReportTemplateFactory.setPilotReportTemplateToStorage(pilotReportTemplate); // save aircraft types to local storage\n\n var aircraftTypes = response.SyncPilotData.aircraftTypes;\n AircraftTypeFactory.setAircraftTypesToStorage(aircraftTypes); //save all GroundServices to local storage\n\n var groundServices = response.SyncPilotData.GroundServices;\n GroundServicesFactory.setGroundServicesToStorage(groundServices); // save Aims Crew Memos to local storage\n\n AimsCrewMemosFactory.setAimsCrewMemosToStorage(response.SyncPilotData.aimsCrewMemos); // get the sync results\n\n var syncResults = PilotReportSyncResultFactory.fromObjectList(response.SyncPilotData.reportResults); // mark sent reports as synched\n\n for (var j = 0; j < reportsToSend.length; j++) {\n var syncResult = PilotReportSyncResultFactory.getSyncResult(syncResults, reportsToSend[j].ReportGuid);\n\n if (syncResult != null) {\n if (syncResult.success) {\n PilotReportLocalEditFactory.markReportAsSynched(reportsToSend[j].ReportGuid);\n syncResult.Result = 'Successfully submitted';\n } else {\n syncResult.Result = 'Submission error';\n } // find flight and append report fields (storage cleared: use orgFlight)\n\n\n var flight = null;\n\n if (orgFlights != null) {\n for (var i = 0; i < orgFlights.length; i++) {\n if (orgFlights[i].FlightId != null && orgFlights[i].FlightId == reportsToSend[j].FlightId || orgFlights[i].FlightAimsId != null && orgFlights[i].FlightAimsId == reportsToSend[j].FlightAimsId) {\n flight = orgFlights[i];\n break;\n }\n }\n } //var flight = FlightFactory.getFlightFromStorage(reportsToSend[j].FlightAimsId);\n\n\n if (flight != null) {\n syncResult.FlightAimsId = flight.FlightAimsId;\n syncResult.FlightId = flight.FlightId;\n syncResult.ScheduledDepartureDateUTC = flight.ScheduledDepartureDateUTC;\n syncResult.FlightNo = flight.FlightNo;\n syncResult.Departure = flight.Departure;\n syncResult.Arrival = flight.Arrival;\n syncResult.ScheduledDepartureTimeUTC = flight.ScheduledDepartureTimeUTC;\n syncResult.AcTailNo = flight.AcTailNo;\n }\n }\n } // save the sync results\n\n\n PilotReportSyncResultFactory.setPilotReportSyncResultsToStorage(syncResults); // log the sync user and date\n\n SyncLogFactory.setSyncLog(aimsId, response.SyncPilotData.version, response.SyncPilotData.toDate); // delete local flights with no local reports\n\n DataCleanerFactory.deleteOrphanedLocalFlights();\n LeaveRequestFactory.saveLeaveRequestInformation(response.SyncPilotData.LeaveRequestInformation); //**************** ADD CODE TO KEEP FLIGHTS IF THEY STIL HAVE AN NOT SYCNHED REPORT *********************//\n //find flight ids used by draft or completed (not synched for some reason) reports\n\n if (allSavedReports) {\n var verifyFlightAimsIds = [];\n var verifyFlightIds = [];\n\n for (var i = 0; i < allSavedReports.length; i++) {\n if (allSavedReports[i].Status == 'draft' || allSavedReports[i].Status == 'completed') verifyFlightAimsIds.push(allSavedReports[i].FlightAimsId);\n verifyFlightIds.push(allSavedReports[i].FlightId);\n } //search these ids into the newly received flights\n\n\n if (verifyFlightAimsIds.length > 0) {\n var missingIds = [];\n var missingAimsIds = [];\n var found, id, aimsId;\n\n for (var i = 0; i < verifyFlightAimsIds.length; i++) {\n found = false;\n aimsId = verifyFlightAimsIds[i];\n id = verifyFlightIds[i];\n\n for (var f = 0; f < flights.length; f++) {\n if (flights[f].FlightId != null && flights[f].FlightId == id || flights[f].FlightAimsId != null && flights[f].FlightAimsId == aimsId) {\n found = true;\n break;\n }\n }\n\n if (!found) missingIds.push(id);\n missingAimsIds.push(aimsId);\n } //search missing flights in flights stored before sync\n\n\n if (orgFlights) {\n for (var m = 0; m < missingIds.length; m++) {\n id = missingIds[m];\n aimsId = missingAimsIds[m];\n\n for (var o = 0; o < orgFlights.length; o++) {\n if (orgFlights[o].FlightId != null && orgFlights[o].FlightId == id || orgFlights[o].FlightAimsId != null && orgFlights[o].FlightAimsId == aimsId) {\n if (!relativeFlightMatcher(orgFlights[o], flights)) {\n flights.push(orgFlights[o]);\n }\n\n break;\n }\n }\n }\n }\n }\n } //FlightFactory.setFlightsToStorage(flights);\n\n\n FlightFactory.storeFlightsWithReportsAndMessages(flights, pilotReports, cabinReports, messages); // return true\n\n call.resolve(responseData);\n }, function (err) {\n call.reject(err);\n });\n return call.promise;\n },\n\n /**\r\n * Update local reports from synced Fligths \r\n * @memberof SyncAPIService\r\n */\n updatePilotReportLocalEditFromSynch: function updatePilotReportLocalEditFromSynch() {\n var pilotReportLocalEdits = PilotReportLocalEditFactory.getPilotReportsFromStorage();\n\n if (pilotReportLocalEdits != undefined && pilotReportLocalEdits != null) {\n for (var i = 0; i < pilotReportLocalEdits.length; i++) {\n var flight = FlightFactory.getFlightFromStorage(pilotReportLocalEdits[i].FlightId, pilotReportLocalEdits[i].FlightAimsId);\n\n if ((pilotReportLocalEdits[i].Status == \"draft\" || pilotReportLocalEdits[i].Status == \"completed\") && flight != undefined) {\n pilotReportLocalEdits[i].Departure = flight.Departure;\n pilotReportLocalEdits[i].Arrival = flight.Arrival;\n pilotReportLocalEdits[i].AcType = flight.AcType;\n pilotReportLocalEdits[i].AcTailNo = flight.AcTailNo;\n pilotReportLocalEdits[i].FlightNo = flight.FlightNo;\n pilotReportLocalEdits[i].DepartureICAO = flight.DepartureICAO;\n pilotReportLocalEdits[i].DepartureCountry = flight.DepartureCountry;\n pilotReportLocalEdits[i].DepartureName = flight.DepartureName;\n pilotReportLocalEdits[i].ArrivalICAO = flight.ArrivalICAO;\n pilotReportLocalEdits[i].ArrivalCountry = flight.ArrivalCountry;\n pilotReportLocalEdits[i].ArrivalName = flight.ArrivalName;\n pilotReportLocalEdits[i].ScheduledDepartureDateUTC = flight.ScheduledDepartureDateUTC;\n pilotReportLocalEdits[i].ScheduledDepartureTimeUTC = flight.ScheduledDepartureTimeUTC;\n pilotReportLocalEdits[i].ScheduledDeparture = flight.ScheduledDeparture;\n pilotReportLocalEdits[i].BookedC = flight.BookedC;\n pilotReportLocalEdits[i].BookedY = flight.BookedY;\n pilotReportLocalEdits[i].BookedInf = flight.BookedInf;\n pilotReportLocalEdits[i].BookedPad = flight.BookedPad;\n pilotReportLocalEdits[i].BookedChld = flight.BookedChld;\n pilotReportLocalEdits[i].ActualC = flight.ActualC;\n pilotReportLocalEdits[i].ActualY = flight.ActualY;\n pilotReportLocalEdits[i].ActualInf = flight.ActualInf;\n pilotReportLocalEdits[i].ActualPad = flight.ActualPad;\n pilotReportLocalEdits[i].ActualChld = flight.ActualChld;\n pilotReportLocalEdits[i].DepartureGate = flight.DepartureGate;\n pilotReportLocalEdits[i].DepartureTimezone = flight.DepartureTimezone;\n pilotReportLocalEdits[i].ArrivalTimezone = flight.ArrivalTimezone;\n pilotReportLocalEdits[i].CallSign = flight.CallSign;\n pilotReportLocalEdits[i].ScheduledArrival = flight.ScheduledArrival;\n pilotReportLocalEdits[i].crew = flight.crew;\n }\n }\n\n PilotReportLocalEditFactory.setPilotReportsToStorage(pilotReportLocalEdits);\n }\n }\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('SynchCtrl', SynchCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SynchCtrl\r\n * @description \r\n * Manage Sync View\r\n * @ngInject\r\n */\n\n function SynchCtrl($scope, $uibModalInstance, UserFactory, FlightFactory, PilotReportLocalEditFactory, SyncAPIService, SyncLogFactory, ReportGuidFactory, PilotReportSyncResultFactory, DataCleanerFactory, MessageFactory, MemoFactory, $route) {\n $scope.syncResultsVisible = false;\n $scope.isSynching = false; // get the number of reports to synch\n\n var reportstobesynched = PilotReportLocalEditFactory.getPilotReportLocalEditThatNeedToBeSynched(); // display the number of reports to synch\n\n $scope.number_of_reports_to_sync = reportstobesynched.length; // get the last sync date\n\n $scope.isFirstSync = false;\n $scope.isTooOldSync = false;\n $scope.lastSyncDate = '-';\n $scope.syncVersion = '1.1';\n var lastLog = SyncLogFactory.getSyncLog();\n\n if (lastLog == null) {\n $scope.isFirstSync = true;\n } else {\n if (lastLog.date != null) {\n $scope.lastSyncDate = new Date(lastLog.date).toUTC().toString('dd-MM-yyyy HH:mm') + ' UTC';\n if (Date.today().add(-3).days().toUTC().isAfter(new Date(lastLog.date).toUTC())) $scope.isTooOldSync = true;\n }\n\n if (lastLog.version != null) $scope.syncVersion = lastLog.version;\n } // get the report credits\n\n\n $scope.reportCredits = ReportGuidFactory.getRemainingReportGuids(); // setup the grid\n\n $scope.syncTableData = PilotReportLocalEditFactory.getPilotReportLocalEditThatNeedToBeSynched();\n $scope.doSynch = doSynch;\n $scope.ok = ok;\n $scope.cancel = cancel;\n $scope.showSyncResults = showSyncResults;\n $scope.syncResultsOk = syncResultsOk;\n /**\r\n * Start Synch functionality\r\n * @memberof SynchCtrl\r\n */\n\n function doSynch() {\n //waiting for memoIds before we sync\n MemoFactory.getStoredMemosIds(function (memoIdsToSend) {\n // get the user\n var user = UserFactory.getUser(); // call the remote service for data\n\n var q = SyncAPIService.doSync(user.aimsId, memoIdsToSend);\n $scope.isSynching = true;\n q.then(function (response) {\n $scope.isSynching = false;\n\n if ($scope.number_of_reports_to_sync > 0) {\n $scope.showSyncResults('synched');\n } else {\n $scope.showSyncResults('synched-no-send');\n }\n\n DataCleanerFactory.deleteSynchedLocalPilotReports();\n DataCleanerFactory.deleteOrphanedLocalReports();\n SyncAPIService.updatePilotReportLocalEditFromSynch();\n MemoFactory.markGroundDutiesUnread();\n });\n q[\"catch\"](function (err) {\n $scope.isSynching = false;\n\n if (err.status == -1) {\n $scope.errorName = \"There were problems during the server synchronization. Please try again.\";\n } else if (err.status != 401) {\n // if an error was encountered display an error message\n $scope.errorName = \"Could not reach the remote server. Please connect to the Internet and try again.\";\n } else {\n $uibModalInstance.close('');\n }\n });\n });\n }\n\n ;\n /**\r\n * Close modal\r\n * @memberof SynchCtrl\r\n */\n\n function ok() {\n $uibModalInstance.close('');\n }\n\n ;\n /**\r\n * show Report Sync Results\r\n * @memberof SynchCtrl\r\n */\n\n function cancel() {\n $uibModalInstance.close('cancel');\n }\n\n ;\n /**\r\n * show Report Sync Results\r\n * @memberof SynchCtrl\r\n */\n\n function showSyncResults(syncResult) {\n $scope.syncResultsVisible = true; // setup the grid\n\n $scope.syncResultsTableData = PilotReportSyncResultFactory.getPilotReportSyncResultsFromStorage();\n $scope.syncSuccesses = PilotReportSyncResultFactory.getSuccesses($scope.syncResultsTableData);\n $scope.syncFailures = PilotReportSyncResultFactory.getFailures($scope.syncResultsTableData);\n\n if ($scope.syncResultsTableData != null) {\n $scope.reports_to_sync = $scope.syncResultsTableData.length;\n } else {\n $scope.reports_to_sync = 0;\n }\n\n if ($scope.syncSuccesses == 1) {\n $scope.sync_successes_descr = 'Pilot Report was';\n } else {\n $scope.sync_successes_descr = 'Pilot Reports were';\n }\n\n if ($scope.syncFailures == 1) {\n $scope.sync_failures_descr = 'Pilot Report was';\n } else {\n $scope.sync_failures_descr = 'Pilot Reports were';\n }\n\n $scope.unreadMessages = MessageFactory.getCountOfUnreadMessages();\n }\n\n ;\n /**\r\n * show Report Sync Results\r\n * @memberof SynchCtrl\r\n */\n\n function syncResultsOk() {\n $uibModalInstance.close('synched');\n $route.reload();\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('SyncLogFactory', SyncLogFactory);\n /* @ngInject */\n\n function SyncLogFactory($log, GenericService) {\n // Define the constructor function.\n function SyncLog() {\n this.userAimsId = null;\n this.date = null;\n this.version = null;\n this.lastShow = null;\n this.isUpdated = false;\n this.lastScheduleDate = null;\n this.forceSync = false; //checks if sync log displayed in the last X minutes, to avoid constantly\n //showing the sync dialog\n\n this.canShowSync = canShowSync;\n }\n\n var objType = 'syncLog';\n var objCallback = SyncLog;\n var service = {\n getSyncLog: getSyncLog,\n setSyncLog: setSyncLog,\n updateSyncVersion: updateSyncVersion,\n setLastShow: setLastShow,\n clearSyncLog: clearSyncLog,\n getLastScheduleDate: getLastScheduleDate,\n setLastScheduleDate: setLastScheduleDate,\n forceSync: forceSync\n };\n\n function canShowSync() {\n var can = false;\n if (this.lastShow == null) can = true;else if (new Date().add(-10).minutes().toUTC().isAfter(new Date(this.lastShow).toUTC())) {\n can = true;\n }\n return can;\n }\n\n function getSyncLog() {\n return GenericService.getOne(objType, objCallback);\n }\n\n function setSyncLog(userAimsId, version, lastScheduleDate) {\n var newLog = new SyncLog();\n newLog.userAimsId = userAimsId;\n newLog.date = new Date();\n newLog.version = version;\n newLog.lastShow = new Date();\n newLog.isUpdated = false;\n newLog.forceSync = false;\n newLog.lastScheduleDate = new Date(lastScheduleDate).getTime();\n GenericService.saveOne(newLog, objType, objCallback);\n }\n\n function updateSyncVersion(version) {\n var syncLog = getSyncLog();\n syncLog.version = version;\n syncLog.isUpdated = true;\n GenericService.saveOne(syncLog, objType, objCallback);\n }\n\n function getLastScheduleDate() {\n var syncLog = getSyncLog();\n\n if (syncLog == null) {\n return null;\n } else {\n return syncLog.lastScheduleDate;\n }\n }\n\n function setLastScheduleDate(date) {\n var log = getSyncLog();\n if (log == null) log = new SyncLog();\n log.lastScheduleDate = date;\n GenericService.saveOne(log, objType, objCallback);\n }\n\n function setLastShow() {\n var log = getSyncLog();\n if (log == null) log = new SyncLog();\n log.lastShow = new Date();\n GenericService.saveOne(log, objType, objCallback);\n }\n\n function clearSyncLog() {\n GenericService.removeAll(objType, objCallback);\n }\n /**\r\n * Forces Sync Modal to appear\r\n * @memberof SyncLogFactory\r\n */\n\n\n function forceSync() {\n var syncLog = getSyncLog();\n if (syncLog == null) syncLog = new SyncLog();\n syncLog.forceSync = true;\n GenericService.saveOne(syncLog, objType, objCallback);\n } // Return constructor - this is what defines the actual\n // injectable in the DI framework.\n\n\n return service;\n }\n\n ;\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('PhotoFactory', PhotoFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PhotoFactory\r\n * @description \r\n * Manage Report's Photos.\r\n * @ngInject\r\n */\n\n function PhotoFactory(GenericModalFactory) {\n /**\r\n * Initialiaze Photo object \r\n * @memberof PhotoFactory\r\n */\n function Photo() {\n this.Id = null;\n this.Remarks = null;\n this.RemarksShort = null;\n this.PhotoData = null;\n this.FileType = null;\n }\n\n var service = {\n createNew: createNew,\n fromObject: fromObject,\n fromObjectList: fromObjectList,\n deleteFromList: deleteFromList\n };\n /**\r\n * Create a new Photo object \r\n * @memberof PhotoFactory\r\n * @returns {object} Photo\r\n */\n\n function createNew() {\n return GenericModalFactory.createNew(Photo);\n }\n /**\r\n * Extend given Photo object \r\n * @memberof PhotoFactory\r\n * @param {object} obj The Photo object that will be extended\r\n * @returns {object} Photo\r\n */\n\n\n function fromObject(obj) {\n return GenericModalFactory.fromObject(obj, Photo);\n }\n /**\r\n * Delete Photo object from given list\r\n * @memberof PhotoFactory\r\n * @param {object} obj The Photo object that will be deleted\r\n * @returns {array} Photos\r\n */\n\n\n function deleteFromList(obj, objList) {\n return GenericModalFactory.deleteFromList(obj, objList);\n }\n /**\r\n * Extend given Photo object \r\n * @memberof PhotoFactory\r\n * @param {object} obj The Photo object that will be extended\r\n * @returns {object} Photo\r\n */\n\n\n function fromObjectList(objList) {\n return GenericModalFactory.fromObjectList(objList, Photo);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('TicketCtrl', TicketCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name TicketCtrl\r\n * @description \r\n * Send a ticket\r\n * @ngInject\r\n */\n\n function TicketCtrl($scope, UserFactory, PhotoFactory, TicketAPIService, $location, $uibModal, version) {\n var user = UserFactory.getUser();\n user;\n $scope.submitted = false;\n $scope.ticket = {};\n $scope.ticket.photos = [];\n $scope.maximumAttatchedPhotos = 3;\n $scope.showMaxImages = false;\n $scope.quality = 0.6;\n $scope.width = 1280;\n $scope.height = 1024;\n $scope.sizeLimitKb = 1000;\n $scope.imageTooLargeMsg = false;\n $scope.gotoHome = gotoHome;\n $scope.state = 'ticket';\n $scope.ticket.Version = version;\n appendPhoto();\n $scope.sendTicket = sendTicket;\n $scope.imageUploaded = imageUploaded;\n $scope.removePhoto = removePhoto;\n\n if (user && user.aimsId && UserFactory.isLoggedIn()) {\n $scope.ticket.aimsId = user.aimsId;\n $scope.isLogged = true;\n }\n /**\r\n * Redirects to home view\r\n * @memberof TicketCtrl\r\n */\n\n\n function gotoHome() {\n $location.path(\"/\");\n }\n /**\r\n * Send application ticket information\r\n * @memberof TicketCtrl\r\n */\n\n\n function sendTicket() {\n $scope.submitted = true;\n\n if (validateTicket()) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Dialogs/dlgTicketSend.html',\n controller: 'TicketModalCtrl',\n size: 'md',\n backdrop: 'static',\n keyboard: false,\n resolve: {\n ticket: function ticket() {\n return $scope.ticket;\n }\n }\n });\n modalInstance.result.then(function () {\n $location.path(\"/\");\n });\n }\n }\n /**\r\n * Validate ticket before sending\r\n * @memberof TicketCtrl\r\n * @return {boolean} isValid\r\n */\n\n\n function validateTicket() {\n var isValid = false;\n\n if ($scope.ticket.aimsId && $scope.ticket.title && $scope.ticket.description) {\n isValid = true;\n }\n\n return isValid;\n }\n /**\r\n * is Image Too Large \r\n * @memberof TicketCtrl\r\n * @return {boolean} isValid\r\n */\n\n\n function isImageTooLarge(image) {\n var isLarge = false;\n\n if (image && image.dataURL != null) {\n isLarge = image.dataURL.length > $scope.sizeLimitKb * 1024;\n }\n\n return isLarge;\n }\n /**\r\n * Upload Image\r\n * @memberof TicketCtrl\r\n */\n\n\n function imageUploaded(data, img) {\n //console.log('told of a new image', imageResult, this.imageBrowsed, $scope.imageBrowsed);\n var imageResult = data; //$scope.imageBrowsed;\n\n if (imageResult != null) {\n if (isImageTooLarge(data)) {\n $scope.imageTooLargeMsg = true;\n } else {\n $scope.imageTooLargeMsg = false;\n img.PhotoData = imageResult.dataURL;\n img.FileType = imageResult.fileType || imageResult.file.type;\n img.Remarks = imageResult.fileName;\n appendPhoto();\n }\n }\n }\n /**\r\n * Allows to add more photos up to the maximum number allowed\r\n * @memberof TicketCtrl\r\n */\n\n\n function appendPhoto() {\n if ($scope.ticket.photos.length < $scope.maximumAttatchedPhotos) {\n var photo = PhotoFactory.createNew();\n $scope.ticket.photos.push(photo);\n } else {\n $scope.showMaxImages = true;\n }\n }\n /**\r\n * Remove Selected photo\r\n * @memberof TicketCtrl\r\n * @param {object} photo\r\n */\n\n\n function removePhoto(photo) {\n PhotoFactory.deleteFromList(photo, $scope.ticket.photos);\n\n if ($scope.showMaxImages) {\n appendPhoto();\n }\n\n $scope.showMaxImages = false;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.service(\"TicketAPIService\", TicketAPIService);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name TicketAPIService\r\n * @description \r\n * Manages the api calls for the Ticket report system\r\n * @ngInject\r\n */\n\n function TicketAPIService($http, $q, apiUrl, localStorageMD5Service, LogService) {\n /**\r\n * Send Ticket\r\n * @memberof TicketAPIService\r\n * @return {object} promise\r\n */\n function sendTicket(ticket) {\n var call = $q.defer();\n ticket.DeviceData = getStoredValues();\n $http.post(apiUrl + '/ticket', ticket, {\n 'Content-Type': 'application/json'\n }).then(function (responseData) {\n if (responseData == undefined || responseData.data == undefined || responseData.data.data == undefined) {\n var err = new Error();\n err.status = -1;\n var msg = \"ResponseData error while sending a ticket :\" + JSON.stringify(responseData);\n LogService.debug(msg, err);\n call.reject(err);\n } else {\n // return true\n call.resolve(responseData);\n }\n }, function (err) {\n call.reject(err);\n });\n return call.promise;\n }\n /**\r\n * Get all values from localstorage\r\n * @memberof TicketAPIService\r\n */\n\n\n function getStoredValues() {\n var values = [];\n var keys = localStorageMD5Service.keys();\n\n if (keys) {\n var key, value, sizeActual, error;\n\n for (var i = 0; i < keys.length; i++) {\n key = keys[i];\n\n try {\n value = localStorageMD5Service.get(key);\n value = angular.toJson(value);\n sizeActual = localStorageMD5Service.usedSize(key);\n error = null;\n } catch (e) {\n error = e.message || e.errorMessage;\n }\n\n values.push({\n key: key,\n value: value,\n error: error,\n size: value ? value.length : 0,\n sizeActual: sizeActual\n });\n }\n }\n\n return values;\n }\n\n return {\n sendTicket: sendTicket\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('TicketModalCtrl', TicketModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name TicketCtrl\r\n * @description \r\n * Report a bug of the application\r\n * @ngInject\r\n */\n\n function TicketModalCtrl($scope, $uibModalInstance, $timeout, TicketAPIService, LogService, PhotoFactory, ticket) {\n $scope.successful = false;\n $scope.error = false;\n var q = TicketAPIService.sendTicket(ticket);\n q.then(function (responseData) {\n if (responseData.data.data) {\n $scope.successful = true;\n } else {\n $scope.error = true;\n }\n\n $timeout(function () {\n $uibModalInstance.close();\n }, 3000);\n }, function () {\n $scope.error = true;\n $timeout(function () {\n $uibModalInstance.close();\n }, 3000);\n });\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('competencesReadOnly', competencesReadOnly);\n /**\r\n * @memberof PilotnReports\r\n * @ngdoc directive\r\n * @name competencesReadOnly\r\n * @restrict E\r\n * @description\r\n * Implementation of competences read only\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function competencesReadOnly() {\n function link(scope, element, attrs) {\n if (scope.trainee.Competences) {\n scope.trainee.Competences.forEach(function (competence) {\n competence.hasSelectedSubCompetence = competence.SubCompetences.some(function (x) {\n return x.Selected;\n });\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/TrainingReadOnly/competences-read-only.tpl.html',\n scope: {\n trainee: \"=\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('courseReadOnly', courseReadOnly);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name courseReadOnly\r\n * @restrict E\r\n * @description\r\n * Initialize read only view of what was submitted\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function courseReadOnly() {\n function link(scope) {\n scope.leftScroll = leftScroll;\n scope.rightScroll = rightScroll;\n scope.selectedTraineeSession = selectedTraineeSession;\n scope.selected = false;\n scope.selectedAbsentTraineeSession = selectedAbsentTraineeSession;\n scope.selectedPhase = scope.phases.find(function (x) {\n return x.PhaseId == scope.session.PhaseId;\n });\n scope.selectedTraineeBadge = {\n crewId: scope.session.TraineesSessions[0].CrewId\n };\n\n function leftScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\n }\n\n function rightScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\n }\n\n function selectedTraineeSession() {\n return function (traineeSession) {\n var showSession = false;\n\n if (traineeSession.CrewId === scope.selectedTraineeBadge.crewId) {\n showSession = true;\n }\n\n return showSession;\n };\n }\n\n function selectedAbsentTraineeSession() {\n return function (traineeSession) {\n var showPanel = false;\n\n if (traineeSession.CrewId === scope.selectedTraineeBadge.crewId && traineeSession.Items.length == 0) {\n showPanel = true;\n }\n\n return showPanel;\n };\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/TrainingReadOnly/course-read-only.tpl.html\",\n scope: {\n phases: \"=\",\n session: \"=\"\n },\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('gradingReadOnly', gradingReadOnly);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name gradingReadOnly\r\n * @restrict E\r\n * @description\r\n * Implementation of grading read only\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function gradingReadOnly() {\n function link(scope, element, attrs) {\n if (scope.settings) {\n scope.grading.GradeType = scope.settings.GradeType;\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/TrainingReadOnly/grading-read-only.tpl.html',\n scope: {\n grading: \"=\",\n settings: \"=\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('pilotFunctionReadOnly', pilotFunctionReadOnly);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name pilotFunctionReadOnly\r\n * @restrict E\r\n * @description\r\n * Implementation of sector history\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function pilotFunctionReadOnly(FlightFactory, UserFactory, $timeout, $routeParams) {\n function link(scope, element, attrs) {}\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/TrainingReadOnly/pilot-function-read-only.tpl.html',\n scope: {\n session: \"=\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('sectorHistory', sectorHistory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name sectorHistory\r\n * @restrict E\r\n * @description\r\n * Implementation of sector history\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function sectorHistory() {\n function link(scope, element, attrs) {}\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/TrainingReadOnly/sector-history.tpl.html',\n scope: {\n history: \"=\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('syllabusProgressReadOnly', syllabusProgressReadOnly);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name syllabusReadOnly\r\n * @restrict E\r\n * @description\r\n * Initialize read only view of submitted syllabus\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function syllabusProgressReadOnly() {\n function link(scope) {\n scope.showRemarks = {\n value: false\n };\n scope.oneAtATime = true;\n scope.filterItems = filterItems;\n scope.toggleItems = toggleItems;\n setSyllabus(scope.history);\n\n function setSyllabus(history) {\n var traineeSessionItems = [];\n scope.phase.Syllabus.SyllabusItems.forEach(function (item) {\n var syllabusItem = JSON.parse(JSON.stringify(item));\n syllabusItem.Tries = [];\n syllabusItem.Selected = false;\n var relatedSessionItem = history.SyllabusProgress.find(function (x) {\n return x.SyllabusItemId == syllabusItem.Id;\n });\n\n if (relatedSessionItem) {\n syllabusItem.hasRemarks = relatedSessionItem.Tries.some(function (x) {\n return x.Comments && x.Comments.length > 0;\n }) || relatedSessionItem.Tries.some(function (t) {\n return t.TryGrading.Competences.some(function (x) {\n return x.Comments && x.Comments.length > 0;\n });\n });\n syllabusItem.Selected = true;\n syllabusItem.Tries = relatedSessionItem.Tries;\n syllabusItem.Tries.forEach(function (attempt) {\n attempt.Selected = true;\n });\n }\n\n setPanelStyle(syllabusItem);\n traineeSessionItems.push(syllabusItem);\n });\n history.ItemsGrouped = SyllabusGrouping(traineeSessionItems);\n }\n\n function setPanelStyle(item) {\n var historyTriesCount = item.Tries.filter(function (x) {\n return x.isReadOnly;\n }).length;\n var newTriesCount = item.Tries.filter(function (x) {\n return !x.isReadOnly && x.Selected;\n }).length;\n item.TriesPerformedCount = historyTriesCount + newTriesCount;\n var completedItem = item.TriesPerformedCount >= item.MandatoryCount;\n\n if (item.MandatoryCount == 0) {\n //non-mandatory items are considered completed if performed at least once\n completedItem = item.TriesPerformedCount >= 1;\n }\n\n if (completedItem) {\n item.PanelClass = 'panel-green panel-border-left-green ';\n } else {\n item.PanelClass = 'panel-border-left-blue ';\n }\n }\n\n function SyllabusGrouping(items) {\n //Syllabus Items Group By 'GroupId'\n var syllabusGroups = [];\n items.forEach(function (item) {\n if (!syllabusGroups.some(function (x) {\n return x.Id == item.SelectedGroup.Id;\n })) {\n if (!item.SelectedGroup) {\n item.SelectedGroup = {\n Id: 0,\n Title: 'General'\n };\n }\n\n var syllabusGroup = {\n Id: item.SelectedGroup.Id,\n Title: item.SelectedGroup.Title ? item.SelectedGroup.Title : 'General',\n Items: []\n };\n syllabusGroup.Items.push(item);\n syllabusGroups.push(syllabusGroup);\n } else {\n syllabusGroups.filter(function (x) {\n return x.Id == item.SelectedGroup.Id;\n })[0].Items.push(item);\n }\n });\n return syllabusGroups;\n }\n\n function filterItems() {\n return function (item) {\n var showItem = true;\n\n if (scope.showRemarks.value) {\n showItem = item.hasRemarks;\n } else {\n scope.oneAtATime = true;\n }\n\n return showItem;\n };\n }\n\n function toggleItems() {\n scope.oneAtATime = !scope.showRemarks.value;\n scope.history.ItemsGrouped.forEach(function (syllabusGroup) {\n syllabusGroup.Items.forEach(function (item) {\n item.isOpen = scope.showRemarks.value;\n });\n });\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: 'views/TrainingReadOnly/syllabus-progress-read-only.tpl.html',\n scope: {\n phase: \"=\",\n history: \"=\"\n },\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('syllabusReadOnly', syllabusReadOnly);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name syllabusReadOnly\r\n * @restrict E\r\n * @description\r\n * Initialize read only view of submitted syllabus\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function syllabusReadOnly() {\n function link(scope) {\n setSyllabus(scope.traineeSession);\n\n function setSyllabus(traineeSession) {\n var traineeSessionItems = [];\n scope.phase.Syllabus.SyllabusItems.forEach(function (item) {\n var syllabusItem = JSON.parse(JSON.stringify(item));\n syllabusItem.Tries = [];\n syllabusItem.Selected = false;\n var relatedSessionItem = null;\n\n if (scope.type == \"signature\") {\n relatedSessionItem = traineeSession.Items.find(function (x) {\n return x.Id == syllabusItem.Id;\n });\n } else {\n relatedSessionItem = traineeSession.Items.find(function (x) {\n return x.SyllabusItemId == syllabusItem.Id;\n });\n }\n\n if (relatedSessionItem) {\n syllabusItem.Selected = true;\n syllabusItem.Tries = relatedSessionItem.Tries;\n }\n\n if (scope.type == \"signature\") {\n setPanelStyleByProgress(syllabusItem);\n } else {\n setPanelStyleBySelected(syllabusItem);\n }\n\n traineeSessionItems.push(syllabusItem);\n });\n traineeSession.ItemsGrouped = SyllabusGrouping(traineeSessionItems);\n traineeSession.ItemsGrouped.forEach(function (group) {\n group.Items.forEach(function (item) {\n //find first not ReadOnly try\n item.firstTry = item.Tries.find(function (x) {\n return !x.isReadOnly;\n });\n });\n });\n }\n\n function setPanelStyleByProgress(item) {\n var historyTriesCount = item.Tries.filter(function (x) {\n return x.isReadOnly;\n }).length;\n var newTriesCount = item.Tries.filter(function (x) {\n return !x.isReadOnly && x.Selected;\n }).length;\n item.TriesPerformedCount = historyTriesCount + newTriesCount;\n var completedItem = item.TriesPerformedCount >= item.MandatoryCount;\n\n if (item.MandatoryCount == 0) {\n //non-mandatory items are considered completed if performed at least once\n completedItem = item.TriesPerformedCount >= 1;\n }\n\n if (completedItem) {\n item.PanelClass = 'panel-green panel-border-left-green ';\n } else {\n item.PanelClass = 'panel-border-left-blue ';\n }\n }\n\n function setPanelStyleBySelected(item) {\n var newTriesCount = item.Tries.filter(function (x) {\n return x.Selected;\n }).length;\n var selectedItem = newTriesCount > 0;\n\n if (selectedItem) {\n item.PanelClass = 'panel-green panel-border-left-green ';\n } else {\n item.PanelClass = 'panel-border-left-blue ';\n }\n }\n\n function SyllabusGrouping(items) {\n //Syllabus Items Group By 'GroupId'\n var syllabusGroups = [];\n items.forEach(function (item) {\n if (!syllabusGroups.some(function (x) {\n return x.Id == item.SelectedGroup.Id;\n })) {\n if (!item.SelectedGroup) {\n item.SelectedGroup = {\n Id: 0,\n Title: 'General'\n };\n }\n\n var syllabusGroup = {\n Id: item.SelectedGroup.Id,\n Title: item.SelectedGroup.Title ? item.SelectedGroup.Title : 'General',\n Items: []\n };\n syllabusGroup.Items.push(item);\n syllabusGroups.push(syllabusGroup);\n } else {\n syllabusGroups.filter(function (x) {\n return x.Id == item.SelectedGroup.Id;\n })[0].Items.push(item);\n }\n });\n return syllabusGroups;\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: 'views/TrainingReadOnly/syllabus-read-only.tpl.html',\n scope: {\n phase: \"=\",\n traineeSession: \"=\",\n type: \"=\"\n },\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('certificateExam', certificateExam);\n /**\r\n * @ngdoc directive\r\n * @name certificateExam\r\n * @restrict E\r\n * @description\r\n * Implementation of certificate exam grading\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function certificateExam(TrainingSessionFactory, FlightSessionFactory) {\n function link(scope, element, attrs) {\n if (scope.trainees) collapseAll();\n scope.validateTrainee = validateTrainee;\n scope.getRemainingCharacters = getRemainingCharacters;\n scope.collapseAll = collapseAll;\n scope.gradeUp = gradeUp;\n scope.gradeDown = gradeDown;\n var courseId = scope.dutyCourse.Id;\n var isGround = false;\n\n if (scope.groundDuty) {\n isGround = true;\n var date = scope.groundDuty.DutyDateS;\n var dutyId = scope.groundDuty.Id;\n } else {\n var date = scope.crewRouteDuty.date;\n var dutyNo = scope.crewRouteDuty.DutyNo;\n var dutyDay = scope.crewRouteDuty.DutyDay;\n }\n\n var gradeBase = scope.selectedPhase.ReleaseGrading.CertificateGradeBase;\n scope.gradeBase = gradeBase;\n scope.gradeMin = 0;\n scope.gradeMax = 100; //Accordion setting\n\n scope.oneAtATime = true;\n scope.gradingStatus = 'All'; //Initialize trainees \n\n scope.sessions = [];\n scope.trainees.filter(function (x) {\n return x.EligibilityStatus && !x.Session.Absent;\n }).forEach(function (trainee) {\n var session = trainee.Session.ReleaseGrading;\n session.Name = trainee.Name;\n session.AimsId = trainee.AimsId;\n session.isOpen = false;\n if (!session.CertificateOutcome) session.CertificateOutcome = \"Pass\";\n if (gradeBase && !session.Grade) session.Grade = gradeBase;\n if (!gradeBase) session.Grade = null;\n scope.sessions.push(session);\n });\n scope.sessions.forEach(function (traineeSession) {\n validateGrading(traineeSession);\n });\n\n function validateGrading(trainee) {\n // Invalid grading\n // 1. If none\n // 2. Over gradeMax\n // 3. Below gradeMin\n // 4. Non numeric\n trainee.isCertificateValid = gradeBase ? trainee.Grade != null && trainee.Grade != undefined : true;\n }\n\n function validateTrainee(trainee) {\n if (gradeBase) {\n validateGrading(trainee);\n\n if (trainee.isCertificateValid) {\n calculateOutcome(trainee);\n }\n }\n\n if (isGround) {\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) {\n console.log(e);\n });\n } else {\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) {\n console.log(e);\n });\n }\n }\n\n function gradeUp(trainee) {\n if (trainee.isCertificateValid && trainee.Grade < scope.gradeMax) {\n trainee.Grade++;\n }\n\n if (!trainee.isCertificateValid) {\n trainee.Grade++;\n }\n\n validateTrainee(trainee);\n }\n\n function gradeDown(trainee) {\n if (trainee.isExamValid && trainee.Grade > scope.gradeMin) {\n trainee.Grade--;\n }\n\n if (!trainee.isExamValid) {\n trainee.Grade--;\n }\n\n validateTrainee(trainee);\n }\n\n function calculateOutcome(trainee) {\n if (trainee.Grade < gradeBase) {\n trainee.CertificateOutcome = \"Fail\";\n } else {\n trainee.CertificateOutcome = \"Pass\";\n }\n }\n\n function getRemainingCharacters(text, max) {\n if (typeof text === \"undefined\" || text === null) return '';\n if (typeof max === \"undefined\" || max === null || max < 0 || !max) max = 4000;\n var length = text.length;\n return 'characters left: ' + (max - length);\n }\n\n function collapseAll() {\n scope.isAllOpen = !scope.isAllOpen;\n scope.trainees.forEach(function (trainee) {\n var session = trainee.Session.ReleaseGrading;\n session.isOpen = scope.isAllOpen;\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/certificate-exam.tpl.html',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('CompetenceModalCtrl', CompetenceModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CompetenceModalCtrl\r\n * @description \r\n * Show competence grading helper\r\n * @ngInject\r\n */\n\n function CompetenceModalCtrl($scope, $uibModalInstance, competence) {\n $scope.close = close;\n $scope.competence = competence;\n /**\r\n * Close the modal\r\n * @memberof CompetenceModalCtrl\r\n */\n\n function close() {\n $uibModalInstance.close($scope.competence.Grading);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('competences', competences);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name certificates\r\n * @restrict E\r\n * @description\r\n * Implementation of competences\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function competences($uibModal, $timeout) {\n function link(scope, element, attrs) {\n scope.manageCompetenceGrading = manageCompetenceGrading;\n scope.selectSubCompetence = selectSubCompetence;\n scope.openGradingModal = openGradingModal;\n scope.trainee.Competences.forEach(function (competence) {\n competence.isCollapsed = competence.hasMandatory || competence.hasOptional;\n competence.showComments = competence.hasMandatory || competence.hasOptional || competence.Comments && competence.Comments != \"\";\n });\n validateTraineeCompetences(scope.trainee);\n\n function validateTraineeCompetences(trainee) {\n var missingGrading = trainee.Competences.some(function (c) {\n return c.Grading == null;\n });\n var missingPerformanceIndicators = trainee.Competences.filter(function (c) {\n return c.hasMandatory;\n }).some(function (c) {\n return !c.SubCompetences.some(function (sub) {\n return sub.Selected;\n });\n });\n trainee.isCompetenceValid = !missingGrading && !missingPerformanceIndicators;\n }\n\n function manageCompetenceGrading(competence) {\n var grading = competence.Grading ? Number(competence.Grading) : null;\n var hadMandatory = competence.hasMandatory;\n var hadOptional = competence.hasOptional;\n competence.hasMandatory = competence.MandatorySub.includes(grading);\n competence.hasOptional = competence.OptionalSub.includes(grading);\n competence.isCollapsed = competence.hasMandatory || competence.hasOptional;\n if (competence.isCollapsed) competence.showComments = true; //From Mandatory to None remove selected Sub Competences\n\n if ((hadMandatory || hadOptional) && !competence.hasMandatory && !competence.hasOptional) {\n competence.SubCompetences.forEach(function (sub) {\n sub.Selected = false;\n });\n }\n\n validateTraineeCompetences(scope.trainee);\n\n switch (competence.Grading) {\n case 5:\n competence.GradingMessage = competence.GradeA;\n break;\n\n case 4:\n competence.GradingMessage = competence.GradeB;\n break;\n\n case 3:\n competence.GradingMessage = competence.GradeC;\n break;\n\n case 2:\n competence.GradingMessage = competence.GradeD;\n break;\n\n case 1:\n competence.GradingMessage = competence.GradeE;\n break;\n\n default:\n competence.GradingMessage = \"\";\n }\n\n scope.gradingSelection();\n }\n\n function selectSubCompetence(sub) {\n sub.Selected = !sub.Selected;\n if (sub.Selected) scope.gradingSelection();\n validateTraineeCompetences(scope.trainee);\n }\n\n function openGradingModal(_competence) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgCompetenceGrading.html',\n controller: 'CompetenceModalCtrl',\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n competence: function competence() {\n return _competence;\n }\n }\n });\n modalInstance.result.then(function (grading) {\n if (grading) {\n manageCompetenceGrading(_competence, grading);\n }\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/competences.tpl.html',\n scope: {\n trainee: \"=\",\n gradingSelection: \"&onGradingSelection\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('courseFooter', courseFooter);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name courseFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of courseFooter (appears in course view)\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function courseFooter($location, $routeParams) {\n function link(scope) {\n scope.gotoCalendar = gotoCalendar;\n scope.gotoGroundDuty = gotoGroundDuty;\n scope.gotoCrewRoute = gotoCrewRoute;\n scope.gotoFlight = gotoFlight;\n\n function gotoCalendar() {\n $location.path(\"/\");\n }\n\n function gotoGroundDuty() {\n $location.path('/groundDuty/' + Number($routeParams.dutyId));\n }\n\n function gotoCrewRoute() {\n var dutyNo = scope.crewRouteDuty.DutyNo;\n var dutyDay = scope.crewRouteDuty.DutyDay;\n $location.path('/crewRoute/' + dutyNo + '/' + dutyDay);\n }\n\n function gotoFlight() {\n var flightId = Number($routeParams.flightId);\n $location.path('/flightinfo/' + flightId);\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/Training/course-footer.tpl.html\",\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('course', course);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name course\r\n * @restrict E\r\n * @description\r\n * Implementation of training course\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function course(GroundDutyFactory, CourseFactory, TrainingSessionFactory, FlightSessionFactory, $timeout, $uibModal, $location, $routeParams, $window) {\n function link(scope, element, attrs) {\n var _courseId = scope.dutyCourse.Id;\n var isGround = false;\n\n if (scope.groundDuty) {\n isGround = true;\n var _date = scope.groundDuty.DutyDateS;\n var _dutyId = scope.groundDuty.Id;\n } else {\n var _date = scope.crewRouteDuty.date;\n var _dutyNo = scope.crewRouteDuty.DutyNo;\n var _dutyDay = scope.crewRouteDuty.DutyDay;\n var trainingFlightIds = scope.crewRouteDuty.Courses.find(function (x) {\n return x.CourseId == _courseId && new moment(x.Date).isSame(_date);\n }).TrainingFlightIds;\n if (scope.course.Media) scope.course.Media.radioModel = \"Flight\";\n }\n\n scope.isGround = isGround;\n scope.updateSession = updateSession;\n scope.availableCourseInfo = false;\n scope.oneTraineeAtATime = true;\n scope.allAbsent = false;\n scope.SubmitSession = SubmitSession;\n scope.close = close;\n scope.updateTraineeSignatures = updateTraineeSignatures;\n scope.checkReleaseAvailability = checkReleaseAvailability;\n scope.setReleaseStatus = setReleaseStatus;\n scope.reloadReleasePanel = reloadReleasePanel;\n scope.showReleasePanel = showReleasePanel;\n scope.filterSelectedSyllabus = filterSelectedSyllabus;\n scope.filterPresentTrainees = filterPresentTrainees;\n scope.selectedPhaseIndex = selectedPhaseIndex();\n scope.releaseTrainee = releaseTrainee;\n scope.showReleaseBtn = showReleaseBtn;\n scope.showGroupReleaseBtn = showGroupReleaseBtn;\n scope.releaseGroup = releaseGroup;\n scope.validateTraineeForm = validateTraineeForm;\n scope.openTraineeSignature = openTraineeSignature;\n scope.resetSignature = resetSignature;\n scope.getTraineeClass = getTraineeClass;\n scope.leftScroll = leftScroll;\n scope.rightScroll = rightScroll;\n scope.togglePanel = togglePanel;\n scope.isReleaseSelected = false;\n scope.toggleBtn = toggleBtn;\n\n function toggleBtn() {\n scope.isReleaseSelected = !scope.isReleaseSelected;\n }\n\n function selectedPhaseIndex() {\n var index = 0;\n scope.course.CrewCoursePhases.some(function (phase, i) {\n if (phase.PhaseId == scope.selectedPhase.PhaseId) {\n index = i;\n return true;\n }\n });\n return index;\n }\n\n function filterSelectedSyllabus() {\n return function (syllabus) {\n var showTrainee = true;\n\n if (scope.traineeSyllabi && scope.traineeSyllabi.length > 1) {\n showTrainee = syllabus.TraineeIds[0] == scope.selectedTrainee.CrewId;\n }\n\n return showTrainee;\n };\n }\n\n function filterPresentTrainees() {\n return function (trainee) {\n return !trainee.Session.Absent;\n };\n }\n\n scope.reloadFooter = true;\n scope.reloadRelease = true;\n setTraineeSessions();\n updateSession();\n setReleaseStatus();\n\n function ResetTraineeSignatures() {\n scope.trainees.forEach(function (trainee) {\n trainee.Session.Authorized = false;\n });\n }\n\n function setReleaseStatus() {\n scope.trainees.forEach(function (trainee) {\n trainee.ShowReleaseWarning = false;\n });\n scope.course.AvailableRelease = checkReleaseAvailability(); //Handle trainee signatures\n\n scope.requiresTraineeSignature = RequiresTraineeSignature();\n if (!scope.requiresTraineeSignature) ResetTraineeSignatures();\n scope.allSignaturesComplete = !scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.Session.Authorized;\n });\n scope.someSignaturesComplete = scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return x.Session.Authorized;\n }); //For flights : check minDays - minSectors\n\n if (!isGround && scope.course.AvailableRelease && (scope.selectedPhase.MinDays > 0 || scope.selectedPhase.MinSectors > 0)) {\n scope.trainees.filter(function (x) {\n return x.AvailableRelease;\n }).forEach(function (trainee) {\n var phaseInfo = trainee.Phases.find(function (x) {\n return x.PhaseId == scope.selectedPhase.PhaseId;\n });\n var completedDays = 0;\n var completedSectors = 0;\n\n if (phaseInfo.Sessions) {\n //previous sessions\n completedDays = phaseInfo.Sessions.length;\n phaseInfo.Sessions.forEach(function (pastSession) {\n if (pastSession.Sectors) {\n completedSectors = completedSectors + pastSession.Sectors.length;\n }\n });\n }\n\n trainee.CompletedDays = completedDays + 1; //add current day\n\n trainee.CompletedSectors = completedSectors + trainingFlightIds.length; //add current sectors\n\n if (trainee.CompletedDays < scope.selectedPhase.MinDays || trainee.CompletedSectors < scope.selectedPhase.MinSectors) {\n trainee.ShowReleaseWarning = true;\n }\n });\n } //For ground: check aircraft visits\n\n\n if (isGround && (scope.course.AvailableRelease || scope.selectedPhase.ModuleType == \"Check\") && scope.selectedPhase.AircraftTypes.length) {\n var trainees = scope.trainees;\n if (scope.selectedPhase.ModuleType != \"Check\") trainees.filter(function (x) {\n return x.AvailableRelease;\n });\n trainees.forEach(function (trainee) {\n var phaseInfo = trainee.Phases.find(function (x) {\n return x.PhaseId == scope.selectedPhase.PhaseId;\n });\n var visitedAircrafts = [];\n\n if (phaseInfo.Sessions) {\n //previous sessions\n phaseInfo.Sessions.forEach(function (session) {\n visitedAircrafts = visitedAircrafts.concat(session.AircraftTypesVisited);\n });\n }\n\n if (scope.course.Media) {\n trainee.visitedAircrafts = visitedAircrafts.concat(scope.course.Media.inputAircrafts); //add current arvis\n }\n\n trainee.pendingAircrafts = [];\n trainee.pairPendingAircrafts = [];\n var pendingAircrafts = [];\n scope.selectedPhase.AircraftTypes.forEach(function (type) {\n var array = type.split(','); //if arvi requirement is not met\n\n if (trainee.visitedAircrafts && !array.some(function (x) {\n return trainee.visitedAircrafts.includes(x);\n })) {\n var pendingArviList = [];\n\n if (array.length > 1) {\n array.forEach(function (arvi) {\n pendingArviList.push(arvi);\n });\n } else {\n pendingArviList.push(array[0]);\n }\n\n pendingAircrafts.push(pendingArviList);\n }\n });\n trainee.pendingAircrafts = pendingAircrafts;\n trainee.ShowReleaseWarning = trainee.pendingAircrafts.length > 0;\n });\n }\n\n scope.showReleaseWarning = scope.trainees.some(function (x) {\n return x.ShowReleaseWarning;\n });\n }\n\n function reloadReleasePanel() {\n setReleaseStatus();\n scope.reloadRelease = false;\n $timeout(function () {\n scope.reloadRelease = true;\n }, 100);\n }\n\n function updateSession() {\n scope.trainees.forEach(function (trainee) {\n trainee.Session.selected = false;\n });\n\n if (scope.selectedTraineeBadge && scope.trainees.find(function (x) {\n return x.CrewId == scope.selectedTraineeBadge.CrewId;\n })) {\n scope.trainees.find(function (x) {\n return x.CrewId == scope.selectedTraineeBadge.CrewId;\n }).Session.selected = true;\n scope.selectedTrainee = scope.trainees.find(function (x) {\n return x.Session.selected;\n });\n }\n\n if (isGround) {\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, _courseId, _date, _dutyId, console.log, function (e) {\n console.log(e);\n });\n } else {\n FlightSessionFactory.updateSession(scope.trainees, scope.course, _courseId, _date, _dutyNo, _dutyDay, console.log, function (e) {\n console.log(e);\n });\n }\n }\n\n function setTraineeSessions() {\n var phase = scope.selectedPhase; // Set Day Grading\n\n var dayCompetences = phase.DayGrading.Competences;\n dayCompetences.forEach(function (competence) {\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences);\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences); //Filter out from optional the ones common with mandatory\n\n competence.OptionalSub = competence.OptionalSub.filter(function (c) {\n return !competence.MandatorySub.includes(c);\n });\n });\n var dayGradingSessions = scope.trainees.map(function (x) {\n return x.Session.DayGrading;\n });\n dayGradingSessions.forEach(function (traineeSession) {\n traineeSession.Competences = setTraineeCompetences(dayCompetences, traineeSession);\n }); // Set Release Grading\n\n var releaseCompetences = phase.ReleaseGrading.Competences;\n releaseCompetences.forEach(function (competence) {\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences);\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences); //Filter out from optional the ones common with mandatory\n\n competence.OptionalSub = competence.OptionalSub.filter(function (c) {\n return !competence.MandatorySub.includes(c);\n });\n });\n var releaseGradingSessions = scope.trainees.map(function (x) {\n return x.Session.ReleaseGrading;\n });\n releaseGradingSessions.forEach(function (traineeSession) {\n traineeSession.Competences = setTraineeCompetences(releaseCompetences, traineeSession);\n }); // Set Syllabus\n\n if (scope.selectedPhase.Syllabus) setSyllabus(); //Check if all are absent\n\n if (scope.trainees && scope.trainees.length && !scope.trainees.some(function (x) {\n return !x.Session.Absent;\n })) {\n scope.allAbsent = true;\n }\n }\n\n function setSyllabus() {\n var traineeSyllabi = [];\n\n if (!scope.selectedPhase.Syllabus.IsGradable && !scope.selectedPhase.InFlight) {\n //Non Gradable syllabus & Ground: All trainees share the same syllabus\n var traineeSyllabus = {\n TraineeIds: scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).map(function (x) {\n return x.CrewId;\n }),\n Items: []\n };\n traineeSyllabi.push(traineeSyllabus);\n } else {\n //Gradable syllabus || flight: each trainee will have its own\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n var traineeSyllabus = {\n TraineeIds: [trainee.CrewId],\n Items: []\n };\n traineeSyllabi.push(traineeSyllabus);\n });\n } //Set syllabus item sub competences \n\n\n scope.selectedPhase.Syllabus.SyllabusItems.forEach(function (item) {\n item.Competences.forEach(function (competence) {\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences);\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences); //Filter out from optional the ones common with mandatory\n\n competence.OptionalSub = competence.OptionalSub.filter(function (c) {\n return !competence.MandatorySub.includes(c);\n });\n });\n });\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n var traineeSessionItems = [];\n scope.selectedPhase.Syllabus.SyllabusItems.forEach(function (item) {\n var syllabusItem = JSON.parse(JSON.stringify(item)); //Get any history tries\n\n var historyTries = [];\n\n if (syllabusItem.History && syllabusItem.History.length) {\n var itemsHistory = syllabusItem.History.filter(function (x) {\n return x.CrewId == trainee.CrewId;\n });\n\n if (itemsHistory.length) {\n var allHistoryTries = [];\n itemsHistory.forEach(function (item) {\n allHistoryTries = allHistoryTries.concat(item.Tries);\n });\n allHistoryTries.forEach(function (historyTry) {\n var performedTry = {\n Comments: null,\n ActionNo: 0\n };\n performedTry.ActionNo = historyTry.ActionNo;\n performedTry.isReadOnly = true;\n performedTry.Comments = historyTry.Comments;\n performedTry.InstructorName = historyTry.InstructorName;\n performedTry.SubmissionDate = historyTry.SubmissionDate;\n performedTry.Grade = historyTry.TryGrading.Grade;\n performedTry.AcTypes = historyTry.AcTypes;\n performedTry.Sectors = historyTry.Sectors;\n historyTries.push(performedTry);\n });\n }\n }\n\n var relatedSessionItem = trainee.Session.Items.find(function (x) {\n return x.Id == syllabusItem.Id;\n }); //Pending tries\n\n var pendingTriesLeft = syllabusItem.MandatoryCount - historyTries.length;\n\n if (syllabusItem.MandatoryCount == 0 && historyTries.length == 0) {\n //for non-mandatory items: add 1 attempt if not already performed\n pendingTriesLeft = 1;\n }\n\n var pendingTries = [];\n\n for (var i = 0; i < pendingTriesLeft; i++) {\n pendingTries.push({\n Comments: null,\n ActionNo: historyTries.length + i + 1,\n isFirstTry: i == 0,\n TryGrading: {\n Grade: syllabusItem.DefaultGrade ? syllabusItem.DefaultGrade : null,\n Competences: [],\n GradeType: syllabusItem.GradeType\n }\n });\n } //Add pending tries to history tries\n\n\n var tries = historyTries.concat(pendingTries); //Create syllabus item depending on existing values\n\n if (!relatedSessionItem) {\n tries.filter(function (x) {\n return !x.isReadOnly;\n }).forEach(function (attempt) {\n attempt.TryGrading.Competences = setTraineeCompetences(syllabusItem.Competences, attempt.TryGrading);\n });\n var newItem = {\n RepeatRequired: false,\n Selected: false,\n Tries: tries,\n PhaseId: scope.selectedPhase.PhaseId,\n Id: syllabusItem.Id\n };\n traineeSessionItems.push(newItem);\n mergeSyllabusItemWithSession(syllabusItem, newItem);\n } else {\n var sessionTries = [];\n tries.forEach(function (tryItem) {\n var relatedSessionTry = relatedSessionItem.Tries.find(function (x) {\n return x.ActionNo == tryItem.ActionNo;\n });\n\n if (relatedSessionTry && !tryItem.isReadOnly) {\n sessionTries.push(deepCopy(relatedSessionTry));\n } else {\n sessionTries.push(deepCopy(tryItem));\n }\n }); //Add any Extra tries\n\n if (syllabusItem.MandatoryCount > 0) {\n var extraTries = relatedSessionItem.Tries.filter(function (x) {\n return x.ActionNo > syllabusItem.MandatoryCount && !x.isReadOnly;\n });\n sessionTries = sessionTries.concat(extraTries);\n }\n\n sessionTries.filter(function (x) {\n return !x.isReadOnly;\n }).forEach(function (attempt) {\n attempt.TryGrading.Competences = setTraineeCompetences(syllabusItem.Competences, attempt.TryGrading);\n });\n var existingItem = {\n RepeatRequired: relatedSessionItem.RepeatRequired,\n Selected: relatedSessionItem.Selected,\n Tries: sessionTries,\n PhaseId: scope.selectedPhase.PhaseId,\n Id: syllabusItem.Id\n };\n traineeSessionItems.push(existingItem);\n mergeSyllabusItemWithSession(syllabusItem, existingItem);\n }\n\n var traineeSyllabus = traineeSyllabi.find(function (x) {\n return x.TraineeIds.includes(trainee.CrewId);\n });\n\n if (!traineeSyllabus.Items.some(function (x) {\n return x.Id == syllabusItem.Id;\n })) {\n traineeSyllabus.Items.push(syllabusItem);\n }\n });\n trainee.Session.Items = traineeSessionItems;\n });\n traineeSyllabi.forEach(function (syllabus) {\n SyllabusGrouping(syllabus);\n });\n scope.traineeSyllabi = traineeSyllabi;\n }\n\n function mergeSyllabusItemWithSession(syllabusItem, sessionItem) {\n syllabusItem.RepeatRequired = sessionItem.RepeatRequired;\n syllabusItem.Selected = sessionItem.Selected;\n syllabusItem.Tries = sessionItem.Tries;\n }\n\n function leftScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\n }\n\n function rightScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\n }\n\n function deepCopy(originalObject) {\n return JSON.parse(JSON.stringify(originalObject));\n }\n\n function SyllabusGrouping(syllabus) {\n //Syllabus Items Group By 'GroupId'\n var syllabusGroups = [];\n syllabus.Items.forEach(function (item) {\n if (!syllabusGroups.some(function (x) {\n return x.Id == item.SelectedGroup.Id;\n })) {\n if (!item.SelectedGroup) {\n item.SelectedGroup = {\n Id: 0,\n Title: 'General'\n };\n }\n\n var syllabusGroup = {\n Id: item.SelectedGroup.Id,\n Title: item.SelectedGroup.Title ? item.SelectedGroup.Title : 'General',\n Items: []\n };\n syllabusGroup.Items.push(item);\n syllabusGroups.push(syllabusGroup);\n } else {\n syllabusGroups.filter(function (x) {\n return x.Id == item.SelectedGroup.Id;\n })[0].Items.push(item);\n }\n });\n syllabus.ItemsGrouped = syllabusGroups;\n }\n\n function setTraineeCompetences(competences, sessionItem) {\n var traineeCompetences = [];\n competences.forEach(function (competence) {\n var traineeCompetence = JSON.parse(JSON.stringify(competence));\n var existingCompetence = sessionItem.Competences.find(function (x) {\n return x.Id == traineeCompetence.Id;\n }); //Get saved values\n\n traineeCompetence.Grading = existingCompetence ? existingCompetence.Grading : null;\n traineeCompetence.Comments = existingCompetence ? existingCompetence.Comments : null;\n\n if (existingCompetence) {\n traineeCompetence.SubCompetences.filter(function (x) {\n return existingCompetence.SubCompetences.some(function (y) {\n return y.Id == x.Id;\n });\n }).forEach(function (commonSub) {\n commonSub.Selected = existingCompetence.SubCompetences.find(function (s) {\n return s.Id == commonSub.Id;\n }).Selected;\n });\n traineeCompetence.hasMandatory = traineeCompetence.MandatorySub.includes(Number(traineeCompetence.Grading));\n traineeCompetence.hasOptional = traineeCompetence.OptionalSub.includes(Number(traineeCompetence.Grading));\n }\n\n traineeCompetences.push(traineeCompetence);\n });\n return traineeCompetences;\n }\n\n function setSubCompetenceValues(current) {\n var updated = [];\n var first = parseInt(current[0], 10);\n var last = current[current.length - 1];\n\n if (first) {\n for (var i = first; i <= last; i++) {\n updated.push(i);\n }\n }\n\n return updated;\n }\n /***************************************************************** Submit ********************************************************************************/\n\n\n function SubmitSession() {\n setReleaseStatus();\n\n if (!isValidForm()) {\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgSubmitValidation.html',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'lg'\n });\n } else {\n if (isGround) {\n //Last save before submission\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, _courseId, _date, _dutyId, function () {\n // Get all trainees found for this session (filter by course and date)\n TrainingSessionFactory.getSessionTrainees(_courseId, _date, _dutyId, function (Trainees) {\n manageSubmission(Trainees);\n });\n });\n } else {\n //Last save before submission\n FlightSessionFactory.updateSession(scope.trainees, scope.course, _courseId, _date, _dutyNo, _dutyDay, function () {\n // Get all trainees found for this session (filter by course and date)\n FlightSessionFactory.getSessionTrainees(_courseId, _date, _dutyNo, _dutyDay, function (Trainees) {\n manageSubmission(Trainees);\n });\n });\n }\n }\n }\n\n function manageSubmission(Trainees) {\n PrepareSessionForSubmission(Trainees);\n setReleaseStatus();\n\n var _requiresInstructorSignature = RequiresInstructorSignature();\n\n var _confirmationMsg = scope.selectedPhase.ReleaseGrading.ConfirmationMessage; // submit now\n\n var _releaseGrading = (scope.selectedPhase.ReleaseGrading.Comments || scope.selectedPhase.ReleaseGrading.GradeType == 'Numeric' || scope.selectedPhase.ReleaseGrading.GradeType == 'Outcome' || scope.selectedPhase.ReleaseGrading.Competences.length) && scope.selectedPhase.ReleaseGrading.GradeType != 'CertificateExam';\n\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgSign.html',\n controller: 'SignatureModalCtrl',\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n courseId: function courseId() {\n return _courseId;\n },\n date: function date() {\n return _date;\n },\n dutyId: function dutyId() {\n return _dutyId;\n },\n dutyNo: function dutyNo() {\n return _dutyNo;\n },\n dutyDay: function dutyDay() {\n return _dutyDay;\n },\n confirmationMsg: function confirmationMsg() {\n return _confirmationMsg;\n },\n requiresInstructorSignature: function requiresInstructorSignature() {\n return _requiresInstructorSignature;\n },\n trainees: function trainees() {\n return scope.trainees;\n },\n submitSession: function submitSession() {\n return SaveSession;\n },\n releaseGrading: function releaseGrading() {\n return _releaseGrading;\n },\n isReleased: function isReleased() {\n return scope.course.ReleasedPhase;\n }\n }\n });\n scope.modalInstance.result.then(function (result) {\n if (result.success) {\n $location.path(\"/\");\n }\n });\n }\n\n function RequiresTraineeSignature() {\n // End of session signature\n var endOfSessionSignature = scope.selectedPhase.DayGrading.TraineeSignature; // End of module signature\n\n var endOfModuleSignature = scope.course.ReleasedPhase && scope.selectedPhase.ReleaseGrading.TraineeSignature;\n return endOfSessionSignature || endOfModuleSignature;\n }\n\n function RequiresInstructorSignature() {\n /* Instructor signature needed if\r\n 1. Syllabus attached needs signature\r\n 2. Completed syllabus items need signature\r\n 3. End of session needs signature\r\n 4. Module is released and end of module needs signature\r\n */\n // 1. Check if syllabus exists and needs signature\n var syllabusSignature = scope.selectedPhase.Syllabus && scope.selectedPhase.Syllabus.SignatureRequired; // 2. Filter selected syllabus items & check if they need signature\n\n var selectedItems = [];\n scope.trainees.forEach(function (trainee) {\n var traineeSelectedItems = trainee.Session.Items.filter(function (x) {\n return x.Selected;\n }).map(function (x) {\n return x.Id;\n });\n selectedItems = selectedItems.concat(traineeSelectedItems);\n });\n selectedItems = _toConsumableArray(new Set(selectedItems));\n var syllabusItemSignature = scope.selectedPhase.Syllabus && scope.selectedPhase.Syllabus.SyllabusItems.filter(function (x) {\n return selectedItems.includes(x.Id);\n }).some(function (x) {\n return x.SignatureRequired;\n }); // 3. End of session signature\n\n var endOfSessionSignature = scope.selectedPhase.DayGrading.InstructorSignature; // 4. End of module signature\n\n var endOfModuleSignature = scope.course.AvailableRelease && scope.course.ReleasedPhase && scope.selectedPhase.ReleaseGrading.InstructorSignature;\n return syllabusSignature || syllabusItemSignature || endOfSessionSignature || endOfModuleSignature;\n }\n /**\r\n * Check if Release requirements are met\r\n * @param {object} group \r\n */\n\n\n function checkReleaseAvailability() {\n //Available Release if No pending mandatory items\n //Calculate item status for each trainee\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (sessionTrainee) {\n if (scope.selectedPhase.Syllabus) {\n var syllabusItems = scope.selectedPhase.Syllabus.SyllabusItems;\n sessionTrainee.Session.Items.forEach(function (sessionItem) {\n var performedTries = sessionItem.Tries.filter(function (x) {\n return x.isReadOnly || x.Selected;\n }).length; // history & current session\n\n var mandatoryCount = syllabusItems.find(function (x) {\n return x.Id == sessionItem.Id;\n }).MandatoryCount;\n sessionItem.Status = mandatoryCount > 0 && performedTries < mandatoryCount ? \"Pending\" : \"Completed\";\n });\n sessionTrainee.AvailableRelease = !sessionTrainee.Session.Items.some(function (x) {\n return x.Status == \"Pending\";\n });\n } else {\n sessionTrainee.AvailableRelease = true;\n }\n });\n\n if (scope.selectedPhase.ModuleType == \"Training\") {\n scope.trainees.filter(function (x) {\n return !x.Session.Absent && !x.AvailableRelease;\n }).forEach(function (trainee) {\n trainee.Session.Released = false;\n });\n\n if (scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.AvailableRelease;\n })) {\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n trainee.Session.Released = false;\n });\n }\n }\n\n scope.course.ReleasedPhase = scope.trainees.filter(function (x) {\n return !x.Absent;\n }).some(function (x) {\n return x.Session.Released;\n });\n return !scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.AvailableRelease;\n });\n }\n\n function SaveSession(password, withRelease) {\n scope.submittedSession.SignaturePassword = password;\n\n if (withRelease) {\n scope.submittedSession.ReleasedPhase = true;\n scope.submittedSession.TraineeSessions.filter(function (x) {\n return !x.Absent;\n }).forEach(function (trainee) {\n trainee.Released = true;\n });\n }\n\n if (isGround) {\n return TrainingSessionFactory.submitSession(scope.submittedSession);\n } else {\n return FlightSessionFactory.submitSession(scope.submittedSession);\n }\n }\n\n function PrepareSessionForSubmission(Trainees) {\n // Filter Trainee Sessions\n var trainees = Trainees.filter(function (x) {\n return x.EligibilityStatus;\n });\n trainees.forEach(function (trainee) {\n trainee.Session.Items = trainee.Session.Items.filter(function (x) {\n return x.Selected;\n }); // Empty absent trainee sessions\n\n if (trainee.Session.Absent) {\n trainee.Session.Items = [];\n trainee.Session.DayGrading.Comments = null;\n trainee.Session.DayGrading.Competences = [];\n trainee.Session.DayGrading.Grade = null;\n trainee.Session.ReleaseGrading.Comments = null;\n trainee.Session.ReleaseGrading.Competences = [];\n trainee.Session.ReleaseGrading.Grade = null;\n }\n });\n var sessionSectors = [];\n\n if (!isGround) {\n //Collect session sectors for flight\n trainingFlightIds.forEach(function (flightId) {\n var sector = {\n FlightId: flightId,\n PM: null,\n PF: null,\n SessionSectorSeats: []\n };\n\n if (scope.course.PilotFunctions) {\n // Set PM/PF values\n var sectors = [];\n scope.course.PilotFunctions.forEach(function (pilot) {\n sectors = sectors.concat(pilot.Sectors.filter(function (x) {\n return x.FlightId == flightId && !x.NonApplicable;\n }));\n });\n var PMsector = sectors.find(function (sec) {\n return sec.isPM;\n });\n var PFsector = sectors.find(function (sec) {\n return !sec.isPM;\n });\n if (PMsector) sector.PM = PMsector.CrewId;\n if (PFsector) sector.PF = PFsector.CrewId; // Set seat values\n\n scope.course.PilotFunctions.forEach(function (pilot) {\n var isInstructor = pilot.IsInstructor;\n var relevantSector = pilot.Sectors.find(function (x) {\n return x.FlightId == flightId && (isInstructor || !x.NonApplicable);\n });\n\n if (relevantSector) {\n var seat = {\n CrewId: relevantSector.CrewId,\n Seat: relevantSector.Seat\n };\n sector.SessionSectorSeats.push(seat);\n }\n });\n }\n\n sessionSectors.push(sector);\n });\n } // Create Session\n\n\n scope.submittedSession = {\n SessionDate: _date,\n CourseId: _courseId,\n GroundDutyIds: isGround ? [_dutyId] : [],\n Sectors: sessionSectors,\n AircraftVisits: scope.course.Media && scope.course.Media.radioModel == \"Aircraft\" ? scope.course.Media.inputAircrafts : [],\n SelectedMedia: scope.course.Media ? scope.course.Media.radioModel : \"\",\n SyntheticDeviceId: scope.course.Media && scope.course.Media.radioModel == \"Simulator\" ? scope.course.Media.selectedDevice.selection : null,\n ReleasedPhase: scope.course.ReleasedPhase,\n GradeType: scope.selectedPhase.DayGrading.GradeType,\n ReleaseGradeType: scope.selectedPhase.ReleaseGrading.GradeType,\n TraineeSessions: trainees.map(function (x) {\n return x.Session;\n }),\n SyllabusVersionId: scope.selectedPhase.Syllabus ? scope.selectedPhase.Syllabus.SyllabusVersionId : null,\n PhaseId: scope.selectedPhase.PhaseId\n };\n }\n\n function isValidForm() {\n /*Requirements before submitting a session\r\n 1. OnLine Mode\r\n 2. Date Allowed\r\n 3. Pending syllabus items\r\n 4. Pending syllabus items for different trainee\r\n 5. Media Validation\r\n 6. Day Grading\r\n 7. Release Grading\r\n 8. Certificate Exam Grading\r\n 9. Trainee Signature\r\n */\n var isValid = false;\n var info = {\n border: \"\",\n icon: \"\",\n msg: \"\",\n scrollToTop: false\n };\n\n if (!window.navigator.onLine) {\n info = {\n border: \"border-left-red\",\n icon: \"fa-warning text-red\",\n msg: \" Online mode is required in order to submit a training.

Check your connection and try again!

\",\n scrollToTop: false\n };\n } else if (!dateAllowed()) {\n info = {\n border: \"border-left-red\",\n icon: \"fa-calendar-times-o text-red\",\n msg: \"You can not submit a session earlier than its duty date!\",\n scrollToTop: false\n };\n } else if (!isSeatValid()) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-plane text-orange\",\n msg: \"You need to select different seats for each pilot!\",\n scrollToTop: true\n };\n } else if (!isPilotFunctionValid()) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-plane text-orange\",\n msg: \" Each sector should have a different PM/PF value for each pilot!\",\n scrollToTop: true\n };\n } else if (syllabusPending()) {\n var traineeDetailsMsg = \"\";\n\n if (scope.selectedTrainee && (scope.selectedPhase.Syllabus.IsGradable || scope.selectedPhase.InFlight)) {\n traineeDetailsMsg = \" for \" + scope.selectedTrainee.Name + \"\";\n }\n\n info = {\n border: \"border-left-orange\",\n icon: \"fa-calendar-times-o text-orange\",\n msg: \"Form cannot be submitted!

Please complete all mandatory syllabus items\" + traineeDetailsMsg + \"

\",\n scrollToTop: false\n };\n } else if (traineesPending()) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-calendar-times-o text-orange\",\n msg: \"Form cannot be submitted!

Please complete all trainee forms.

\",\n scrollToTop: true\n };\n } else if (!isMediaValid()) {\n if (scope.hasNoAircraft) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-plane text-orange\",\n msg: \"You need to provide an aircraft type!\",\n scrollToTop: true\n };\n } else if (scope.hasNoDevice) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-plane text-orange\",\n msg: \"You need to select a synthetic device!\",\n scrollToTop: true\n };\n }\n } else if (!isSyllabusGradingValid()) {\n var invalidTrainees = scope.trainees.filter(function (t) {\n return t.Session.SyllabusValidationErrors && t.Session.SyllabusValidationErrors.Items.length;\n });\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"Some of the selected syllabus items require a grading\",\n SyllabusErrors: invalidTrainees.map(function (t) {\n return t.Session.SyllabusValidationErrors;\n }),\n scrollToTop: false\n };\n } else if (!isGradingValid()) {\n if (!scope.gradingValidationInfo.isDayCompetencesValid || !scope.gradingValidationInfo.isReleaseCompetencesValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to grade all competences before submitting!\",\n scrollToTop: false\n };\n } else if (!scope.gradingValidationInfo.isDayGradingValid || !scope.gradingValidationInfo.isReleaseGradingValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to grade all trainees!\",\n scrollToTop: false\n };\n } else if (!scope.gradingValidationInfo.isCertificateGradingValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to grade all certificate exams!\",\n scrollToTop: false\n };\n }\n } else if (scope.requiresTraineeSignature && !scope.allSignaturesComplete) {\n if (scope.selectedTrainee && !scope.selectedTrainee.Session.Authorized) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-pencil-square-o text-orange\",\n msg: \"\" + scope.selectedTrainee.Name + \" needs to sign the form!\",\n scrollToTop: false\n };\n } else {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"All trainees need to sign their forms!\",\n scrollToTop: true\n };\n }\n } else {\n isValid = true;\n }\n\n scope.info = info;\n return isValid;\n }\n\n function dateAllowed() {\n var dateAllowed = false; //Submission is allowed only on the day of the training and after\n\n var trainingDay = moment.utc(_date).valueOf();\n var today = moment.utc().valueOf();\n\n if (today >= trainingDay) {\n dateAllowed = true;\n }\n\n return dateAllowed;\n }\n\n function isSeatValid() {\n var isValid = true;\n\n if (!isGround) {\n for (var i = 0; i < trainingFlightIds.length; i++) {\n var selectedSeats = [];\n scope.course.PilotFunctions.forEach(function (pilot) {\n selectedSeats = selectedSeats.concat(pilot.Sectors.filter(function (x) {\n return !x.NonApplicable && x.FlightId == trainingFlightIds[i];\n }).map(function (x) {\n return x.Seat;\n }));\n });\n isValid = new Set(selectedSeats).size == selectedSeats.length;\n if (!isValid) break;\n }\n }\n\n return isValid;\n }\n\n function isPilotFunctionValid() {\n var isValid = true;\n\n if (!isGround) {\n for (var i = 0; i < trainingFlightIds.length; i++) {\n var sectors = [];\n scope.course.PilotFunctions.forEach(function (pilot) {\n sectors = sectors.concat(pilot.Sectors.filter(function (x) {\n return !x.NonApplicable && x.FlightId == trainingFlightIds[i];\n }));\n });\n isValid = sectors.filter(function (x) {\n return x.isPM;\n }).length == 1;\n if (!isValid) break;\n }\n }\n\n return isValid;\n }\n\n function syllabusPending() {\n var syllabus = scope.selectedPhase.Syllabus;\n var type = scope.selectedPhase.ModuleType;\n return syllabus && type == 'Check' && (scope.selectedTrainee && !scope.selectedTrainee.AvailableRelease || !scope.selectedTrainee && scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.AvailableRelease;\n }));\n }\n\n function traineesPending() {\n var syllabus = scope.selectedPhase.Syllabus;\n var type = scope.selectedPhase.ModuleType;\n return syllabus && type == 'Check' && scope.selectedTrainee && scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.AvailableRelease;\n });\n }\n\n function isSyllabusGradingValid() {\n var syllabus = scope.selectedPhase.Syllabus;\n\n if (syllabus && syllabus.IsGradable) {\n var gradableSyllabusItems = syllabus.SyllabusItems.filter(function (x) {\n return x.IsGradable;\n });\n var gradableSyllabusItemIds = gradableSyllabusItems.map(function (x) {\n return x.Id;\n }); //foreach trainee get selected tries that need grading\n\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n var invalidItems = [];\n trainee.Session.Items.filter(function (x) {\n return x.Selected && gradableSyllabusItemIds.includes(x.Id);\n }).forEach(function (selectedItem) {\n var syllabusItem = gradableSyllabusItems.find(function (x) {\n return x.Id == selectedItem.Id;\n });\n var gradingType = syllabusItem.GradeType; //Numeric or Outcome or Competences\n\n var traineeSelectedTries = selectedItem.Tries.filter(function (x) {\n return x.Selected;\n });\n traineeSelectedTries.forEach(function (selectedTry) {\n var invalidGrading = gradingType != \"Competences\" && !selectedTry.TryGrading.Grade;\n var invalidCompetences = gradingType == \"Competences\" && !selectedTry.TryGrading.isCompetenceValid;\n\n if (invalidGrading || invalidCompetences) {\n invalidItems.push(syllabusItem.Title);\n }\n });\n });\n trainee.Session.SyllabusValidationErrors = {\n Name: trainee.Name,\n Items: invalidItems\n };\n });\n }\n\n return !scope.trainees.some(function (t) {\n return t.Session.SyllabusValidationErrors && t.Session.SyllabusValidationErrors.Items.length;\n });\n }\n\n function isGradingValid() {\n var isDayGradingValid = scope.selectedPhase.DayGrading.GradeType == \"NotSet\";\n var isReleaseGradingValid = scope.selectedPhase.ReleaseGrading.GradeType == \"NotSet\" || scope.selectedPhase.ReleaseGrading.GradeType == \"CertificateExam\" || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\n var isCertificateGradingValid = scope.selectedPhase.ReleaseGrading.GradeType != \"CertificateExam\" || !scope.course.ReleasedPhase;\n var isDayCompetencesValid = scope.selectedPhase.DayGrading.Competences.length == 0;\n var isReleaseCompetencesValid = scope.selectedPhase.ReleaseGrading.Competences.length == 0 || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\n if (!isDayGradingValid) isDayGradingValid = !scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.Session.DayGrading.isGradeValid;\n });\n if (!isReleaseGradingValid) isReleaseGradingValid = !scope.trainees.filter(function (x) {\n return !x.Session.Absent && x.Session.Released;\n }).some(function (x) {\n return !x.Session.ReleaseGrading.isGradeValid;\n });\n if (!isCertificateGradingValid) isCertificateGradingValid = !scope.trainees.filter(function (x) {\n return !x.Session.Absent && x.AvailableRelease;\n }).some(function (x) {\n return !x.Session.ReleaseGrading.isCertificateValid;\n });\n if (!isDayCompetencesValid) isDayCompetencesValid = !scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.Session.DayGrading.isCompetenceValid;\n });\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !scope.trainees.filter(function (x) {\n return !x.Session.Absent && x.Session.Released;\n }).some(function (x) {\n return !x.Session.ReleaseGrading.isCompetenceValid;\n });\n scope.gradingValidationInfo = {\n isDayGradingValid: isDayGradingValid,\n isReleaseGradingValid: isReleaseGradingValid,\n isDayCompetencesValid: isDayCompetencesValid,\n isReleaseCompetencesValid: isReleaseCompetencesValid,\n isCertificateGradingValid: isCertificateGradingValid\n };\n return isDayGradingValid && isReleaseGradingValid && isDayCompetencesValid && isReleaseCompetencesValid && isCertificateGradingValid;\n }\n\n function isTraineeGradingValid(trainee) {\n var isDayGradingValid = scope.selectedPhase.DayGrading.GradeType == \"NotSet\";\n var isReleaseGradingValid = scope.selectedPhase.ReleaseGrading.GradeType == \"NotSet\" || scope.selectedPhase.ReleaseGrading.GradeType == \"CertificateExam\" || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\n var isCertificateGradingValid = scope.selectedPhase.ReleaseGrading.GradeType != \"CertificateExam\" || !scope.course.ReleasedPhase;\n var isDayCompetencesValid = scope.selectedPhase.DayGrading.Competences.length == 0;\n var isReleaseCompetencesValid = scope.selectedPhase.ReleaseGrading.Competences.length == 0 || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\n if (!isDayGradingValid) isDayGradingValid = trainee.Session.DayGrading.isGradeValid;\n if (!isReleaseGradingValid) isReleaseGradingValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isGradeValid;\n if (!isCertificateGradingValid) isCertificateGradingValid = !trainee.AvailableRelease || trainee.Session.ReleaseGrading.isCertificateValid;\n if (!isDayCompetencesValid) isDayCompetencesValid = trainee.Session.DayGrading.isCompetenceValid;\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isCompetenceValid;\n trainee.Session.gradingValidationInfo = {\n isDayGradingValid: isDayGradingValid,\n isReleaseGradingValid: isReleaseGradingValid,\n isDayCompetencesValid: isDayCompetencesValid,\n isReleaseCompetencesValid: isReleaseCompetencesValid,\n isCertificateGradingValid: isCertificateGradingValid\n };\n return isDayGradingValid && isReleaseGradingValid && isDayCompetencesValid && isReleaseCompetencesValid && isCertificateGradingValid;\n }\n\n function isMediaValid() {\n scope.hasNoAircraft = scope.course.Media && scope.course.Media.radioModel == \"Aircraft\" && !scope.course.Media.inputAircrafts.length;\n scope.hasNoDevice = scope.course.Media && scope.course.Media.radioModel == \"Simulator\" && !scope.course.Media.selectedDevice.selection;\n return !scope.hasNoAircraft && !scope.hasNoDevice;\n }\n /**\r\n * Triggered after a trainee has successfully signed\r\n */\n\n\n function updateTraineeSignatures() {\n updateSession();\n scope.allSignaturesComplete = !scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.Session.Authorized;\n });\n scope.someSignaturesComplete = scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return x.Session.Authorized;\n });\n }\n\n function close() {\n scope.modalInstance.close();\n\n if (scope.info && scope.info.scrollToTop) {\n $window.scrollTo(0, 0);\n }\n }\n\n function showReleasePanel(syllabus) {\n var retVal = false;\n var phase = scope.selectedPhase;\n var availableCourse = scope.availableCourse && scope.trainees.length;\n var isCheck = phase.ModuleType == 'Check';\n var releaseGrading = (phase.ReleaseGrading.Comments || phase.ReleaseGrading.GradeType == 'Numeric' || phase.ReleaseGrading.GradeType == 'Outcome' || phase.ReleaseGrading.Competences.length) && phase.ReleaseGrading.GradeType != 'CertificateExam';\n\n if (isCheck) {\n retVal = availableCourse && releaseGrading;\n } else if (scope.traineeSyllabi.length > 1) {\n var crewId = syllabus.TraineeIds[0];\n var trainee = scope.trainees.find(function (x) {\n return x.CrewId == crewId;\n });\n retVal = scope.reloadRelease && trainee.AvailableRelease && trainee.Session.Released && availableCourse && releaseGrading;\n } else {\n retVal = scope.reloadRelease && scope.course.AvailableRelease && scope.course.ReleasedPhase && availableCourse && releaseGrading;\n }\n\n return retVal;\n }\n\n function releaseTrainee(syllabus) {\n var crewIds = syllabus.TraineeIds;\n var trainees = scope.trainees.filter(function (x) {\n return crewIds.includes(x.CrewId);\n });\n trainees.forEach(function (trainee) {\n trainee.Session.Released = !trainee.Session.Released;\n });\n scope.course.ReleasedPhase = scope.trainees.filter(function (x) {\n return !x.Absent;\n }).some(function (x) {\n return x.Session.Released;\n });\n }\n\n function releaseGroup() {\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n trainee.Session.Released = !trainee.Session.Released;\n });\n scope.course.ReleasedPhase = scope.trainees.filter(function (x) {\n return !x.Absent;\n }).some(function (x) {\n return x.Session.Released;\n });\n setReleaseStatus();\n }\n\n function showReleaseBtn(syllabus) {\n var retVal = false;\n var availableCourse = scope.availableCourse && scope.trainees.length;\n var isCheck = scope.selectedPhase.ModuleType == 'Check';\n\n if (isCheck) {\n retVal = false;\n } else if (scope.traineeSyllabi.length > 1) {\n var crewId = syllabus.TraineeIds[0];\n var trainee = scope.trainees.find(function (x) {\n return x.CrewId == crewId;\n });\n retVal = scope.reloadRelease && availableCourse && trainee.AvailableRelease;\n } else {\n retVal = scope.reloadRelease && availableCourse && scope.course.AvailableRelease;\n }\n\n return retVal;\n }\n\n function showGroupReleaseBtn() {\n var retVal = false;\n var availableCourse = scope.availableCourse && scope.trainees.length > 0;\n var isCheck = scope.selectedPhase.ModuleType == 'Check';\n var releaseGrading = (scope.selectedPhase.ReleaseGrading.Comments || scope.selectedPhase.ReleaseGrading.GradeType == 'Numeric' || scope.selectedPhase.ReleaseGrading.GradeType == 'Outcome' || scope.selectedPhase.ReleaseGrading.Competences.length) && scope.selectedPhase.ReleaseGrading.GradeType != 'CertificateExam';\n\n if (isCheck) {\n retVal = false;\n } else {\n retVal = scope.reloadRelease && availableCourse && releaseGrading && !scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.AvailableRelease;\n });\n }\n\n return retVal;\n }\n\n function getTraineeClass(crewId) {\n isSyllabusGradingValid();\n var textClass = \"\";\n var trainee = scope.trainees.find(function (x) {\n return x.CrewId == crewId;\n });\n var syllabus = scope.selectedPhase.Syllabus;\n var type = scope.selectedPhase.ModuleType;\n var allSyllabusCompleted = trainee.AvailableRelease; //Draft status\n\n var selectedItems = trainee.Session.Items.some(function (i) {\n return i.Tries.filter(function (t) {\n return !t.isReadOnly;\n }).some(function (t) {\n return t.Selected;\n });\n }); //Validate syllabus\n\n var validSyllabusGrading = !trainee.Session.SyllabusValidationErrors || !trainee.Session.SyllabusValidationErrors.Items.length; //Validate Day grading\n\n var isDayGradingValid = scope.selectedPhase.DayGrading.GradeType == \"NotSet\";\n var isDayCompetencesValid = scope.selectedPhase.DayGrading.Competences.length == 0;\n if (!isDayGradingValid) isDayGradingValid = trainee.Session.DayGrading.isGradeValid;\n if (!isDayCompetencesValid) isDayCompetencesValid = trainee.Session.DayGrading.isCompetenceValid; //Validate Release grading\n\n var isReleaseGradingValid = scope.selectedPhase.ReleaseGrading.GradeType == \"NotSet\" || scope.selectedPhase.ReleaseGrading.GradeType == \"CertificateExam\" || scope.selectedPhase.ModuleType == \"Training\" && (!trainee.AvailableRelease || !trainee.Session.Released);\n var isReleaseCompetencesValid = scope.selectedPhase.ReleaseGrading.Competences.length == 0 || scope.selectedPhase.ModuleType == \"Training\" && (!trainee.AvailableRelease || !trainee.Session.Released);\n if (!isReleaseGradingValid) isReleaseGradingValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isGradeValid;\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isCompetenceValid;\n\n if (selectedItems) {\n textClass = \"bg-amber text-white\";\n\n if (validSyllabusGrading && isDayGradingValid && isDayCompetencesValid && isReleaseGradingValid && isReleaseCompetencesValid && (type == 'Training' || allSyllabusCompleted)) {\n textClass = \"bg-green text-white\";\n }\n }\n\n return textClass;\n }\n\n function togglePanel(panelId) {\n $('#' + panelId).toggle();\n }\n /**\r\n * Toggle signature panel while trainee hasn't signed yet\r\n * @param {object} trainee \r\n */\n\n\n function openTraineeSignature(_trainee) {\n //Enter signature mode : trainee form becomes read-only\n if (!_trainee.Session.Authorized) {\n setReleaseStatus(); //Trainee can sign only if his form is valid\n\n if (!validateTraineeForm(_trainee)) {\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgSubmitValidation.html',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'lg'\n });\n } else {\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgTraineeSignature.html',\n controller: 'TraineeSignatureModalCtrl',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n trainee: function trainee() {\n return _trainee;\n },\n signatureSuccess: function signatureSuccess() {\n return updateTraineeSignatures;\n }\n }\n });\n }\n }\n\n scope.someSignaturesComplete = scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return x.Session.Authorized;\n });\n }\n\n function validateTraineeForm(trainee) {\n var trainee = scope.selectedTrainee;\n var isValid = false;\n var info = {\n border: \"\",\n icon: \"\",\n msg: \"\",\n scrollToTop: false\n };\n\n if (!window.navigator.onLine) {\n info = {\n border: \"border-left-red\",\n icon: \"fa-warning text-red\",\n msg: \" Online mode is required in order to sign.

Check your connection and try again!

\",\n scrollToTop: false\n };\n } else if (syllabusPending()) {\n var traineeDetailsMsg = \"\";\n\n if (trainee && (scope.selectedPhase.Syllabus.IsGradable || scope.selectedPhase.InFlight)) {\n traineeDetailsMsg = \" for \" + trainee.Name + \"\";\n }\n\n info = {\n border: \"border-left-orange\",\n icon: \"fa-calendar-times-o text-orange\",\n msg: \"Form cannot be submitted!

Please complete all mandatory syllabus items\" + traineeDetailsMsg + \"

\",\n scrollToTop: false\n };\n } else if (!isSyllabusGradingValid() && trainee.Session.SyllabusValidationErrors && trainee.Session.SyllabusValidationErrors.Items.length) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"Some of the selected syllabus items require a grading\",\n SyllabusErrors: trainee.Session.SyllabusValidationErrors,\n scrollToTop: false\n };\n } else if (!isTraineeGradingValid(trainee)) {\n if (!trainee.Session.gradingValidationInfo.isDayCompetencesValid || !trainee.Session.gradingValidationInfo.isReleaseCompetencesValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to grade all competences!\",\n scrollToTop: false\n };\n } else if (!trainee.Session.isDayGradingValid || !trainee.Session.isReleaseGradingValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to select an overall grade !\",\n scrollToTop: false\n };\n } else if (!trainee.Session.isCertificateGradingValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to grade all certificate exams!\",\n scrollToTop: false\n };\n }\n } else {\n isValid = true;\n }\n\n scope.info = info;\n return isValid;\n }\n\n function resetSignature(_trainee2) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgResetSignature.html',\n controller: 'TraineeSignatureModalCtrl',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n trainee: function trainee() {\n return _trainee2;\n },\n signatureSuccess: function signatureSuccess() {\n return updateTraineeSignatures;\n }\n }\n });\n modalInstance.result.then(function (confirm) {\n if (confirm) {\n _trainee2.Session.Authorized = false;\n scope.trainees.find(function (x) {\n return x.CrewId == _trainee2.CrewId;\n }).Session.Authorized = false;\n updateTraineeSignatures();\n }\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/course.html',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('CourseFactory', CourseFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CourseFactory\r\n * @description \r\n * Add, Update, Delete and Get Training Courses.\r\n * @ngInject\r\n */\n\n function CourseFactory(IndexedDBService, GroundDutyFactory, $http, apiUrl) {\n /**\r\n * Initialize Course\r\n * @memberof CourseFactory\r\n */\n function Course() {\n this.Id = null;\n }\n\n var objType = 'Courses';\n var objCallback = Course;\n var service = {\n setCoursesFromServer: setCoursesFromServer,\n setCoursesToStorage: setCoursesToStorage,\n //save all courses\n addCourseToStorage: addCourseToStorage,\n //update course\n saveOneCourseToStorage: saveOneCourseToStorage,\n //save course\n getCoursesFromStorage: getCoursesFromStorage,\n //get all\n getCourseFromStorage: getCourseFromStorage,\n //getById\n updateCourseInfo: updateCourseInfo,\n updateFlightCourseInfo: updateFlightCourseInfo,\n getCoursesFromStorageByIds: getCoursesFromStorageByIds,\n setCourseOutdated: setCourseOutdated,\n upsertCourse: upsertCourse\n };\n /**\r\n * Get Course By Id\r\n * @memberof CourseFactory\r\n * @param {function} callback \r\n */\n\n function getCourseFromStorage(courseId, callback, errorCallback) {\n IndexedDBService.getById(objType, courseId).then(function (result) {\n callback(result);\n })[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Get Courses\r\n * @memberof CourseFactory\r\n * @param {function} callback \r\n */\n\n function getCoursesFromStorage(callback, errorCallback) {\n IndexedDBService.getAll(objType).then(function (results) {\n callback(results);\n })[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Get Course By Ids\r\n * @memberof CourseFactory\r\n * @param {function} callback \r\n */\n\n function getCoursesFromStorageByIds(courseIds, callback, errorCallback) {\n IndexedDBService.getAll(objType).then(function (results) {\n var selectedResults = [];\n results.forEach(function (result) {\n if (courseIds.includes(result.Id) && selectedResults.filter(function (x) {\n return x.Id == result.Id;\n }).length == 0) {\n selectedResults.push(result);\n }\n });\n callback(selectedResults);\n })[\"catch\"](errorCallback);\n }\n\n ;\n\n function updateCourseInfo(courseId, dutyId, callback, errorOnSaveCallback, errorOnNetwork) {\n var traingingApiURL = apiUrl + '/Training?courseId=' + courseId + '&dutyId=' + dutyId;\n $http.get(traingingApiURL, {\n 'Content-Type': 'application/json'\n }).then(function (data) {\n var course = data.data;\n course.FetchedTime = moment.utc().toJSON();\n var duty = GroundDutyFactory.getGroundDutyFromStorage(dutyId);\n course.FetchedDutyCodes = duty.RelatedGroundDuties.filter(function (x) {\n return !x.IsInstructor;\n }).map(function (x) {\n return String(x.GroundDutyNo);\n });\n course.LastFetchedDutyId = dutyId; //Upsert course in IndexDB \n\n upsertCourse(course, function (course) {\n callback(course);\n }, errorOnSaveCallback);\n })[\"catch\"](errorOnNetwork);\n }\n\n function updateFlightCourseInfo(crewRouteCourse, date, dutyNo, dutyDay, callback, errorOnSaveCallback, errorOnNetwork) {\n var traingingApiURL = apiUrl + '/Training/GetCrewRouteTraining';\n $http.post(traingingApiURL, crewRouteCourse, {\n 'Content-Type': 'application/json'\n }).then(function (data) {\n var course = data.data;\n course.FetchedTime = moment.utc().toJSON();\n course.FetchedCrewRoute = {\n date: date,\n dutyNo: dutyNo,\n dutyDay: dutyDay\n }; //Upsert course in IndexDB \n\n upsertCourse(course, function (course) {\n callback(course);\n }, errorOnSaveCallback);\n })[\"catch\"](errorOnNetwork);\n }\n\n function upsertCourse(course, callback, errorOnSaveCallback) {\n getCourseFromStorage(course.Id, function (localCourse) {\n if (localCourse) {\n saveOneCourseToStorage(course);\n } else {\n addCourseToStorage(course);\n }\n\n callback(course);\n }, errorOnSaveCallback);\n }\n\n function setCourseOutdated(courseId, callback, errorCallback) {\n getCourseFromStorage(courseId, function (localCourse) {\n if (localCourse) {\n localCourse.NeedsRefresh = true;\n saveOneCourseToStorage(localCourse);\n }\n\n if (callback) {\n callback();\n }\n }, errorCallback);\n }\n /**\r\n * Set Courses from server API \r\n * @memberof CourseFactory\r\n * @param {array} courses Courses Object\r\n * @param {array} courseIdsToSend Current courses of the storage\r\n * @param {string} lastSyncDate Last Sync Date \r\n */\n\n\n function setCoursesFromServer(courses, callback, errorCallback) {\n getCoursesFromStorage(function (localCourses) {\n // No courses found - Save All Incoming\n if (!localCourses || localCourses.length == 0) {\n setCoursesToStorage(courses);\n } else {\n for (var j = 0; j < courses.length; j++) {\n var IsCourseIncluded = false;\n\n for (var h = 0; h < localCourses.length; h++) {\n if (courses[j].Id == localCourses[h].Id) {\n IsCourseIncluded = true;\n break;\n }\n } //Update existing course\n\n\n if (IsCourseIncluded) {\n localCourses[h].Title = courses[j].Title; //Update title from sync\n\n saveOneCourseToStorage(localCourses[h]);\n } //Add a new Course\n else {\n addCourseToStorage(courses[j]);\n }\n }\n\n localCourses.filter(function (x) {\n return !courses.some(function (z) {\n return z.Id == x.Id;\n });\n }).forEach(function (course) {\n IndexedDBService.remove(objType, course.Id);\n });\n }\n });\n }\n /**\r\n * Set Courses\r\n * @memberof CourseFactory\r\n * @param {array} Courses A list of courses to set to indexedDB\r\n */\n\n\n function setCoursesToStorage(Courses, callback, errorCallback) {\n IndexedDBService.addAll(objType, Courses).then(callback)[\"catch\"](errorCallback);\n ;\n }\n\n ;\n /**\r\n * Add Course to Storage\r\n * @memberof CourseFactory\r\n * @param {object} Course\r\n */\n\n function addCourseToStorage(Course, callback, errorCallback) {\n IndexedDBService.add(objType, Course).then(callback)[\"catch\"](errorCallback);\n ;\n }\n\n ;\n /**\r\n * Update Course to Storage\r\n * @memberof CourseFactory\r\n * @param {object} Course\r\n */\n\n function saveOneCourseToStorage(Course, callback, errorCallback) {\n IndexedDBService.put(objType, Course).then(callback)[\"catch\"](errorCallback);\n }\n\n ;\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('FlightCourseCtrl', FlightCourseCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightCourseCtrl\r\n * @description \r\n *\r\n * @ngInject\r\n */\n\n function FlightCourseCtrl($route, $filter, $timeout, FlightSessionFactory, CrewRouteFactory, FlightFactory, GroundDutyFactory, CourseFactory, $scope, $location, $routeParams) {\n $scope.gotoCourse = gotoCourse;\n $scope.gotoCrewRoute = gotoCrewRoute;\n $scope.gotoFlight = gotoFlight;\n $scope.stickySelectedTrainee = stickySelectedTrainee;\n $scope.toggleView = toggleView;\n $scope.refreshCourse = refresh;\n $scope.courseTrainees = [];\n var courseId = Number($routeParams.courseId);\n var dutyNo = Number($routeParams.dutyNo);\n var dutyDay = Number($routeParams.dutyDay);\n $scope.viewFromFlight = Number($routeParams.flightId);\n var crewRouteDuty = CrewRouteFactory.getCrewRouteFromStorage(dutyNo, dutyDay);\n var date = $routeParams.date;\n crewRouteDuty.date = date;\n var crewRouteCourse = crewRouteDuty.Courses.find(function (x) {\n return x.CourseId == courseId && new moment(x.Date).isSame(date);\n });\n $scope.isEdit = false;\n $scope.loading = false;\n $scope.refreshSuccess = true; //show refresh icon\n\n if (!crewRouteDuty) {\n // go to dashboard if no groundDuty\n $location.path(\"/\");\n } else {\n $scope.flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay); //Get Crew Route's course\n\n CourseFactory.getCourseFromStorage(courseId, function (savedCourse) {\n var dutyCourse = savedCourse;\n $scope.dutyCourse = dutyCourse;\n initCourse(false);\n });\n $scope.crewRouteDuty = crewRouteDuty;\n }\n\n function gotoFlight() {\n var flightId = Number($routeParams.flightId);\n $location.path('/flightinfo/' + flightId);\n }\n\n function initCourse(afterRefresh) {\n var courseId = $scope.dutyCourse.Id;\n FlightSessionFactory.getSession(courseId, date, dutyNo, dutyDay, crewRouteCourse.TrainingFlightIds, afterRefresh, function (course) {\n if (course && !course.HasLimitedInfo) {\n $scope.availableCourse = true;\n $scope.selectedPhase = course.selectedPhase;\n $scope.trainees = course.CourseTrainees;\n course.SequenceWarning = false;\n }\n\n $scope.course = course;\n manageCourseStatus($scope.dutyCourse, course, afterRefresh);\n toggleView('History'); //default\n\n if ($scope.trainees) {\n stickySelectedTrainee(); //Check for status change (new trainees found on a submitted session (reset) || failed certificate trainees want to retake the test)\n\n if (afterRefresh && $scope.isCourseComplete && $scope.trainees.length) {\n CrewRouteFactory.setCoursePending(dutyNo, dutyDay, courseId, date);\n $scope.isCourseComplete = false;\n $route.reload();\n }\n }\n\n $scope.reload = false;\n $timeout(function () {\n $scope.reload = true;\n }, 100);\n });\n }\n\n function gotoCourse(course) {\n $location.path('/course/' + course.Id + '/' + groundDuty.DutyDateS + \"/\" + groundDuty.Id);\n }\n\n function gotoCrewRoute() {\n $location.path('/crewRoute/' + dutyNo + '/' + dutyDay);\n }\n\n function refresh() {\n $scope.loading = true;\n\n if ($scope.isOffline) {\n $timeout(function () {\n $scope.loading = false;\n }, 100);\n $scope.refreshSuccess = false;\n $scope.availableCourseInfo = false;\n $scope.refreshErrorMsg = \"Online mode is required in order to get course. Please connect to the internet and try again.\";\n } else {\n CourseFactory.updateFlightCourseInfo(crewRouteCourse, date, dutyNo, dutyDay, function () {\n $scope.loading = false;\n $scope.refreshSuccess = true;\n $scope.availableCourseInfo = true;\n initCourse(true);\n $scope.reload = false;\n $timeout(function () {\n $scope.reload = true;\n }, 100);\n }, function () {\n $scope.loading = false;\n $scope.refreshSuccess = false;\n $scope.availableCourseInfo = false;\n $scope.refreshErrorMsg = \"Something went wrong! Please Try again.\";\n }, function (error) {\n console.log(error);\n $scope.loading = false;\n $scope.refreshSuccess = false;\n $scope.availableCourseInfo = false;\n $scope.refreshErrorMsg = \"Oops! Something went wrong!\";\n\n if (error.data.errorMessage) {\n $scope.refreshErrorMsg = error.data.errorMessage;\n }\n });\n }\n }\n\n function manageCourseStatus(dutyCourse, course, afterRefresh) {\n // COMPLETED : has been submitted\n var isCourseComplete = crewRouteCourse.Status == \"Completed\"; // NEEDS SUBMIT : 1 hour has passed since the end of the course\n\n var now = moment.utc();\n\n if (!dutyCourse.IsCompleted) {\n var needsSubmit = false;\n var fetched = moment.utc(crewRouteDuty.DutyEnd);\n var duration = moment.duration(now.diff(fetched)).asHours();\n\n if (duration > 1) {\n needsSubmit = true;\n }\n } // LIMITED : no info available\n\n\n var isCourseLimited = !course || course.HasLimitedInfo || course.HasLimitedSession && !afterRefresh; // OUTDATED : NeedsRefresh || 18 hours since last refresh\n\n var isCourseOutdated = false;\n\n if (course && course.FetchedTime) {\n var now = moment.utc();\n var fetched = moment.utc(course.FetchedTime);\n var duration = moment.duration(now.diff(fetched)).asHours();\n\n if (duration > 18 || course.NeedsRefresh) {\n isCourseOutdated = true;\n }\n }\n\n $scope.headerMsg = \"Refresh Course\";\n if (isCourseLimited) $scope.headerMsg = \"Fetch Course\";\n $scope.hasPendingTraining = !isCourseComplete;\n $scope.hasUnsetTraining = needsSubmit;\n $scope.isCourseLimited = isCourseLimited;\n $scope.isCourseComplete = isCourseComplete;\n $scope.isCourseOutdated = isCourseOutdated;\n $scope.hasNotifications = isCourseLimited || isCourseOutdated || isCourseComplete;\n }\n\n function stickySelectedTrainee() {\n if ($scope.trainees && $scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).length) {\n if ($scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).find(function (x) {\n return x.Session.selected;\n })) {\n $scope.selectedTrainee = $scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).find(function (x) {\n return x.Session.selected;\n });\n } else {\n $scope.selectedTrainee = $scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n })[0];\n }\n } else {\n $scope.selectedTrainee = null;\n }\n\n if ($scope.selectedTrainee) $scope.selectedTraineeBadge = {\n CrewId: $scope.selectedTrainee.CrewId\n };\n }\n\n function toggleView(mode) {\n $scope.viewMode = mode;\n }\n }\n})();\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('FlightSessionFactory', FlightSessionFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightSessionFactory\r\n * @description \r\n * Add, Update, Delete and Flight Sessions.\r\n * @ngInject\r\n */\n\n function FlightSessionFactory(IndexedDBService, CrewRouteFactory, FlightFactory, CourseFactory, $http, apiUrl, $filter) {\n /**\r\n * Initialize Session\r\n * @memberof FlightSessionFactory\r\n */\n function Session() {\n this.Id = null;\n }\n\n var objType = 'FlightSessions';\n var objCallback = Session;\n var service = {\n getAll: getAll,\n getSession: getSession,\n setSession: setSession,\n updateSession: updateSession,\n getSessionTrainees: getSessionTrainees,\n submitSession: submitSession,\n remove: remove,\n getCrewRouteFlightTrainees: getCrewRouteFlightTrainees,\n applyTraineeInfoToSession: applyTraineeInfoToSession\n };\n /**\r\n * Get all flight training sessions\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\n\n function getAll(callback) {\n IndexedDBService.getAll(objType).then(function (results) {\n callback(results);\n });\n }\n\n ;\n /**\r\n * Get session By day and courseId\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\n\n function getSession(courseId, day, dutyNo, dutyDay, trainingFlightIds, afterRefresh, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay]).then(function (session) {\n CourseFactory.getCourseFromStorage(courseId, function (course) {\n if (course && !course.HasLimitedInfo && course.CrewCoursePhases && course.CourseTrainees) {\n mergeCourseWithSession(course, session, dutyNo, dutyDay, trainingFlightIds, afterRefresh);\n }\n\n callback(course);\n }, errorCallback);\n })[\"catch\"](errorCallback);\n }\n /**\r\n * Remove session By day, dutyNo, dutyDay and courseId\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\n\n\n function remove(courseId, day, dutyNo, dutyDay, callback, errorCallback) {\n IndexedDBService.remove(objType, [day, courseId, dutyNo, dutyDay]).then(callback)[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Get session Trainees By day and courseId\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\n\n function getSessionTrainees(courseId, day, dutyNo, dutyDay, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay]).then(function (session) {\n var trainees = session && session.trainees ? session.trainees : [];\n callback(trainees);\n })[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Set session\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\n\n function setSession(session, callback, errorCallback) {\n IndexedDBService.getById(objType, [session.day, session.courseId, session.dutyNo, session.dutyDay]).then(function (result) {\n if (result) {\n saveSessionToStorage(session).then(callback)[\"catch\"](errorCallback);\n ;\n } else {\n addSessionToStorage(session).then(callback)[\"catch\"](errorCallback);\n }\n })[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Set session\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\n\n function updateSession(trainees, session, courseId, day, dutyNo, dutyDay, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay]).then(function (localSession) {\n var isNewSession = false;\n\n if (!localSession) {\n localSession = {\n courseId: courseId,\n day: day,\n dutyNo: dutyNo,\n dutyDay: dutyDay,\n trainees: []\n };\n isNewSession = true;\n } else {\n localSession.trainees = [];\n }\n\n if (session) {\n localSession.Media = session.Media;\n localSession.ReleasedPhase = session.ReleasedPhase;\n localSession.PilotFunctions = session.PilotFunctions;\n localSession.TraineeEligibilty = session.TraineeEligibilty;\n }\n\n trainees.forEach(function (trainee) {\n localSession.trainees.push(trainee);\n });\n\n if (isNewSession) {\n addSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n } else {\n saveSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n }\n })[\"catch\"](errorCallback);\n }\n\n function mergeCourseWithSession(course, session, dutyNo, dutyDay, trainingFlightIds, afterRefresh) {\n course.HasLimitedSession = session == undefined;\n var hasPreviousSessions = mergeSyllabusWithHistory(course.CourseTrainees, course.CrewCoursePhases);\n filterTraineesByEligibility(dutyNo, dutyDay, course, trainingFlightIds, session, afterRefresh);\n course.CrewCoursePhases.forEach(function (phase) {\n calculatePhaseStatus(phase, course);\n });\n course.selectedPhase = getSelectedPhase(course); // Calculate eligible trainees phase status\n\n course.CourseTrainees.forEach(function (trainee) {\n var traineePhase = trainee.Phases.find(function (x) {\n return x.PhaseId == course.selectedPhase.PhaseId;\n });\n\n if (traineePhase) {\n trainee.ActivePhaseStatus = traineePhase.PhaseStatus;\n } else {\n trainee.ActivePhaseStatus = \"Pending\";\n }\n\n trainee.Selectable = trainee.ActivePhaseStatus == \"InProgress\";\n }); // Non InProgress trainees will be marked as NonEligible (remove further ahead trainees on multiple InProgress phases)\n\n course.CourseTrainees.filter(function (x) {\n return !x.Selectable;\n }).forEach(function (invalidPhaseTrainee) {\n invalidPhaseTrainee.EligibilityStatus = false;\n invalidPhaseTrainee.EligibilityDesc = \"AlreadySubmitted\";\n course.NonEligibleTrainees.push(invalidPhaseTrainee);\n });\n course.CourseTrainees = course.CourseTrainees.filter(function (x) {\n return x.EligibilityStatus;\n }); // Get trainee sessions\n\n course.CourseTrainees.forEach(function (trainee) {\n var sessionTrainee = session ? session.trainees.find(function (x) {\n return x.CrewId == trainee.CrewId;\n }) : null;\n\n if (sessionTrainee) {\n trainee.Session = sessionTrainee.Session;\n } else {\n trainee.Session = {\n Released: course.selectedPhase.ModuleType == \"Training\" ? false : true,\n CrewId: trainee.CrewId,\n Items: [],\n Absent: false,\n DayGrading: {\n Comments: null,\n Grade: null,\n Competences: []\n },\n ReleaseGrading: {\n Comments: null,\n Grade: null,\n Competences: []\n }\n };\n }\n });\n /* Set default values for release option\r\n Training Modules: 'No' release as default\r\n Check Module: 'Yes' release as default\r\n */\n\n course.ReleasedPhase = course.selectedPhase.ModuleType == \"Training\" ? false : true;\n\n if (session) {\n course.Media = session.Media;\n course.ReleasedPhase = session.ReleasedPhase;\n course.PilotFunctions = session.PilotFunctions;\n course.TraineeEligibilty = session.TraineeEligibilty;\n }\n }\n\n function getSelectedPhase(course) {\n var hasSelectedPhase = false;\n var phases = course.CrewCoursePhases;\n phases.forEach(function (phase, index, array) {\n phase.isFirst = index == 0;\n phase.isLast = index + 1 == array.length; // Select the first InProgress & selected phase\n\n if (!hasSelectedPhase && phase.Status == \"InProgress\" && phase.isSelected) {\n phase.Selected = true;\n hasSelectedPhase = true;\n }\n }); // Select the first InProgress phase\n\n if (!hasSelectedPhase && phases.some(function (x) {\n return x.Status == \"InProgress\";\n })) {\n phases.find(function (x) {\n return x.Status == \"InProgress\";\n }).Selected = true;\n hasSelectedPhase = true;\n }\n\n if (!hasSelectedPhase) {\n phases.find(function (x) {\n return x.isFirst;\n }).Selected = true;\n }\n\n var selectedPhase = phases.find(function (x) {\n return x.Selected;\n });\n return selectedPhase;\n }\n\n function filterTraineesByEligibility(dutyNo, dutyDay, course, trainingFlightIds, session, afterRefresh) {\n var _course$CourseTrainee;\n\n // Trainee Eligiblity cases\n // 1. After refresh - Save newly fetched eligibility in session\n // 2. No refresh & Session exists - Get last fetched eligibility from session\n // 3. No refresh & No session exists - Rely on previously fetched eligibility (different duty - same course)\n var traineeEligibility = course.TraineeEligibilty;\n\n if (!afterRefresh && session && session.TraineeEligibilty) {\n traineeEligibility = session.TraineeEligibilty;\n }\n\n if (session) session.TraineeEligibilty = traineeEligibility; //update session eligibility\n // Get crew route trainees without any training records\n\n var trainees = getCrewRouteFlightTrainees(dutyNo, dutyDay, trainingFlightIds);\n var inactiveTrainees = trainees.filter(function (x) {\n return !course.CourseTrainees.some(function (z) {\n return z.CrewId == x.CrewId;\n });\n }); //Exclude Non valid trainees\n\n var eligibleTraineeIds = Object.keys(traineeEligibility).filter(function (x) {\n return traineeEligibility[x] == \"NotStarted\" || traineeEligibility[x] == \"ValidPhase\" || traineeEligibility[x] == \"FailedCertificate\";\n }).map(Number);\n var eligibleTrainees = inactiveTrainees.filter(function (x) {\n return eligibleTraineeIds.includes(x.CrewId);\n });\n eligibleTrainees.forEach(function (trainee) {\n trainee.EligibilityStatus = true;\n });\n createNewPhaseTrainees(dutyNo, dutyDay, trainingFlightIds, course, eligibleTrainees); // Merge eligibleTrainees (inactive) with CourseTrainees (eligible & active)\n\n course.CourseTrainees.forEach(function (trainee) {\n trainee.EligibilityStatus = true;\n });\n\n (_course$CourseTrainee = course.CourseTrainees).push.apply(_course$CourseTrainee, _toConsumableArray(eligibleTrainees)); // Non eligible trainees\n\n\n var nonEligibleTrainees = inactiveTrainees.filter(function (x) {\n return !eligibleTraineeIds.includes(x.CrewId);\n });\n course.NonEligibleTrainees = nonEligibleTrainees;\n nonEligibleTrainees.forEach(function (trainee) {\n trainee.EligibilityStatus = false;\n trainee.EligibilityDesc = traineeEligibility[trainee.CrewId];\n }); // Result:\n // CourseTrainees = eligible trainees (active or new)\n // Non EligibleTrainees\n }\n /**\r\n * Create first phase foreach trainee\r\n * @param {object} groundDuty\r\n * @param {object} course\r\n * @param {array} trainees Eligible trainees that haven't yet started training\r\n */\n\n\n function createNewPhaseTrainees(dutyNo, dutyDay, trainingFlightIds, course, trainees) {\n var flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay).filter(function (f) {\n return trainingFlightIds.some(function (z) {\n return z == f.FlightId;\n });\n }); //Match TrainingIndicators with PhaseDutyNos\n\n var crewCoursePhaseDutyNos = [];\n var crewrouteTrainingIndicators = [];\n course.CrewCoursePhases.forEach(function (coursePhase) {\n crewCoursePhaseDutyNos = crewCoursePhaseDutyNos.concat(coursePhase.FlightTrainingIndicators);\n });\n flights.forEach(function (flight) {\n crewrouteTrainingIndicators.push(flight.TrainingIndicatorId.toString());\n });\n var relatedDutyNos = crewCoursePhaseDutyNos.filter(function (x) {\n return crewrouteTrainingIndicators.includes(x);\n });\n var relatedPhases = course.CrewCoursePhases.filter(function (x) {\n return x.FlightTrainingIndicators.some(function (fti) {\n return relatedDutyNos.includes(fti);\n });\n }); //From related phases, select first in order\n\n relatedPhases = $filter('orderBy')(relatedPhases, 'OrderNo');\n var firstPhase = relatedPhases[0];\n trainees.forEach(function (trainee) {\n trainee.Phases = [{\n PhaseId: firstPhase.PhaseId,\n PhaseStatus: \"InProgress\",\n RepeatRequestedItems: [],\n isSelected: true //selectedPhase\n\n }];\n });\n }\n\n function getCrewRouteFlightTrainees(dutyNo, dutyDay, trainingFlightIds) {\n var flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay).filter(function (f) {\n return trainingFlightIds.some(function (z) {\n return z == f.FlightId;\n });\n });\n var trainees = [];\n flights.forEach(function (flight) {\n flight.crew.filter(function (x) {\n return x.IsTrainee && !x.isDHC;\n }).forEach(function (trainee) {\n if (!trainees.some(function (x) {\n return x.id == trainee.id;\n })) {\n //do not push duplicates : trainees that are in multiple flights\n trainees.push(trainee);\n }\n });\n });\n trainees.forEach(function (trainee) {\n trainee.CrewId = trainee.id;\n trainee.Id = trainee.id;\n trainee.Name = trainee.name;\n trainee.AimsId = trainee.aimsId;\n });\n return trainees;\n }\n\n function calculatePhaseStatus(phase, course) {\n course.CourseTrainees.forEach(function (trainee) {\n var traineePhase = trainee.Phases.find(function (x) {\n return x.PhaseId == phase.PhaseId;\n });\n\n if (traineePhase && traineePhase.PhaseStatus == \"InProgress\") {\n phase.Status = \"InProgress\";\n } else if (!traineePhase && phase.Status != \"InProgress\") {\n phase.Status = \"Pending\";\n } else if (traineePhase && traineePhase.PhaseStatus == \"Completed\" && phase.Status != \"InProgress\") {\n phase.Status = \"Completed\";\n } //Selected phase, If at least one trainee has it selected\n\n\n if (traineePhase && !phase.isSelected) {\n phase.isSelected = traineePhase.isSelected;\n }\n });\n }\n\n function mergeSyllabusWithHistory(trainees, phases) {\n var flatSullabusItems = [];\n trainees.forEach(function (trainee) {\n trainee.Phases.forEach(function (phase) {\n phase.Sessions.forEach(function (session) {\n session.Items.forEach(function (item) {\n var flatItem = createFlatHistorySullabusItem(trainee, phase, session, item);\n flatSullabusItems.push(flatItem);\n });\n });\n });\n });\n phases.filter(function (x) {\n return x.Syllabus;\n }).forEach(function (phase, index, array) {\n phase.Syllabus.SyllabusItems.forEach(function (syllabusItem) {\n syllabusItem.History = flatSullabusItems.filter(function (item) {\n return item.ItemId == syllabusItem.Id;\n });\n });\n });\n var hasPreviousSessions = flatSullabusItems.length > 0;\n return hasPreviousSessions;\n }\n\n function createFlatHistorySullabusItem(trainee, phase, session, item) {\n var flatItem = {\n CrewId: trainee.CrewId,\n PhaseId: phase.PhaseId,\n SessionId: session.SessionId,\n SessionComments: session.SessionComments,\n SubmissionDate: item.SubmissionDate,\n RepeatRequired: item.RepeatRequired,\n Tries: item.Tries,\n ItemId: item.SyllabusItemId,\n Grade: session.Grade,\n GradeType: session.GradeType,\n InstructorName: session.InstructorName,\n InstructorAimsId: session.InstructorAimsId\n };\n return flatItem;\n }\n /**\r\n * Add Session to Storage\r\n * @memberof FlightSessionFactory\r\n * @param {object} Session\r\n */\n\n\n function addSessionToStorage(session) {\n return IndexedDBService.add(objType, session);\n }\n\n ;\n /**\r\n * Update Session to Storage\r\n * @memberof FlightSessionFactory\r\n * @param {object} Session\r\n */\n\n function saveSessionToStorage(session) {\n return IndexedDBService.put(objType, session);\n }\n\n ;\n\n function submitSession(submittedSession, callback) {\n var traingingApiURL = apiUrl + '/Training/SubmitTraining';\n return $http.post(traingingApiURL, submittedSession, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n\n function applyTraineeInfoToSession(course, courseId, day, dutyNo, dutyDay, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay]).then(function (localSession) {\n var isNewSession = false;\n\n if (!localSession) {\n localSession = {\n courseId: courseId,\n day: day,\n dutyNo: dutyNo,\n dutyDay: dutyDay,\n trainees: [],\n TraineeEligibilty: course.TraineeEligibilty,\n CourseTrainees: course.CourseTrainees\n };\n isNewSession = true;\n } else {\n localSession.CourseTrainees = course.CourseTrainees;\n localSession.TraineeEligibilty = course.TraineeEligibilty;\n }\n\n if (isNewSession) {\n addSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n } else {\n saveSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n }\n })[\"catch\"](errorCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('grading', grading);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name grading\r\n * @restrict E\r\n * @description\r\n * Implementation of overall grading\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function grading() {\n function link(scope, element, attrs) {\n scope.getRemainingCharacters = getRemainingCharacters;\n scope.validateGrading = validateGrading;\n scope.filterValidTrainees = filterValidTrainees;\n scope.filterTrainee = filterTrainee;\n scope.saveComment = saveComment;\n scope.isDayGrading = scope.type == \"day\";\n scope.hasCertificateExam = scope.type == \"certificate\";\n scope.isCheck = scope.phase == \"Check\"; //Separate DayGrading and ReleaseGrading \n\n scope.sessions = [];\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n var session = scope.isDayGrading ? trainee.Session.DayGrading : trainee.Session.ReleaseGrading;\n session.Name = trainee.Name;\n session.AimsId = trainee.AimsId;\n session.CrewId = trainee.CrewId;\n\n if (scope.isDayGrading || !scope.isDayGrading && !scope.isCheck && trainee.AvailableRelease || !scope.isDayGrading && scope.isCheck) {\n scope.sessions.push(session);\n }\n });\n scope.sessions.forEach(function (traineeSession) {\n validateGrading(traineeSession);\n });\n filterValidTrainees();\n /**\r\n * Calculate remaining characters for comment input\r\n * @param {string} text \r\n * @param {number} max \r\n */\n\n function getRemainingCharacters(text, max) {\n if (typeof text === \"undefined\" || text === null) return '';\n if (typeof max === \"undefined\" || max === null || max < 0 || !max) max = 4000;\n var length = text.length;\n return 'characters left: ' + (max - length);\n }\n\n function validateGrading(trainee) {\n trainee.isGradeValid = trainee.Grade != null && trainee.Grade != undefined;\n }\n\n function filterValidTrainees() {\n scope.sessions.forEach(function (traineeSession) {\n traineeSession.isValid = traineeSession.isGradeValid && (!scope.settings.Competences.length || traineeSession.isCompetenceValid);\n });\n }\n\n function filterTrainee() {\n return function (trainee) {\n var showTrainee = true;\n\n if (scope.selected) {\n //individual grading view: filter selected\n showTrainee = scope.selected.CrewId == trainee.CrewId;\n }\n\n return showTrainee;\n };\n }\n\n function saveComment() {\n scope.commentInput();\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/grading.tpl.html',\n scope: {\n trainees: \"=\",\n settings: \"=\",\n type: \"@\",\n phase: \"=\",\n selected: \"=\",\n commentInput: \"&onCommentInput\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('GroundCourseCtrl', GroundCourseCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name GroundCourseCtrl\r\n * @description \r\n *\r\n * @ngInject\r\n */\n\n function GroundCourseCtrl($route, $filter, $timeout, TrainingSessionFactory, CrewRouteFactory, FlightFactory, GroundDutyFactory, CourseFactory, $scope, $location, $routeParams) {\n $scope.gotoCourse = gotoCourse;\n $scope.gotoGroundDuty = gotoGroundDuty;\n $scope.stickySelectedTrainee = stickySelectedTrainee;\n $scope.toggleView = toggleView;\n $scope.refreshCourse = refresh;\n $scope.courseTrainees = [];\n var courseId = Number($routeParams.courseId);\n var groundDutyId = Number($routeParams.dutyId);\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(groundDutyId);\n $scope.isEdit = false;\n $scope.loading = false;\n $scope.allAbsent = false;\n $scope.refreshSuccess = true; //show refresh icon\n\n if (!groundDuty) {\n // go to dashboard if no groundDuty\n $location.path(\"/\");\n } else {\n var date = groundDuty.DutyDateS;\n\n if (groundDuty.RelatedGroundDuties) {\n var courses = GroundDutyFactory.getGroundDutyActiveCourses(groundDutyId);\n\n if (courses.length) {\n CourseFactory.getCourseFromStorage(courseId, function (dutyCourse) {\n $scope.dutyCourse = dutyCourse;\n initCourse(false);\n });\n }\n }\n\n $scope.groundDuty = groundDuty;\n $scope.groundDutyId = groundDutyId;\n }\n\n function initCourse(afterRefresh) {\n var courseId = $scope.dutyCourse.Id;\n TrainingSessionFactory.getSession(courseId, date, groundDutyId, afterRefresh, function (course) {\n if (course && !course.HasLimitedInfo) {\n $scope.availableCourse = true;\n $scope.selectedPhase = course.selectedPhase;\n $scope.trainees = course.CourseTrainees;\n course.SequenceWarning = false;\n }\n\n $scope.course = course;\n manageCourseStatus($scope.dutyCourse, course, afterRefresh);\n toggleView('History'); //default\n\n if ($scope.trainees) {\n applyAttendanceFromGroundDuty(groundDuty, $scope.trainees);\n stickySelectedTrainee();\n\n if ($scope.trainees.length && !$scope.trainees.some(function (x) {\n return !x.Session.Absent;\n })) {\n $scope.allAbsent = true;\n } //Check for status change (new trainees found on a submitted session (reset) || failed certificate trainees want to retake the test)\n\n\n if (afterRefresh && $scope.isCourseComplete && $scope.trainees.length) {\n GroundDutyFactory.setCoursePending(groundDutyId, courseId);\n $scope.isCourseComplete = false;\n $route.reload();\n }\n }\n\n $scope.reload = false;\n $timeout(function () {\n $scope.reload = true;\n }, 100);\n });\n }\n\n function applyAttendanceFromGroundDuty(groundDuty, trainees) {\n groundDuty.Trainees.forEach(function (related) {\n related.CrewMembers.forEach(function (crew) {\n var trainee = trainees.find(function (x) {\n return x.CrewId == crew.Id;\n });\n\n if (trainee) {\n trainee.Session.Absent = crew.Absent;\n }\n });\n });\n }\n\n function gotoCourse(course) {\n $location.path('/course/' + course.Id + '/' + groundDuty.DutyDateS + \"/\" + groundDuty.Id);\n }\n\n function refresh() {\n $scope.loading = true;\n\n if ($scope.isOffline) {\n $timeout(function () {\n $scope.loading = false;\n }, 100);\n $scope.refreshSuccess = false;\n $scope.availableCourseInfo = false;\n $scope.refreshErrorMsg = \"Online mode is required in order to get course. Please connect to the internet and try again.\";\n } else {\n CourseFactory.updateCourseInfo($scope.dutyCourse.Id, groundDutyId, function () {\n $scope.loading = false;\n $scope.refreshSuccess = true;\n $scope.availableCourseInfo = true;\n initCourse(true);\n $scope.reload = false;\n $timeout(function () {\n $scope.reload = true;\n }, 100);\n }, function () {\n $scope.loading = false;\n $scope.refreshSuccess = false;\n $scope.availableCourseInfo = false;\n $scope.refreshErrorMsg = \"Something went wrong! Please Try again.\";\n }, function (error) {\n console.log(error);\n $scope.loading = false;\n $scope.refreshSuccess = false;\n $scope.availableCourseInfo = false;\n $scope.refreshErrorMsg = \"Oops! Something went wrong!\";\n\n if (error.data.errorMessage) {\n $scope.refreshErrorMsg = error.data.errorMessage;\n }\n });\n }\n }\n\n function manageCourseStatus(dutyCourse, course, afterRefresh) {\n // COMPLETED : has been submitted\n var isCourseComplete = courses.find(function (x) {\n return x.CourseId == dutyCourse.Id && x.Status == \"Completed\";\n }) != null; // NEEDS SUBMIT : 1 hour has passed since the end of the course\n\n var now = moment.utc();\n\n if (!dutyCourse.IsCompleted) {\n var needsSubmit = false;\n var fetched = moment.utc(groundDuty.DutyEnd);\n var duration = moment.duration(now.diff(fetched)).asHours();\n\n if (duration > 1) {\n needsSubmit = true;\n }\n } // LIMITED : no info available\n\n\n var isCourseLimited = !course || course.HasLimitedInfo || course.HasLimitedSession && !afterRefresh; // OUTDATED : NeedsRefresh || 18 hours since last refresh\n\n var isCourseOutdated = false;\n\n if (course && course.FetchedTime) {\n var now = moment.utc();\n var fetched = moment.utc(course.FetchedTime);\n var duration = moment.duration(now.diff(fetched)).asHours();\n\n if (duration > 18 || course.NeedsRefresh) {\n isCourseOutdated = true;\n }\n }\n\n $scope.headerMsg = \"Refresh Course\";\n if (isCourseLimited) $scope.headerMsg = \"Fetch Course\";\n $scope.hasPendingTraining = !isCourseComplete;\n $scope.hasUnsetTraining = needsSubmit;\n $scope.isCourseLimited = isCourseLimited;\n $scope.isCourseComplete = isCourseComplete;\n $scope.isCourseOutdated = isCourseOutdated;\n $scope.hasNotifications = isCourseLimited || isCourseOutdated || isCourseComplete;\n }\n\n function gotoGroundDuty() {\n $location.path('/groundDuty/' + groundDutyId);\n }\n\n function stickySelectedTrainee() {\n var availableRelease = $scope.selectedPhase.ModuleType == \"Check\" || !$scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (tr) {\n return tr.Session.Items.some(function (i) {\n return i.Status == \"Pending\";\n });\n });\n var individualGrading = $scope.trainees && $scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).length && $scope.selectedPhase && ($scope.selectedPhase.Syllabus && $scope.selectedPhase.Syllabus.IsGradable || $scope.selectedPhase.HasDayGrading || $scope.selectedPhase.HasReleaseGrading && availableRelease || RequiresTraineeSignature());\n\n if (individualGrading) {\n if ($scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).find(function (x) {\n return x.Session.selected;\n })) {\n $scope.selectedTrainee = $scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).find(function (x) {\n return x.Session.selected;\n });\n } else {\n $scope.selectedTrainee = $scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n })[0];\n }\n } else {\n $scope.selectedTrainee = null;\n }\n\n if ($scope.selectedTrainee) $scope.selectedTraineeBadge = {\n CrewId: $scope.selectedTrainee.CrewId\n };\n }\n\n function RequiresTraineeSignature() {\n // End of session signature\n var endOfSessionSignature = $scope.selectedPhase.DayGrading.TraineeSignature; // End of module signature\n\n var endOfModuleSignature = $scope.course.ReleasedPhase && $scope.selectedPhase.ReleaseGrading.TraineeSignature;\n return endOfSessionSignature || endOfModuleSignature;\n }\n\n function toggleView(mode) {\n $scope.viewMode = mode;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('instructions', instructions);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name notifications\r\n * @restrict E\r\n * @description\r\n * Show selected module's trainee & instructor instructions\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function instructions($filter, $routeParams, $location) {\n function link(scope, attrs) {\n scope.warningMessageText = \"\";\n scope.viewModuleHistory = viewModuleHistory;\n\n if (!scope.course.isParallel) {\n var currentActiveOrderNo = scope.selectedPhase.OrderNo;\n scope.course.CrewCoursePhases.forEach(function (phase) {\n if (phase.OrderNo < currentActiveOrderNo && phase.Status != \"Completed\") {\n phase.SequentialWarning = true;\n } //check if phase has any history\n\n\n var oldSessions = [];\n scope.trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n var historyPhase = trainee.Phases.find(function (x) {\n return x.PhaseId == phase.PhaseId;\n });\n if (historyPhase && historyPhase.Sessions) oldSessions = oldSessions.concat(historyPhase.Sessions);\n });\n phase.hasHistory = oldSessions.length > 0;\n });\n }\n\n scope.course.CrewCoursePhases.forEach(function (phase) {\n phase.StatusClass = '';\n\n if (phase.SequentialWarning) {\n phase.StatusClass = \"panel-danger border-left-red\";\n phase.BtnClass = \"bg-red text-white\";\n } else if (phase.Status == 'InProgress') {\n phase.StatusClass = \"border-left-blue\";\n phase.TextClass = \"text-blue\";\n phase.BtnClass = \"bg-blue text-white\";\n } else if (phase.Status == 'Pending') {\n phase.StatusClass = \"border-left-gray \";\n phase.TextClass = \"text-gray\";\n phase.BtnClass = \"bg-gray text-white\";\n } else if (phase.Status == 'Completed') {\n phase.StatusClass = \"border-left-green\";\n phase.TextClass = \"text-green\";\n phase.BtnClass = \"bg-green text-white\";\n }\n\n if (phase.PhaseId == scope.selectedPhase.PhaseId) {\n phase.StatusClass = phase.StatusClass + \" panel-info\";\n }\n });\n var furtherAheadPhases = [];\n furtherAheadPhases = scope.course.CrewCoursePhases.filter(function (x) {\n return x.SequentialWarning;\n });\n furtherAheadPhases = $filter('orderBy')(furtherAheadPhases, 'OrderNo');\n\n if (furtherAheadPhases.length > 0) {\n scope.course.SequenceWarning = true;\n scope.warningMessageText = \"\" + furtherAheadPhases[furtherAheadPhases.length - 1].Title + \" is not completed. Confirm that you want to continue to \" + scope.selectedPhase.Title + \".\";\n }\n\n scope.traineeInstructions = scope.selectedPhase.TraineeInstructions;\n scope.examinerInstructions = scope.selectedPhase.ExaminerInstructions;\n scope.continueSubmission = continueSubmission;\n scope.cancelSubmission = cancelSubmission;\n\n function continueSubmission() {\n scope.course.SequenceWarning = false;\n }\n\n function cancelSubmission() {\n if (scope.isGround) {\n gotoGroundDuty();\n } else {\n gotoCrewRoute();\n }\n }\n\n function gotoGroundDuty() {\n $location.path('/groundDuty/' + Number($routeParams.dutyId));\n }\n\n function gotoCrewRoute() {\n var dutyNo = scope.crewRouteDuty.DutyNo;\n var dutyDay = scope.crewRouteDuty.DutyDay;\n $location.path('/crewRoute/' + dutyNo + '/' + dutyDay);\n }\n\n function viewModuleHistory(phaseId) {\n var courseId = Number($routeParams.courseId);\n var dutyId = Number($routeParams.dutyId);\n var date = $routeParams.date;\n\n if (dutyId) {\n $location.path('/groundHistory/' + courseId + '/' + dutyId + '/' + date + '/' + phaseId);\n } else {\n var dutyNo = scope.crewRouteDuty.DutyNo;\n var dutyDay = scope.crewRouteDuty.DutyDay;\n $location.path('/flightHistory/' + courseId + '/' + dutyNo + '/' + dutyDay + '/' + date + '/' + phaseId);\n }\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/Training/instructions.tpl.html\",\n scope: false,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('media', media);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name ground Media\r\n * @restrict E\r\n * @description\r\n * Initialize panel with media of training selection, aircraft types & synthetic devices\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function media($location, CourseFactory) {\n function link(scope, attrs) {\n scope.addAircraftRow = addAircraftRow;\n scope.removeAircraftRow = removeAircraftRow;\n scope.isObjectEmpty = isObjectEmpty;\n initializeMedia();\n\n function isObjectEmpty(obj) {\n return Object.keys(obj).length === 0;\n }\n\n function initializeMedia() {\n if (scope.course) {\n if (!scope.course.Media) {\n // Create Media object\n scope.course.Media = {\n inputAircrafts: [],\n selectedAircraft: {\n selection: undefined\n },\n selectedDevice: {\n selection: undefined\n },\n radioModel: \"\"\n };\n }\n\n if (scope.course.Media.radioModel == \"\" || mediaRemoved()) {\n //Auto select media on init or if selection was removed in admin settings\n if (scope.selectedPhase.InSimulator) scope.course.Media.radioModel = \"Simulator\";\n if (scope.selectedPhase.InAircraft) scope.course.Media.radioModel = \"Aircraft\";\n if (scope.selectedPhase.InClassroom) scope.course.Media.radioModel = \"Classroom\";\n }\n\n if (scope.selectedPhase.InSimulator) {\n //Auto select device on init\n if (!scope.course.Media.selectedDevice.selection && scope.course.SyntheticDevices && !isObjectEmpty(scope.course.SyntheticDevices)) {\n scope.course.Media.selectedDevice.selection = Object.keys(scope.course.SyntheticDevices)[0];\n } //Remove selection if no devices\n\n\n if (!scope.course.SyntheticDevices || isObjectEmpty(scope.course.SyntheticDevices)) {\n scope.course.Media.selectedDevice.selection = undefined;\n }\n }\n }\n }\n\n function mediaRemoved() {\n return scope.course.Media.radioModel == \"Simulator\" && !scope.selectedPhase.InSimulator || scope.course.Media.radioModel == \"Aircraft\" && !scope.selectedPhase.InAircraft || scope.course.Media.radioModel == \"Classroom\" && !scope.selectedPhase.InClassroom;\n }\n\n function addAircraftRow() {\n var aircraftTypes = scope.course.AircraftTypes;\n\n if (scope.course.Media.selectedAircraft.selection != undefined && aircraftTypes && aircraftTypes.includes(scope.course.Media.selectedAircraft.selection) && (!scope.course.Media.inputAircrafts || !scope.course.Media.inputAircrafts.includes(scope.course.Media.selectedAircraft.selection))) {\n //Add to selected\n if (!scope.course.Media.inputAircrafts) {\n scope.course.Media.inputAircrafts = [];\n }\n\n scope.course.Media.inputAircrafts.push(scope.course.Media.selectedAircraft.selection); //Remove from options\n\n scope.course.AircraftTypes = aircraftTypes.filter(function (aircraft) {\n return aircraft != scope.course.Media.selectedAircraft.selection;\n }); //Clear \n\n scope.course.Media.selectedAircraft.selection = undefined;\n }\n }\n\n function removeAircraftRow(aircraft) {\n //Remove from selected\n var acIndex = scope.course.Media.inputAircrafts.indexOf(aircraft);\n scope.course.Media.inputAircrafts.splice(acIndex, 1); //Add back to options\n\n scope.course.AircraftTypes.push(aircraft);\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/Training/media.tpl.html\",\n scope: false,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ModuleHistoryCtrl', ModuleHistoryCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ModuleHistoryCtrl\r\n * @description \r\n *\r\n * @ngInject\r\n */\n\n function ModuleHistoryCtrl($scope, $routeParams, TrainingSessionFactory, CourseFactory, FlightSessionFactory, $location) {\n $scope.rightScroll = rightScroll;\n $scope.leftScroll = leftScroll;\n $scope.selectedTrainee = selectedTrainee;\n $scope.selectedSession = selectedSession;\n $scope.gotoCourse = gotoCourse;\n var isGround = false;\n\n if ($routeParams.dutyId) {\n isGround = true;\n var courseId = Number($routeParams.courseId);\n var dutyId = Number($routeParams.dutyId);\n var date = $routeParams.date;\n var phaseId = Number($routeParams.phaseId);\n } else {\n var courseId = Number($routeParams.courseId);\n var dutyNo = Number($routeParams.dutyNo);\n var dutyDay = Number($routeParams.dutyDay);\n var date = $routeParams.date;\n var phaseId = Number($routeParams.phaseId);\n }\n\n CourseFactory.getCourseFromStorage(courseId, function (course) {\n $scope.phase = course.CrewCoursePhases.find(function (x) {\n return x.PhaseId == phaseId;\n });\n $scope.course = course;\n\n if (isGround) {\n TrainingSessionFactory.getSessionTrainees(courseId, date, dutyId, function (trainees) {\n initHistory(trainees);\n });\n } else {\n FlightSessionFactory.getSessionTrainees(courseId, date, dutyNo, dutyDay, function (trainees) {\n initHistory(trainees);\n });\n }\n });\n\n function initHistory(trainees) {\n if (trainees && trainees.length) {\n trainees.forEach(function (trainee) {\n trainee.HistoryPhase = trainee.Phases.find(function (x) {\n return x.PhaseId == phaseId;\n });\n });\n $scope.historyTrainees = setHistoryTrainees(trainees);\n $scope.selectedTraineeBadge = {\n crewId: trainees[0].CrewId,\n traineeSessionId: trainees[0].HistoryPhase.Sessions[0].Id\n };\n $scope.selectedSubmittedSessionBadge = {\n sessionId: trainees[0].HistoryPhase.Sessions[0].SessionId\n };\n }\n }\n\n function setHistoryTrainees(trainees) {\n var historyTrainees = trainees.filter(function (x) {\n return x.HistoryPhase && x.HistoryPhase.Sessions && !x.Session.Absent;\n });\n historyTrainees.forEach(function (trainee) {\n trainee.HistoryPhase.hasSectors = trainee.HistoryPhase.Sessions.some(function (x) {\n return x.Sectors && x.Sectors.length > 0;\n });\n trainee.HistoryPhase.Sessions.forEach(function (session) {\n session.hasDayGrading = session.DayGrading.Comments || session.DayGrading.GradeType != 'NotSet' && session.DayGrading.Grade || session.DayGrading.Competences.length > 0;\n session.hasReleaseGrading = session.ReleaseGrading.Comments || session.ReleaseGrading.GradeType != 'NotSet' && session.ReleaseGrading.Grade || session.ReleaseGrading.Competences.length > 0;\n session.AcTypes = _toConsumableArray(new Set(session.Sectors.map(function (ses) {\n return ses.AcType;\n }))); //GroupBy AcType\n\n session.SectorsByAcType = [];\n session.AcTypes.forEach(function (acType) {\n var group = {\n AcType: acType,\n Sectors: session.Sectors.filter(function (x) {\n return x.AcType == acType;\n })\n };\n session.SectorsByAcType.push(group);\n });\n });\n setTraineeSummary(trainee.HistoryPhase);\n });\n return historyTrainees;\n }\n\n function setTraineeSummary(phase) {\n var sectorSummary = [];\n var totalSectors = 0; //Unique ac types of all sessions\n\n var allAcTypes = [];\n phase.Sessions.forEach(function (session) {\n allAcTypes = allAcTypes.concat(session.AcTypes);\n });\n allAcTypes = _toConsumableArray(new Set(allAcTypes)); //Group by ac type\n\n allAcTypes.forEach(function (acType) {\n var sectors = [];\n phase.Sessions.forEach(function (session) {\n sectors = sectors.concat(session.Sectors.filter(function (x) {\n return x.AcType == acType;\n }));\n });\n var sectorGroup = {\n AcType: acType,\n Sectors: sectors\n };\n totalSectors = totalSectors + sectors.length;\n sectorSummary.push(sectorGroup);\n });\n phase.SectorSummary = sectorSummary;\n phase.TotalSectors = totalSectors;\n }\n\n function selectedTrainee() {\n return function (trainee) {\n var showSession = false;\n\n if (trainee.CrewId === $scope.selectedTraineeBadge.crewId) {\n showSession = true;\n }\n\n return showSession;\n };\n }\n\n function selectedSession() {\n return function (historyTrainee) {\n var showSession = false;\n\n if (historyTrainee.SessionId === $scope.selectedSubmittedSessionBadge.sessionId) {\n showSession = true;\n }\n\n return showSession;\n };\n }\n\n function leftScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\n }\n\n function rightScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\n }\n\n function gotoCourse() {\n if (isGround) {\n $location.path('/groundcourse/' + Number($routeParams.courseId) + '/' + Number($routeParams.dutyId) + '/' + $routeParams.date);\n } else {\n $location.path('/flightcourse/' + Number($routeParams.courseId) + '/' + Number($routeParams.dutyNo) + '/' + Number($routeParams.dutyDay) + '/' + $routeParams.date);\n }\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('nonEligibleTrainees', nonEligibleTrainees);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name nonEligibleTrainees\r\n * @restrict E\r\n * @description\r\n * Show trainees that are not eligible for this training session\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\n\n function nonEligibleTrainees(FlightSessionFactory, $routeParams) {\n function link(scope) {\n scope.categories = setCategories(); //Collect duty trainees\n\n var dutyTrainees = [];\n\n if (scope.groundDuty) {\n scope.groundDuty.Trainees.forEach(function (related) {\n related.CrewMembers.forEach(function (trainee) {\n dutyTrainees.push(trainee);\n });\n });\n } else {\n var date = $routeParams.date;\n var dutyNo = Number($routeParams.dutyNo);\n var dutyDay = Number($routeParams.dutyDay);\n var crewRouteCourse = scope.crewRouteDuty.Courses.find(function (x) {\n return x.CourseId == scope.course.Id && new moment(x.Date).isSame(date);\n });\n var dutyTrainees = FlightSessionFactory.getCrewRouteFlightTrainees(dutyNo, dutyDay, crewRouteCourse.TrainingFlightIds);\n }\n\n if (scope.course && scope.course.CourseTrainees) {\n categorizeTrainee(dutyTrainees);\n }\n\n scope.dutyTrainees = dutyTrainees;\n\n function setCategories() {\n var parallelMessage = \"Trainees may have already completed this module\";\n var sequentialMessage = \"Trainees have either completed this module or are not yet ready to start it\";\n return [{\n title: \"InvalidPhase\",\n msg: scope.course.isParallel ? parallelMessage : sequentialMessage,\n trainees: [],\n all: false\n }, {\n title: \"Submitted\",\n msg: \"Trainees have already been submitted\",\n trainees: [],\n all: false\n }, {\n title: \"RecurrentPeriod\",\n msg: \"Trainees have completed the course earlier\",\n trainees: [],\n all: false\n }, {\n title: \"InvalidRole\",\n msg: \"For this training, cabin crew trainees can only be assessed by a cabin crew instructor\",\n trainees: [],\n all: false\n }];\n }\n\n function categorizeTrainee(dutyTrainees) {\n var allEligibilityTrainees = scope.course.CourseTrainees.concat(scope.course.NonEligibleTrainees);\n dutyTrainees.forEach(function (dutyTrainee) {\n var courseTrainee = allEligibilityTrainees.find(function (x) {\n return x.CrewId == dutyTrainee.Id;\n });\n\n if (courseTrainee) {\n // if (courseTrainee.ActivePhaseStatus == 'Completed') {\n // scope.categories.find(x => x.title==\"Completed\").trainees.push(dutyTrainee);\n // }\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc == 'AlreadySubmitted') {\n scope.categories.find(function (x) {\n return x.title == \"Submitted\";\n }).trainees.push(dutyTrainee);\n }\n\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc == 'InvalidPhase') {\n scope.categories.find(function (x) {\n return x.title == \"InvalidPhase\";\n }).trainees.push(dutyTrainee);\n }\n\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc == 'CooldownPending') {\n scope.categories.find(function (x) {\n return x.title == \"RecurrentPeriod\";\n }).trainees.push(dutyTrainee);\n }\n\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc == 'InvalidRole') {\n scope.categories.find(function (x) {\n return x.title == \"InvalidRole\";\n }).trainees.push(dutyTrainee);\n }\n }\n });\n var allCategory = scope.categories.find(function (x) {\n return x.trainees.length == dutyTrainees.length;\n }); //all trainees in same category\n\n if (allCategory) {\n allCategory.all = true;\n }\n }\n }\n\n return {\n restrict: 'E',\n terminal: true,\n templateUrl: \"views/Training/non-eligible-trainees.tpl.html\",\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('NotificationModalCtrl', NotificationModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name NotificationModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\n\n function NotificationModalCtrl($scope, $uibModalInstance) {\n $scope.close = close;\n /**\r\n * Close the modal\r\n * @memberof NotificationModalCtrl\r\n */\n\n function close() {\n $uibModalInstance.close($scope.success);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('notifications', notifications);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name notifications\r\n * @restrict E\r\n * @description\r\n * Initialize panel with information messages about session's status and necessary actions\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function notifications($routeParams) {\n function link(scope) {\n var info = {\n msg: \"\",\n border: \"\",\n text: \"\",\n showHistory: false\n };\n var date = $routeParams.date;\n scope.filterSession = filterSession;\n scope.selectSession = selectSession;\n scope.historyAvailable = false; //If already submitted : show submitted sessions menu and select first\n\n if (scope.course.SubmittedSessions && scope.course.SubmittedSessions.length) {\n var submittedDay = scope.course.SubmittedSessions[0].DutyDay;\n var isSame = moment(date).isSame(submittedDay);\n\n if (isSame) {\n scope.course.historyAvailable = true;\n scope.historyAvailable = true;\n scope.selectedSubmittedSession = {\n sessionId: scope.course.SubmittedSessions[0].SessionId\n };\n }\n } // 1. Check if session has been already submitted \n\n\n var isCourseComplete = scope.isCourseComplete;\n\n if (isCourseComplete) {\n info = {\n msg: \"Training form already submitted for this day.\",\n border: \"border-left-orange\",\n text: \"text-orange\",\n showHistory: true //show what was submitted in read-only view\n\n };\n } // 2. Check if course is Outdated\n\n\n var isCourseOutdated = scope.isCourseOutdated;\n\n if (isCourseOutdated) {\n info = {\n msg: \"You have an outdated version of this course. Please Refresh Course.\",\n border: \"border-left-orange\",\n text: \"text-orange\",\n showHistory: false\n };\n } // 3. Check if course needs an initial fetch\n\n\n var isCourseLimited = scope.isCourseLimited;\n\n if (isCourseLimited && !isCourseComplete) {\n isCourseLimited = true;\n info = {\n msg: \"You need to perform an initial fetch to receive all available information.\",\n border: \"border-left-blue\",\n text: \"text-blue\",\n showHistory: false\n };\n } // Result\n\n\n scope.info = info;\n /**\r\n * Filter submitted sessions based on selected from the top menu\r\n * @returns if session is currently selected\r\n */\n\n function filterSession() {\n return function (traineeSession) {\n var showSessionTrainees = false;\n\n if (traineeSession.SessionId === scope.selectedSubmittedSession.sessionId) {\n showSessionTrainees = true;\n }\n\n return showSessionTrainees;\n };\n }\n\n function selectSession(sessionId) {\n scope.selectedSubmittedSession.sessionId = sessionId;\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/Training/notifications.tpl.html\",\n scope: false,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('pilotFunction', pilotFunction);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name pilotFunction\r\n * @restrict E\r\n * @description\r\n * Initialize panel with pm/pf and seating info : Only for pilots in flight courses\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function pilotFunction(FlightFactory, UserFactory, $timeout) {\n function link(scope, attrs, $routeParams) {\n scope.selectSeat = selectSeat;\n scope.selectFunction = selectFunction;\n scope.reloadPilotFunction = false;\n var date = scope.crewRouteDuty.date;\n var courseId = scope.dutyCourse.Id;\n var crewRouteCourse = scope.crewRouteDuty.Courses.find(function (x) {\n return x.CourseId == courseId && new moment(x.Date).isSame(date);\n });\n var trainingFlightIds = crewRouteCourse.TrainingFlightIds;\n var trainingFlights = [];\n trainingFlightIds.forEach(function (flightId) {\n trainingFlights.push(FlightFactory.getFlightFromStorage(flightId));\n });\n var instructor = UserFactory.getUser();\n var instructorTrainingIndicator = trainingFlights[0].crew.find(function (x) {\n return x.id == instructor.id;\n }).TrainingIndicatorCode;\n var traineeTrainingIndicator = instructorTrainingIndicator.toLowerCase();\n scope.flights = trainingFlights;\n trainingFlights.forEach(function (flight) {\n flight.hasMultipleTrainees = flight.crew.filter(function (x) {\n return x.TrainingIndicatorCode && x.TrainingIndicatorCode == traineeTrainingIndicator && !x.isDHC && x.IsTrainee;\n }).length > 1;\n });\n initializePilotFunctions(); //Operating pilots can change in each sector\n //When multiple trainees, instructor is not operating\n\n trainingFlights.forEach(function (flight) {\n //Assign operatingPilots on each flight\n flight.operatingPilots = flight.hasMultipleTrainees ? scope.course.PilotFunctions.filter(function (x) {\n return !x.IsInstructor;\n }) : scope.course.PilotFunctions.filter(function (x) {\n return !x.Sectors.find(function (sec) {\n return sec.FlightId == flight.FlightId;\n }).NonApplicable;\n });\n });\n\n function initializePilotFunctions() {\n var PilotFunctions = [];\n\n if (scope.course && scope.trainees.length) {\n //Create trainee info\n scope.trainees.forEach(function (trainee) {\n nameArray = trainee.Name.split(/[ ]+/);\n var pilot = {\n CrewId: trainee.CrewId,\n AimsId: trainee.AimsId,\n Name: trainee.Name,\n FirstName: nameArray[1],\n LastName: nameArray[0],\n IsInstructor: false,\n Sectors: createLegInfo(trainee.CrewId, trainee)\n };\n PilotFunctions.push(pilot);\n }); //Create instructor info\n\n var nameArray = instructor.name.split(/[ ]+/);\n var pilot = {\n CrewId: instructor.id,\n AimsId: instructor.aimsId,\n Name: instructor.name,\n FirstName: nameArray[1],\n LastName: nameArray[0],\n IsInstructor: true,\n Sectors: createLegInfo(instructor.id)\n };\n PilotFunctions.push(pilot); //make only one pilot flying\n\n trainingFlights.forEach(function (flight) {\n var sectors = [];\n PilotFunctions.forEach(function (pilot) {\n var pilotSector = pilot.Sectors.find(function (sec) {\n return sec.FlightId == flight.FlightId;\n });\n\n if (pilotSector && !pilotSector.NonApplicable) {\n sectors.push(pilotSector);\n }\n });\n sectors[0].isPM = true;\n }); //Apply existing saved info\n\n if (scope.course.PilotFunctions) {\n PilotFunctions.forEach(function (pilot) {\n var existingInfo = scope.course.PilotFunctions.find(function (x) {\n return x.CrewId == pilot.CrewId;\n });\n\n if (existingInfo) {\n pilot.Seat = existingInfo.Seat;\n var sectors = [];\n pilot.Sectors.forEach(function (incomingSector) {\n var existingSector = existingInfo.Sectors.find(function (x) {\n return x.FlightId == incomingSector.FlightId && x.Arrival == incomingSector.Arrival && x.Departure == incomingSector.Departure;\n });\n\n if (existingSector) {\n var sector = deepCopy(existingSector);\n sector.NonApplicable = incomingSector.NonApplicable;\n sector.SeatOptions = incomingSector.SeatOptions;\n\n if (!incomingSector.SeatOptions.includes(sector.Seat)) {\n sector.Seat = incomingSector.Seat;\n }\n\n sectors.push(sector);\n } else {\n sectors.push(incomingSector);\n }\n });\n pilot.Sectors = sectors;\n }\n });\n }\n\n scope.reloadPilotFunction = true;\n }\n\n scope.course.PilotFunctions = PilotFunctions;\n }\n\n scope.instructor = instructor;\n\n function deepCopy(originalObject) {\n return JSON.parse(JSON.stringify(originalObject));\n }\n\n function createLegInfo(crewId, trainee) {\n var legs = [];\n var traineeSeatOptions = ['Right', 'Left'];\n var instructorSeatOptions = ['Right', 'Left', 'Jumpseat'];\n trainingFlights.forEach(function (flight) {\n var leg = {\n CrewId: crewId,\n FlightId: flight.FlightId,\n Departure: flight.Departure,\n Arrival: flight.Arrival,\n isPM: false,\n NonApplicable: trainee ? false : flight.hasMultipleTrainees,\n SeatOptions: trainee ? traineeSeatOptions : instructorSeatOptions\n };\n\n if (trainee) {\n leg.Seat = flight.hasMultipleTrainees ? undefined : 'Right';\n } else {\n leg.Seat = flight.hasMultipleTrainees ? 'Jumpseat' : 'Left';\n }\n\n legs.push(leg);\n });\n\n if (trainee) {\n // Get only the flights trainee is a participant of\n var traineeFlightIds = [];\n trainingFlights.forEach(function (flight) {\n var crewMember = flight.crew.find(function (x) {\n return x.id == trainee.CrewId;\n });\n\n if (crewMember && crewMember.TrainingIndicatorCode && crewMember.TrainingIndicatorCode == traineeTrainingIndicator) {\n traineeFlightIds.push(flight.FlightId);\n }\n });\n var nonActiveLegs = legs.filter(function (l) {\n return !traineeFlightIds.includes(l.FlightId);\n });\n nonActiveLegs.forEach(function (nonActiveLeg) {\n nonActiveLeg.NonApplicable = true;\n });\n }\n\n return legs;\n }\n\n function selectSeat(flight, pilot, leg) {\n if (flight.hasMultipleTrainees) {\n var otherPilotId = flight.operatingPilots.find(function (x) {\n return x.CrewId != pilot.CrewId;\n }).CrewId;\n var otherPilot = scope.course.PilotFunctions.find(function (x) {\n return x.CrewId == otherPilotId;\n });\n var otherSector = otherPilot.Sectors.find(function (x) {\n return x.FlightId == leg.FlightId;\n });\n\n if (leg.Seat == 'Left') {\n otherSector.Seat = 'Right';\n } else {\n otherSector.Seat = 'Left';\n }\n }\n }\n\n function selectFunction(flight, pilot, leg) {\n var otherPilotId = flight.operatingPilots.find(function (x) {\n return x.CrewId != pilot.CrewId;\n }).CrewId;\n var otherPilot = scope.course.PilotFunctions.find(function (x) {\n return x.CrewId == otherPilotId;\n });\n var otherSector = otherPilot.Sectors.find(function (x) {\n return x.FlightId == leg.FlightId;\n });\n\n if (leg.isPM) {\n otherSector.isPM = false;\n } else {\n otherSector.isPM = true;\n }\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/Training/pilotFunctionPanel.tpl.html\",\n scope: false,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('releasableModule', releasableModule);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name releasableModule\r\n * @restrict E\r\n * @description\r\n * Implementation of releasable Module\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function releasableModule(TrainingSessionFactory, $uibModal, $location) {\n function link(scope) {\n scope.Submit = Submit;\n scope.selectedTrainee = selectedTrainee;\n scope.toggleTrainee = toggleTrainee;\n scope.getRemainingCharacters = getRemainingCharacters;\n scope.leftScroll = leftScroll;\n scope.rightScroll = rightScroll;\n scope.validateGrading = validateGrading;\n scope.getTraineeClass = getTraineeClass;\n scope.openTraineeSignature = openTraineeSignature;\n scope.resetSignature = resetSignature;\n scope.close = close;\n\n var _isGround = scope.groundDuty != null && scope.groundDuty != null;\n\n var phaseId = scope.course.SubmittedSessions[0].PhaseId;\n var phase = scope.course.CrewCoursePhases.find(function (x) {\n return x.PhaseId == phaseId;\n });\n scope.settings = phase.ReleaseGrading; //Collect all trainee sessions that could be released\n\n var trainees = [];\n scope.course.SubmittedSessions.forEach(function (session) {\n session.TraineesSessions.filter(function (x) {\n return x.CouldBeReleased;\n }).forEach(function (traineeSession) {\n traineeSession.RadioModel = true; //set default realease option true\n\n trainees.push(traineeSession);\n });\n });\n\n if (trainees.length) {\n initializeTrainees(trainees, phase);\n }\n\n scope.phase = phase;\n scope.trainees = trainees;\n\n function initializeTrainees(trainees, phase) {\n scope.selectedTraineeBadge = {\n crewId: trainees[0].CrewId\n }; // Set Release Grading\n\n var releaseCompetences = phase.ReleaseGrading.Competences;\n releaseCompetences.forEach(function (competence) {\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences);\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences); //Filter out from optional the ones common with mandatory\n\n competence.OptionalSub = competence.OptionalSub.filter(function (c) {\n return !competence.MandatorySub.includes(c);\n });\n }); //Set Trainee Competences\n\n trainees.forEach(function (traineeSession) {\n var competences = [];\n releaseCompetences.forEach(function (competence) {\n competences.push(JSON.parse(JSON.stringify(competence)));\n });\n traineeSession.ReleaseGrading.Competences = competences;\n }); //Initialize validation\n\n trainees.forEach(function (traineeSession) {\n traineeSession.ReleaseGrading.isGradeValid = scope.settings.GradeType == \"NotSet\";\n traineeSession.ReleaseGrading.isReleaseGradingValid = scope.settings.Competences.length == 0;\n }); //For ground: check aircraft visits\n\n if (_isGround && phase.AircraftTypes.length) {\n trainees.forEach(function (trainee) {\n var visitedAircrafts = trainee.AllVisitedAcTypes;\n var pendingAircrafts = [];\n phase.AircraftTypes.forEach(function (type) {\n var array = type.split(','); //if arvi requirement is not met\n\n if (!array.some(function (x) {\n return visitedAircrafts.includes(x);\n })) {\n var pendingArviList = [];\n\n if (array.length > 1) {\n array.forEach(function (arvi) {\n pendingArviList.push(arvi);\n });\n } else {\n pendingArviList.push(array[0]);\n }\n\n pendingAircrafts.push(pendingArviList);\n }\n });\n trainee.pendingAircrafts = pendingAircrafts;\n trainee.ShowReleaseWarning = trainee.pendingAircrafts.length > 0;\n });\n }\n\n scope.showReleaseWarning = trainees.some(function (x) {\n return x.ShowReleaseWarning;\n });\n }\n\n function selectedTrainee() {\n return function (trainee) {\n var showTrainee = false;\n\n if (trainee.CrewId === scope.selectedTraineeBadge.crewId) {\n showTrainee = true;\n }\n\n return showTrainee;\n };\n }\n\n function close() {\n scope.modalInstance.close();\n }\n\n function toggleTrainee() {\n if (!scope.selectedTraineeBadge.crewId) {\n scope.selectedTraineeBadge.crewId = scope.trainees.find(function (x) {\n return x.RadioModel;\n }).CrewId;\n }\n\n var selectedCrewId = scope.selectedTraineeBadge.crewId;\n var selectedTrainee = scope.trainees.find(function (x) {\n return x.CrewId == selectedCrewId;\n });\n\n if (selectedTrainee && !selectedTrainee.RadioModel) {\n if (scope.trainees.find(function (x) {\n return x.RadioModel;\n })) {\n scope.selectedTraineeBadge.crewId = scope.trainees.find(function (x) {\n return x.RadioModel;\n }).CrewId;\n } else {\n scope.selectedTraineeBadge.crewId = null;\n }\n }\n }\n\n function getTraineeClass(crewId) {\n var textClass = \"\";\n var trainee = scope.trainees.find(function (x) {\n return x.CrewId == crewId;\n }); //Validate Release grading\n\n var isReleaseGradingValid = trainee.ReleaseGrading.isGradeValid;\n var isReleaseCompetencesValid = trainee.ReleaseGrading.isCompetenceValid;\n\n if (isReleaseGradingValid && isReleaseCompetencesValid) {\n textClass = \"bg-green text-white\";\n } else {\n textClass = \"bg-amber text-white\";\n }\n\n return textClass;\n }\n\n function Submit() {\n if (!isValidForm()) {\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgSubmitValidation.html',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'lg'\n });\n } else {\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgSign.html',\n controller: 'ReleaseSignatureModalCtrl',\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n courseId: function courseId() {\n return scope.course.Id;\n },\n isGround: function isGround() {\n return _isGround;\n },\n confirmationMsg: function confirmationMsg() {\n return scope.settings.ConfirmationMessage;\n },\n requiresInstructorSignature: function requiresInstructorSignature() {\n return scope.settings.InstructorSignature;\n },\n trainees: function trainees() {\n return scope.trainees.filter(function (x) {\n return x.RadioModel;\n });\n },\n submitRelease: function submitRelease() {\n return SubmitRelease;\n }\n }\n });\n scope.modalInstance.result.then(function (result) {\n if (result.success) {\n $location.path(\"/\");\n }\n });\n }\n }\n\n function SubmitRelease(password) {\n var submittedSessions = {\n SignaturePassword: password,\n TraineesSessions: trainees.filter(function (x) {\n return x.RadioModel;\n })\n };\n return TrainingSessionFactory.releaseSession(submittedSessions);\n }\n\n function validateGrading(trainee) {\n trainee.ReleaseGrading.isGradeValid = trainee.ReleaseGrading.Grade != null && trainee.ReleaseGrading.Grade != undefined;\n }\n /**\r\n * Calculate remaining characters for comment input\r\n * @param {string} text \r\n * @param {number} max \r\n */\n\n\n function getRemainingCharacters(text, max) {\n if (typeof text === \"undefined\" || text === null) return '';\n if (typeof max === \"undefined\" || max === null || max < 0 || !max) max = 4000;\n var length = text.length;\n return 'characters left: ' + (max - length);\n }\n\n function setSubCompetenceValues(current) {\n var updated = [];\n var first = parseInt(current[0], 10);\n var last = current[current.length - 1];\n\n if (first) {\n for (var i = first; i <= last; i++) {\n updated.push(i);\n }\n }\n\n return updated;\n }\n\n function leftScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\n }\n\n function rightScroll() {\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\n }\n\n function isValidForm() {\n /*Requirements before split release\r\n 1. OnLine Mode\r\n 2. Valid Release Grading\r\n 3. Trainee Signature\r\n */\n var selectedTrainee = scope.trainees.find(function (x) {\n return x.CrewId == scope.selectedTraineeBadge.crewId;\n });\n var isValid = false;\n var info = {\n border: \"\",\n icon: \"\",\n msg: \"\"\n };\n\n if (!window.navigator.onLine) {\n info = {\n border: \"border-left-red\",\n icon: \"fa-warning text-red\",\n msg: \" Online mode is required in order to submit a training.

Check your connection and try again!

\"\n };\n } else if (scope.settings.TraineeSignature && scope.trainees.filter(function (x) {\n return x.RadioModel;\n }).some(function (x) {\n return !x.Authorized;\n })) {\n if (selectedTrainee && !selectedTrainee.Authorized) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-pencil-square-o text-orange\",\n msg: \"\" + selectedTrainee.TraineeName + \" needs to sign the form!\",\n scrollToTop: false\n };\n } else {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"All trainees need to sign their forms!\",\n scrollToTop: true\n };\n }\n } else if (!isGradingValid()) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"\"\n };\n\n if (selectedTrainee && !selectedTrainee.ReleaseGrading.isCompetenceValid) {\n info.msg = \"You need to grade all competences for \" + selectedTrainee.TraineeName + \" before submitting!\";\n } else if (selectedTrainee && !selectedTrainee.ReleaseGrading.isGradeValid) {\n info.msg = \"You need to grade \" + selectedTrainee.TraineeName + \" before submitting!\";\n } else if (!scope.gradingValidationInfo.isReleaseCompetencesValid || !scope.gradingValidationInfo.isReleaseGradingValid) {\n info.msg = \"You need to grade all trainees before submitting!\";\n }\n } else {\n isValid = true;\n }\n\n scope.info = info;\n return isValid;\n }\n\n function validateTraineeForm(trainee) {\n /*Requirements before trainee signature\r\n 1. OnLine Mode\r\n 2. Valid Trainee Release Grading\r\n */\n var isValid = false;\n var info = {\n border: \"\",\n icon: \"\",\n msg: \"\"\n };\n\n if (!window.navigator.onLine) {\n info = {\n border: \"border-left-red\",\n icon: \"fa-warning text-red\",\n msg: \" Online mode is required in order to submit a training.

Check your connection and try again!

\"\n };\n } else if (!trainee.ReleaseGrading.isCompetenceValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to grade all competences!\"\n };\n } else if (!trainee.ReleaseGrading.isGradeValid) {\n info = {\n border: \"border-left-orange\",\n icon: \"fa-warning text-orange\",\n msg: \"You need to select an overall grade!\"\n };\n } else {\n isValid = true;\n }\n\n scope.info = info;\n return isValid;\n }\n\n function isGradingValid() {\n var isReleaseGradingValid = scope.settings.GradeType == \"NotSet\";\n var isReleaseCompetencesValid = scope.settings.Competences.length == 0;\n if (!isReleaseGradingValid) isReleaseGradingValid = !scope.trainees.filter(function (x) {\n return x.RadioModel;\n }).some(function (x) {\n return !x.ReleaseGrading.isGradeValid;\n });\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !scope.trainees.filter(function (x) {\n return x.RadioModel;\n }).some(function (x) {\n return !x.ReleaseGrading.isCompetenceValid;\n });\n scope.gradingValidationInfo = {\n isReleaseGradingValid: isReleaseGradingValid,\n isReleaseCompetencesValid: isReleaseCompetencesValid\n };\n return isReleaseGradingValid && isReleaseCompetencesValid;\n }\n\n function openTraineeSignature(_trainee) {\n //Enter signature mode : trainee form becomes read-only\n if (!_trainee.Authorized) {\n //Trainee can sign only if his form is valid\n if (!validateTraineeForm(_trainee)) {\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgSubmitValidation.html',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'lg'\n });\n } else {\n _trainee.Session = {\n Authorized: false\n };\n _trainee.Name = _trainee.TraineeName;\n scope.modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgTraineeSignature.html',\n controller: 'TraineeSignatureModalCtrl',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n trainee: function trainee() {\n return _trainee;\n },\n signatureSuccess: function signatureSuccess() {\n return function () {\n _trainee.Authorized = true;\n };\n }\n }\n });\n }\n }\n }\n\n function resetSignature(_trainee2) {\n var modalInstance = $uibModal.open({\n templateUrl: 'views/Training/dlgResetSignature.html',\n controller: 'TraineeSignatureModalCtrl',\n scope: scope,\n backdrop: 'static',\n keyboard: false,\n size: 'md',\n resolve: {\n trainee: function trainee() {\n return _trainee2;\n },\n signatureSuccess: function signatureSuccess() {\n return function () {};\n }\n }\n });\n modalInstance.result.then(function (confirm) {\n if (confirm) {\n _trainee2.Authorized = false;\n _trainee2.Session.Authorized = false;\n }\n });\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/releasable-module.tpl.html',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('releaseWarning', releaseWarning);\n /**\r\n * @memberof CabinReports\r\n * @ngdoc directive\r\n * @name releaseWarning\r\n * @restrict E\r\n * @description\r\n * Soft rules alert in release\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function releaseWarning() {\n function link(scope, attrs) {\n scope.warningTrainees = scope.trainees.filter(function (x) {\n return !x.Session.Absent && x.ShowReleaseWarning;\n });\n scope.filterSelectedTrainee = filterSelectedTrainee;\n\n function filterSelectedTrainee() {\n return function (trainee) {\n var showTrainee = false;\n\n if (scope.selectedTrainee) {\n showTrainee = trainee.CrewId == scope.selectedTrainee.CrewId;\n }\n\n return showTrainee;\n };\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/Training/releaseWarning.tpl.html\",\n scope: false,\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ReleaseSignatureModalCtrl', ReleaseSignatureModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SignatureModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\n\n function ReleaseSignatureModalCtrl($scope, $routeParams, CourseFactory, $uibModalInstance, courseId, isGround, confirmationMsg, requiresInstructorSignature, trainees, submitRelease) {\n $scope.close = close;\n $scope.submit = submit;\n $scope.confirm = confirm;\n $scope.confirmAircraft = confirmAircraft;\n $scope.errorMessage = \"\";\n $scope.successMessage = \"\";\n $scope.responseText = null;\n $scope.responseHasErrors = null;\n $scope.success = false;\n $scope.isLoading = false;\n $scope.formData = {};\n $scope.requiredSignature = requiresInstructorSignature;\n $scope.isConfirmed = true;\n $scope.finalPendigArVis = [];\n\n if (isGround && hasPendingAircraftVisits()) {\n $scope.aircraftVisits = true;\n } else if (confirmationMsg) {\n $scope.confirmationMsg = confirmationMsg;\n $scope.isConfirmed = false;\n } else {\n if (!requiresInstructorSignature) {\n //if signature isn't required continue with submit \n $scope.isLoading = true;\n submit();\n }\n }\n\n function hasPendingAircraftVisits() {\n var released = trainees.filter(function (x) {\n return x.RadioModel;\n });\n var pendingVisits = released.some(function (x) {\n return x.pendingAircrafts && x.pendingAircrafts.length > 0;\n });\n\n if (pendingVisits) {\n var maxLength = 0;\n released.forEach(function (trainee) {\n if (trainee.pendingAircrafts.length > maxLength) {\n var maxList = trainee.pendingAircrafts;\n maxLength = maxList.length;\n $scope.finalPendigArVis = trainee.pendingAircrafts;\n }\n });\n }\n\n return pendingVisits;\n }\n\n function confirm() {\n $scope.isConfirmed = true;\n\n if (!requiresInstructorSignature) {\n //if signature isn't required continue with submit \n $scope.isLoading = true;\n submit();\n }\n }\n\n function confirmAircraft() {\n $scope.aircraftVisits = false;\n\n if (confirmationMsg) {\n $scope.confirmationMsg = confirmationMsg;\n $scope.isConfirmed = false;\n }\n }\n\n function submit() {\n $scope.errorMessage = \"\";\n $scope.successMessage = \"\";\n $scope.isLoading = true;\n $scope.success = false;\n var signaturePassword = $scope.formData.password;\n\n if (!signaturePassword && requiresInstructorSignature) {\n $scope.isLoading = false;\n $scope.errorMessage = \"Signature is required. Please enter your password.\";\n } else {\n submitRelease(signaturePassword).then(function (data) {\n $scope.isLoading = false;\n var errorMessage = data.data.errorMessage;\n $scope.successMessage = \"Training has been submitted.\"; //always show errorMessage even if success is true\n\n if (errorMessage && errorMessage.length > 0) {\n $scope.errorMessage = errorMessage; //not Release Trainees\n\n var responseTrainees = data.data.data.data;\n var responseTraineeCrewIds = responseTrainees.map(function (trainee) {\n return trainee.CrewId;\n });\n $scope.traineeInfo = trainees.filter(function (x) {\n return responseTraineeCrewIds.includes(x.CrewId);\n });\n } else {\n $scope.errorMessage = null;\n }\n\n CourseFactory.setCourseOutdated(courseId);\n $scope.success = true;\n })[\"catch\"](function (data) {\n $scope.isLoading = false;\n\n if (data.data && data.data.errorMessage) {\n $scope.errorMessage = data.data.errorMessage;\n } else {\n $scope.errorMessage = \"Failed to save Training Session\";\n }\n });\n } // clear password\n\n\n $scope.formData.password = \"\";\n }\n /**\r\n * Close the modal\r\n * @memberof SignModalCtrl\r\n */\n\n\n function close() {\n var result = {\n \"success\": $scope.success\n };\n $uibModalInstance.close(result);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('SignatureModalCtrl', SignatureModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SignatureModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\n\n function SignatureModalCtrl($scope, $routeParams, $uibModalInstance, TrainingSessionFactory, FlightSessionFactory, GroundDutyFactory, CrewRouteFactory, CourseFactory, courseId, date, dutyId, dutyNo, dutyDay, confirmationMsg, requiresInstructorSignature, trainees, submitSession, releaseGrading, isReleased) {\n $scope.close = close;\n $scope.submit = submit;\n $scope.confirm = confirm;\n $scope.confirmSubmit = confirmSubmit;\n $scope.releaseSubmit = releaseSubmit;\n $scope.confirmAircraft = confirmAircraft;\n $scope.errorMessage = \"\";\n $scope.successMessage = \"\";\n $scope.responseText = null;\n $scope.responseHasErrors = null;\n $scope.success = false;\n $scope.isLoading = false;\n $scope.withGrading = false;\n $scope.formData = {};\n var requiredSignature = requiresInstructorSignature;\n $scope.requiredSignature = requiredSignature;\n $scope.releaseWarning = false;\n $scope.isConfirmed = true;\n $scope.releaseGrading = releaseGrading;\n $scope.finalPendigArVis = [];\n var isGroundDuty = false;\n\n if (dutyId) {\n isGroundDuty = true;\n }\n\n if (releaseNotSelected()) {\n $scope.releaseWarning = true;\n } else if (isGroundDuty && hasPendingAircraftVisits()) {\n $scope.aircraftVisits = true;\n } else if (confirmationMsg && isReleased) {\n $scope.confirmationMsg = confirmationMsg;\n $scope.isConfirmed = false;\n } else {\n if (!requiresInstructorSignature) {\n //if signature isn't required continue with submit \n $scope.isLoading = true;\n submit();\n }\n }\n\n function releaseNotSelected() {\n var allAvailable = !trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.AvailableRelease;\n });\n var notReleased = trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.Session.Released;\n });\n return allAvailable && notReleased;\n }\n\n function hasPendingAircraftVisits() {\n var released = !trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return !x.Session.Released;\n }) || $scope.withGrading;\n var pendingVisits = released && trainees.filter(function (x) {\n return !x.Session.Absent;\n }).some(function (x) {\n return x.pendingAircrafts && x.pendingAircrafts.length > 0;\n });\n\n if (pendingVisits) {\n var maxLength = 0;\n trainees.filter(function (x) {\n return !x.Session.Absent;\n }).forEach(function (trainee) {\n if (trainee.pendingAircrafts.length > maxLength) {\n var maxList = trainee.pendingAircrafts;\n maxLength = maxList.length;\n $scope.finalPendigArVis = trainee.pendingAircrafts;\n }\n });\n }\n\n return pendingVisits;\n }\n\n function confirm() {\n $scope.isConfirmed = true;\n\n if (!requiresInstructorSignature) {\n //if signature isn't required continue with submit \n $scope.isLoading = true;\n submit();\n }\n }\n\n function confirmSubmit() {\n $scope.releaseWarning = false;\n\n if (isGroundDuty && hasPendingAircraftVisits()) {\n $scope.aircraftVisits = true;\n }\n }\n\n function confirmAircraft() {\n $scope.aircraftVisits = false;\n\n if (confirmationMsg) {\n $scope.confirmationMsg = confirmationMsg;\n $scope.isConfirmed = false;\n }\n }\n\n function releaseSubmit() {\n $scope.withGrading = true;\n $scope.releaseWarning = false;\n\n if (hasPendingAircraftVisits()) {\n $scope.aircraftVisits = true;\n } else if (confirmationMsg) {\n $scope.confirmationMsg = confirmationMsg;\n $scope.isConfirmed = false;\n }\n }\n\n function submit() {\n $scope.errorMessage = \"\";\n $scope.successMessage = \"\";\n $scope.isLoading = true;\n $scope.success = false;\n var signaturePassword = $scope.formData.password;\n\n if (!signaturePassword && requiredSignature) {\n $scope.isLoading = false;\n $scope.errorMessage = \"Signature is required. Please enter your password.\";\n } else {\n submitSession(signaturePassword, $scope.withGrading).then(function (data) {\n $scope.isLoading = false;\n var errorMessage = data.data.errorMessage;\n $scope.successMessage = \"Training has been submitted.\"; //always show errorMessage even if success is true\n\n if (errorMessage && errorMessage.length > 0) {\n $scope.errorMessage = errorMessage; //not Release Trainees\n\n var responseTrainees = data.data.data.data;\n var responseTraineeCrewIds = responseTrainees.map(function (trainee) {\n return trainee.CrewId;\n });\n $scope.traineeInfo = trainees.filter(function (x) {\n return responseTraineeCrewIds.includes(x.CrewId);\n });\n } else {\n $scope.errorMessage = null;\n }\n\n if (dutyId) {\n //isGround\n TrainingSessionFactory.remove(courseId, date, dutyId);\n GroundDutyFactory.setCourseCompleted(dutyId, courseId);\n } else {\n //isFlight\n FlightSessionFactory.remove(courseId, date, dutyNo, dutyDay);\n CrewRouteFactory.setCourseCompleted(dutyNo, dutyDay, courseId, date);\n }\n\n CourseFactory.setCourseOutdated(courseId);\n $scope.success = true;\n })[\"catch\"](function (data) {\n $scope.isLoading = false;\n\n if (data.data && data.data.errorMessage) {\n $scope.errorMessage = data.data.errorMessage;\n } else {\n $scope.errorMessage = \"Failed to save Training Session\";\n }\n });\n } // clear password\n\n\n $scope.formData.password = \"\";\n }\n /**\r\n * Close the modal\r\n * @memberof SignModalCtrl\r\n */\n\n\n function close() {\n var result = {\n \"success\": $scope.success\n };\n $uibModalInstance.close(result);\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('syllabusItemHeader', syllabusItemHeader);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name syllabusItemHeader\r\n * @restrict E\r\n * @description\r\n * Panel heading for syllabus items\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function syllabusItemHeader() {\n function link(scope, element, attrs) {\n scope.selectTry = selectTry;\n scope.selectGrading = selectGrading; //find first not ReadOnly try\n\n scope.pendingAttempt = scope.item.Tries.find(function (x) {\n return x.isFirstTry;\n });\n scope.firstTry = scope.item.Tries[0];\n\n function selectTry() {\n if (scope.pendingAttempt) {\n scope.itemSelection();\n }\n }\n\n function selectGrading() {\n scope.gradingSelection();\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/syllabus-item-header.tpl.html',\n scope: {\n item: \"=\",\n itemSelection: \"&onItemSelection\",\n gradingSelection: \"&onGradingSelection\"\n },\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.directive('syllabus', syllabus);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name certificates\r\n * @restrict E\r\n * @description\r\n * Implementation of syllabus\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function syllabus(TrainingSessionFactory, FlightSessionFactory, $timeout) {\n function link(scope, element, attrs) {\n var isGround = false;\n var courseId = scope.dutyCourse.Id;\n\n if (scope.groundDuty) {\n isGround = true;\n var date = scope.groundDuty.DutyDateS;\n var dutyId = scope.groundDuty.Id;\n } else {\n var date = scope.crewRouteDuty.date;\n var dutyNo = scope.crewRouteDuty.DutyNo;\n var dutyDay = scope.crewRouteDuty.DutyDay;\n }\n\n scope.updateTraineesSyllabus = updateTraineesSyllabus;\n scope.selectTry = selectTry;\n scope.updateTry = updateTry;\n scope.oneAtATime = true;\n scope.addTry = addTry;\n scope.removeTry = removeTry;\n scope.setPanelStyle = setPanelStyle;\n scope.selectTryFromHeader = selectTryFromHeader;\n scope.gradeFromHeader = gradeFromHeader;\n scope.traineeSyllabi.forEach(function (traineeSyllabus) {\n traineeSyllabus.Items.forEach(function (syllabusItem) {\n syllabusItem.Tries.forEach(function (attempt) {\n //Check if default grade exists & set status\n if (syllabusItem.IsGradable && !attempt.isReadOnly) {\n itemAutoSelection(syllabusItem, attempt); //select item depending on grade existence\n }\n });\n setPanelStyle(syllabusItem); //ui depending on validation & status\n\n updateTraineesSyllabus(syllabusItem, traineeSyllabus); //copy values to all trainee syllabi \n });\n }); //Multiple syllabi - Get session to store competence grading\n\n if (scope.traineeSyllabi.length > 1) {\n scope.traineeSyllabi.forEach(function (traineeSyllabus) {\n var crewId = traineeSyllabus.TraineeIds[0];\n var trainee = scope.trainees.find(function (x) {\n return x.CrewId == crewId;\n });\n traineeSyllabus.TraineeName = trainee.Name;\n traineeSyllabus.TraineeAimsId = trainee.AimsId;\n });\n }\n\n function gradeFromHeader(syllabus, syllabusItem) {\n var firstPendingTry = syllabusItem.Tries.filter(function (x) {\n return !x.isReadOnly;\n })[0];\n updateTry(syllabus, syllabusItem, firstPendingTry);\n setPanelStyle(syllabusItem);\n updateTraineesSyllabus(syllabusItem, syllabus);\n triggerSyllabusClick();\n }\n\n function selectTryFromHeader(syllabus, syllabusItem) {\n var firstPendingTry = syllabusItem.Tries.filter(function (x) {\n return !x.isReadOnly;\n })[0];\n selectTry(syllabus, syllabusItem, firstPendingTry);\n\n if (isGround) {\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) {\n console.log(e);\n });\n } else {\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) {\n console.log(e);\n });\n }\n\n triggerSyllabusClick();\n }\n\n function triggerSyllabusClick() {\n //preventDefault() and stopPropagation() prevents setReleaseStatus() to be triggered\n $timeout(function () {\n var el = document.getElementById('syllabus');\n angular.element(el).triggerHandler('click');\n }, 0);\n }\n\n function selectTry(syllabus, syllabusItem, attempt) {\n attempt.Selected = !attempt.Selected;\n syllabusItem.Selected = syllabusItem.Tries.filter(function (t) {\n return !t.isReadOnly;\n }).some(function (t) {\n return t.Selected;\n });\n setPanelStyle(syllabusItem);\n updateTraineesSyllabus(syllabusItem, syllabus);\n }\n\n function updateTry(syllabus, syllabusItem, attempt) {\n if (syllabusItem.IsGradable) {\n itemAutoSelection(syllabusItem, attempt); //select item depending on grade existence\n }\n\n setPanelStyle(syllabusItem); //ui depending on validation & status\n\n updateTraineesSyllabus(syllabusItem, syllabus); //copy values to all trainee syllabi \n\n updateSession(); //save in IndexDb\n }\n\n function itemAutoSelection(syllabusItem, attempt) {\n var hasCompetencesGrading = attempt.TryGrading.Competences.some(function (x) {\n return x.Grading;\n });\n\n if (attempt.TryGrading.Grade || hasCompetencesGrading) {\n attempt.Selected = true;\n syllabusItem.Selected = true;\n } else {\n attempt.Selected = false;\n syllabusItem.Selected = false; //Check if any of the tries has grading - If not, deselect item\n\n var pendingTries = syllabusItem.Tries.filter(function (x) {\n return !x.isReadOnly;\n }); //filter out history tries\n\n for (var i = 0; i < pendingTries.length; i++) {\n var itemTry = pendingTries[i];\n var tryCompetenceGrading = itemTry.TryGrading.Competences.some(function (x) {\n return x.Grading;\n });\n\n if (itemTry.TryGrading.Grade || tryCompetenceGrading) {\n syllabusItem.Selected = true;\n break;\n }\n }\n }\n }\n\n function setPanelStyle(item) {\n var historyTriesCount = item.Tries.filter(function (x) {\n return x.isReadOnly;\n }).length;\n var newTriesCount = item.Tries.filter(function (x) {\n return !x.isReadOnly && x.Selected;\n }).length;\n item.TriesPerformedCount = historyTriesCount + newTriesCount;\n var completedItem = item.TriesPerformedCount >= item.MandatoryCount;\n\n if (item.MandatoryCount == 0) {\n //non-mandatory items are considered completed if performed at least once\n completedItem = item.TriesPerformedCount >= 1;\n }\n\n var invalidItem = false;\n\n if (item.IsGradable && item.Selected) {\n var gradingType = item.GradeType; //Numeric or Outcome or Competences\n\n var traineeSelectedTries = item.Tries.filter(function (x) {\n return x.Selected;\n });\n traineeSelectedTries.forEach(function (selectedTry) {\n var invalidGrading = gradingType != \"Competences\" && !selectedTry.TryGrading.Grade;\n var invalidCompetences = gradingType == \"Competences\" && !selectedTry.TryGrading.isCompetenceValid;\n\n if (invalidGrading || invalidCompetences) {\n invalidItem = true;\n }\n });\n }\n\n if (completedItem) {\n item.PanelClass = 'panel-green panel-border-left-green ';\n } else {\n item.PanelClass = 'panel-border-left-blue ';\n }\n\n if (invalidItem) {\n item.PanelClass = 'panel-border-left-orange ';\n }\n }\n\n function updateTraineesSyllabus(item, syllabus) {\n var crewIds = syllabus.TraineeIds;\n scope.trainees.filter(function (x) {\n return crewIds.includes(x.CrewId);\n }).forEach(function (trainee) {\n var sessionItem = trainee.Session.Items.find(function (sessionItem) {\n return item.Id == sessionItem.Id;\n });\n sessionItem.RepeatRequired = item.RepeatRequired;\n sessionItem.Selected = item.Selected;\n sessionItem.PhaseId = item.PhaseId;\n sessionItem.Tries = deepCopy(item.Tries);\n sessionItem.SyllabusItemId = item.Id;\n sessionItem.TriesPerformedCount = item.TriesPerformedCount;\n });\n }\n\n function deepCopy(originalObject) {\n return JSON.parse(JSON.stringify(originalObject));\n }\n\n function addTry(item, syllabus) {\n var competences = deepCopy(item.Competences);\n var newTry = {\n Comments: null,\n ActionNo: item.Tries.length + 1,\n Selected: true,\n TryGrading: {\n Grade: null,\n Competences: competences,\n GradeType: item.GradeType\n }\n };\n item.Selected = true;\n item.Tries.push(newTry);\n setPanelStyle(item);\n updateTraineesSyllabus(item, syllabus);\n }\n\n function removeTry(item, syllabus) {\n item.Tries.pop();\n\n if (!item.Tries.filter(function (x) {\n return !x.isReadOnly;\n }).length) {\n item.Selected = false;\n }\n\n setPanelStyle(item);\n updateTraineesSyllabus(item, syllabus);\n }\n\n function updateSession() {\n if (isGround) {\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) {\n console.log(e);\n });\n } else {\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) {\n console.log(e);\n });\n }\n }\n }\n\n return {\n restrict: 'E',\n terminal: false,\n templateUrl: 'views/Training/syllabus.tpl.html',\n scope: false,\n link: link\n };\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('TraineeSignatureModalCtrl', TraineeSignatureModalCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name TraineeSignatureModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\n\n function TraineeSignatureModalCtrl($scope, $timeout, $uibModalInstance, trainee, TrainingSessionFactory, signatureSuccess) {\n $scope.close = close;\n $scope.confirmReset = confirmReset;\n $scope.traineeSign = traineeSign;\n $scope[\"continue\"] = continueWarning;\n $scope.confirmation = false;\n initialiazeTrainee(trainee);\n\n function initialiazeTrainee(trainee) {\n var signatureTrainee = deepCopy(trainee);\n signatureTrainee.Session.Authorized = trainee.Session.Authorized ? trainee.Session.Authorized : false;\n signatureTrainee.errorMessage = \"\";\n signatureTrainee.successMessage = \"\";\n signatureTrainee.responseText = null;\n signatureTrainee.responseHasErrors = null;\n signatureTrainee.success = false;\n signatureTrainee.isLoading = false;\n signatureTrainee.password = \"\";\n signatureTrainee.username = trainee.AimsId;\n signatureTrainee.PositionCode = trainee.position ? trainee.position : trainee.PositionCode;\n $scope.signatureTrainee = signatureTrainee;\n }\n\n function deepCopy(originalObject) {\n return JSON.parse(JSON.stringify(originalObject));\n }\n\n function traineeSign(signatureTrainee) {\n if (!signatureTrainee.password || !signatureTrainee.username) {\n signatureTrainee.errorMessage = \"Signature is required. Please enter your username and password.\";\n } else {\n signatureTrainee.isLoading = true; //Individually authorize trainee\n\n var credentials = {\n CrewId: signatureTrainee.CrewId,\n Password: signatureTrainee.password,\n Username: signatureTrainee.username,\n PositionCode: signatureTrainee.PositionCode\n };\n\n if ($scope.isOffline) {\n $timeout(function () {\n signatureTrainee.isLoading = false;\n }, 100);\n signatureTrainee.errorMessage = \"Online mode is required in order to sign. Please connect to the internet and try again.\";\n } else {\n TrainingSessionFactory.authorizeTrainee(credentials, function (responseData) {\n signatureTrainee.isLoading = false;\n signatureTrainee.success = true;\n signatureTrainee.Session.Authorized = true;\n signatureTrainee.Session.Authorized = true;\n trainee.Session.Authorized = true;\n signatureSuccess();\n })[\"catch\"](function (data) {\n signatureTrainee.isLoading = false;\n\n if (data.data && data.data.errorMessage) {\n signatureTrainee.errorMessage = data.data.errorMessage;\n } else {\n signatureTrainee.errorMessage = \"An error occured during your authentication\";\n }\n });\n }\n } // clear credentials\n\n\n trainee.username = \"\";\n trainee.password = \"\";\n }\n /**\r\n * Close the modal\r\n */\n\n\n function close() {\n $uibModalInstance.close(false);\n }\n /**\r\n * Confirm\r\n */\n\n\n function confirmReset() {\n $uibModalInstance.close(true);\n }\n\n function continueWarning() {\n $scope.confirmation = true;\n }\n }\n})();\n\"use strict\";\n\n(function () {\n a3_pilot_reports.directive('trainingMenu', trainingMenu);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name ground Course List\r\n * @restrict E\r\n * @description\r\n * Initialize navigation menu panel with with status indicators\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\n\n function trainingMenu(CourseFactory, GroundDutyFactory, FlightFactory, CrewRouteFactory, $location, TrainingSessionFactory, FlightSessionFactory, $filter, $routeParams) {\n function link($scope, attrs) {\n $scope.gotoCourse = gotoCourse;\n $scope.hasPendingTraining = false;\n $scope.hasUnsetTraining = false;\n var groundSessions = [];\n var flightSessions = [];\n TrainingSessionFactory.getAll(function (savedGroundSessions) {\n FlightSessionFactory.getAll(function (savedFlightSessions) {\n groundSessions = savedGroundSessions;\n flightSessions = savedFlightSessions;\n $scope.courses = [];\n var duty = null;\n var dutyCourses = [];\n\n if ($scope.type == 'ground') {\n duty = GroundDutyFactory.getGroundDutyFromStorage($scope.id);\n $scope.duty = duty;\n\n if (duty && duty.RelatedGroundDuties) {\n dutyCourses = GroundDutyFactory.getGroundDutyActiveCourses($scope.id);\n\n if (dutyCourses) {\n CourseFactory.getCoursesFromStorageByIds(dutyCourses.map(function (course) {\n return course.CourseId;\n }), function (savedCourses) {\n manageGroundCourseStatuses(duty, dutyCourses, savedCourses); //Overall panel color\n\n if (savedCourses.some(function (x) {\n return x.Status == \"Draft\";\n })) {\n $scope.PanelClass = \"border-bottom-orange\";\n } else if (savedCourses.some(function (x) {\n return x.Status == \"Pending\" || x.Status == \"Outdated\";\n })) {\n $scope.PanelClass = \"border-bottom-blue\";\n } else {\n $scope.PanelClass = \"border-bottom-green\";\n }\n\n $scope.courses = savedCourses;\n });\n }\n }\n } else if ($scope.type == 'crewroute' || $scope.type == 'flight') {\n if ($scope.type == 'crewroute') {\n duty = CrewRouteFactory.getCrewRouteFromStorage($scope.dutyNo, $scope.dutyDay);\n } else {\n duty = FlightFactory.getFlightFromTotalFlights($scope.id);\n }\n\n if (duty && duty.Courses) {\n dutyCourses = duty.Courses;\n CourseFactory.getCoursesFromStorageByIds(dutyCourses.map(function (course) {\n return course.CourseId;\n }), function (savedCourses) {\n dutyCourses.forEach(function (dutyCourse) {\n var savedCourse = savedCourses.find(function (x) {\n return x.Id == dutyCourse.CourseId;\n });\n var course = {\n Id: savedCourse.Id,\n Title: savedCourse.Title,\n Day: new moment(dutyCourse.Date)\n };\n manageFlightCourseStatus(course, dutyCourse);\n $scope.courses.push(course);\n });\n $scope.courses.forEach(function (course) {\n course.FullDate = course.Day.format(\"YYYY-MM-DD\");\n course.Day = course.Day.format(\"DD/MM\");\n\n if ($scope.courses.filter(function (x) {\n return x.Id == course.Id;\n }).length > 1) {\n course.IsMultiday = true;\n }\n }); //Overall panel color\n\n if ($scope.courses.some(function (x) {\n return x.Status == \"Draft\";\n })) {\n $scope.PanelClass = \"border-bottom-orange\";\n } else if ($scope.courses.some(function (x) {\n return x.Status == \"Pending\" || x.Status == \"Outdated\";\n })) {\n $scope.PanelClass = \"border-bottom-blue\";\n } else {\n $scope.PanelClass = \"border-bottom-green\";\n }\n });\n }\n }\n });\n });\n\n function manageFlightCourseStatus(course, crewRouteCourse) {\n var now = moment.utc();\n var flights = FlightFactory.getFlightsFromStorage().filter(function (x) {\n return crewRouteCourse.TrainingFlightIds.includes(x.FlightId);\n });\n flights = $filter('orderBy')(flights, 'ScheduledArrival');\n var dutyEnd = flights[flights.length - 1].ScheduledArrival;\n var dutyDate = new moment(crewRouteCourse.Date).format(\"YYYY-MM-DD\");\n var status = \"\";\n\n if (crewRouteCourse.Status == \"Pending\") {\n //Pending\n course.Status = \"Pending\";\n course.StatusClass = \"text-blue\";\n course.StatusDesc = \"pending\"; //Outdated\n\n dutyEnd = moment.utc(dutyEnd);\n var duration = moment.duration(now.diff(dutyEnd)).asHours();\n\n if (duration > 1) {\n course.Status = \"Outdated\";\n } //Draft\n\n\n if (flightSessions && flightSessions.length) {\n var existingSession = flightSessions.find(function (s) {\n return s.courseId == crewRouteCourse.CourseId && s.day == dutyDate && s.dutyDay == $scope.dutyDay && s.dutyNo == $scope.dutyNo;\n });\n\n if (existingSession && !existingSession.HasLimitedInfo && existingSession.trainees && existingSession.trainees.length) {\n //a training session with trainees exists\n course.Status = \"Draft\";\n course.StatusClass = \"text-orange\";\n course.StatusDesc = \"draft\";\n }\n }\n } else if (crewRouteCourse.Status == \"Completed\") {\n //Completed\n course.Status = \"Completed\";\n course.StatusClass = \"text-green\";\n course.StatusDesc = \"synced\";\n }\n\n return status;\n }\n\n function manageGroundCourseStatuses(duty, dutyCourses, courses) {\n var now = moment.utc();\n courses.forEach(function (course) {\n var dutyCourse = dutyCourses.find(function (x) {\n return x.CourseId == course.Id;\n });\n course.Status = dutyCourse.Status;\n /*Statuses\r\n \tCompleted : session has been sent\r\n \tOutdated :\tsession submission is overdue\r\n \tDraft\t : session completion has started but not submitted\r\n \tPending : session submission not yet due\r\n */\n\n if (course.Status == \"Pending\") {\n course.StatusClass = \"text-blue\";\n course.StatusDesc = \"pending\"; //Outdated\n\n var dutyEnd = moment.utc(duty.DutyEnd);\n var duration = moment.duration(now.diff(dutyEnd)).asHours();\n\n if (duration > 1) {\n course.Status = \"Outdated\";\n } //Draft\n\n\n if (groundSessions && groundSessions.length) {\n var existingSession = groundSessions.find(function (s) {\n return s.courseId == course.Id && s.day == duty.DutyDateS && s.dutyId == duty.Id;\n });\n\n if (existingSession && !existingSession.HasLimitedInfo && existingSession.trainees && existingSession.trainees.length) {\n //a training session with trainees exists\n course.Status = \"Draft\";\n course.StatusClass = \"text-orange\";\n course.StatusDesc = \"draft\";\n }\n }\n } else if (course.Status == \"Completed\") {\n //Completed\n course.Status = \"Completed\";\n course.StatusClass = \"text-green\";\n course.StatusDesc = \"synced\";\n }\n });\n }\n /**\r\n * Redirect to Course Session\r\n */\n\n\n function gotoCourse(course) {\n if ($scope.type == \"ground\") {\n $location.path('/groundcourse/' + course.Id + '/' + $scope.duty.Id + \"/\" + $scope.duty.DutyDateS);\n } else if ($scope.type == \"crewroute\") {\n $location.path('/flightcourse/' + course.Id + '/' + $scope.dutyNo + '/' + $scope.dutyDay + '/' + course.FullDate);\n } else if ($scope.type == \"flight\") {\n $location.path('/flightcourse/' + course.Id + '/' + $scope.dutyNo + '/' + $scope.dutyDay + '/' + course.FullDate + '/' + Number($routeParams.flightId));\n }\n }\n }\n\n return {\n restrict: 'E',\n templateUrl: \"views/Training/training-menu.tpl.html\",\n scope: {\n type: '@',\n id: '=',\n dutyNo: '=',\n dutyDay: '='\n },\n terminal: true,\n link: link\n };\n }\n})();\n\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('TrainingSessionFactory', TrainingSessionFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name TrainingSessionFactory\r\n * @description \r\n * Add, Update, Delete and Get Training Courses.\r\n * @ngInject\r\n */\n\n function TrainingSessionFactory(IndexedDBService, CourseFactory, $http, apiUrl, GroundDutyFactory, $filter) {\n /**\r\n * Initialize Session\r\n * @memberof TrainingSessionFactory\r\n */\n function Session() {\n this.Id = null;\n }\n\n var objType = 'TrainingSessions';\n var objCallback = Session;\n var service = {\n getAll: getAll,\n getSession: getSession,\n setSession: setSession,\n updateSession: updateSession,\n getSessionTrainees: getSessionTrainees,\n submitSession: submitSession,\n remove: remove,\n authorizeTrainee: authorizeTrainee,\n getDutySessions: getDutySessions,\n applyTraineeInfoToSession: applyTraineeInfoToSession,\n releaseSession: releaseSession\n };\n /**\r\n * Get all ground training sessions\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\n\n function getAll(callback) {\n IndexedDBService.getAll(objType).then(function (results) {\n callback(results);\n });\n }\n\n ;\n /**\r\n * Get session By day and courseId\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\n\n function getSession(courseId, day, dutyId, afterRefresh, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyId]).then(function (session) {\n CourseFactory.getCourseFromStorage(courseId, function (course) {\n if (course && !course.HasLimitedInfo && course.CrewCoursePhases && course.CourseTrainees) {\n mergeCourseWithSession(course, session, dutyId, afterRefresh);\n }\n\n callback(course);\n }, errorCallback);\n })[\"catch\"](errorCallback);\n }\n\n function applyTraineeInfoToSession(course, courseId, day, dutyId, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyId]).then(function (localSession) {\n var isNewSession = false;\n\n if (!localSession) {\n localSession = {\n courseId: courseId,\n day: day,\n dutyId: dutyId,\n trainees: [],\n TraineeEligibilty: course.TraineeEligibilty,\n CourseTrainees: course.CourseTrainees\n };\n isNewSession = true;\n } else {\n localSession.TraineeEligibilty = course.TraineeEligibilty;\n localSession.CourseTrainees = course.CourseTrainees;\n }\n\n if (isNewSession) {\n addSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n } else {\n saveSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n }\n })[\"catch\"](errorCallback);\n }\n\n function getDutySessions(day, dutyId, callback) {\n IndexedDBService.getAll(objType).then(function (results) {\n results = results.filter(function (x) {\n return x.day == day && x.dutyId == dutyId;\n });\n callback(results);\n });\n }\n /**\r\n * Remove session By day,dutyID (Optional) and courseId\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\n\n\n function remove(courseId, day, dutyId, callback, errorCallback) {\n IndexedDBService.remove(objType, [day, courseId, dutyId]).then(callback)[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Get session Trainees By day and courseId\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\n\n function getSessionTrainees(courseId, day, dutyId, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyId]).then(function (session) {\n var trainees = session && session.trainees ? session.trainees : [];\n callback(trainees);\n })[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Set session\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\n\n function setSession(session, callback, errorCallback) {\n IndexedDBService.getById(objType, [session.day, session.courseId, session.dutyId]).then(function (result) {\n if (result) {\n saveSessionToStorage(session).then(callback)[\"catch\"](errorCallback);\n ;\n } else {\n addSessionToStorage(session).then(callback)[\"catch\"](errorCallback);\n }\n })[\"catch\"](errorCallback);\n }\n\n ;\n /**\r\n * Set session\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\n\n function updateSession(trainees, session, courseId, day, dutyId, callback, errorCallback) {\n IndexedDBService.getById(objType, [day, courseId, dutyId]).then(function (localSession) {\n var isNewSession = false;\n\n if (!localSession) {\n localSession = {\n courseId: courseId,\n day: day,\n dutyId: dutyId,\n trainees: []\n };\n isNewSession = true;\n } else {\n localSession.trainees = [];\n }\n\n if (session) {\n localSession.Media = session.Media;\n localSession.ReleasedPhase = session.ReleasedPhase;\n localSession.TraineeEligibilty = session.TraineeEligibilty;\n }\n\n trainees.forEach(function (trainee) {\n localSession.trainees.push(trainee);\n });\n\n if (isNewSession) {\n addSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n } else {\n saveSessionToStorage(localSession).then(callback)[\"catch\"](errorCallback);\n }\n })[\"catch\"](errorCallback);\n }\n\n function mergeCourseWithSession(course, session, dutyId, afterRefresh) {\n course.HasLimitedSession = session == undefined;\n var hasPreviousSessions = mergeSyllabusWithHistory(course.CourseTrainees, course.CrewCoursePhases);\n filterTraineesByEligibility(dutyId, course, session, afterRefresh);\n course.CrewCoursePhases.forEach(function (phase) {\n calculatePhaseStatus(phase, course);\n });\n course.selectedPhase = getSelectedPhase(course); // Calculate eligible trainees phase status\n\n course.CourseTrainees.forEach(function (trainee) {\n var traineePhase = trainee.Phases.find(function (x) {\n return x.PhaseId == course.selectedPhase.PhaseId;\n });\n\n if (traineePhase) {\n trainee.ActivePhaseStatus = traineePhase.PhaseStatus;\n } else {\n trainee.ActivePhaseStatus = \"Pending\";\n }\n\n trainee.Selectable = trainee.ActivePhaseStatus == \"InProgress\";\n }); //Filter By Role: Filter out trainees that have a flight crew role\n\n if (course.selectedPhase.FilterByRole) {\n course.CourseTrainees.filter(function (x) {\n return x.Selectable && x.PositionCode != 'CP' && x.PositionCode != 'FO';\n }).forEach(function (flightCrewTrainee) {\n flightCrewTrainee.EligibilityStatus = false;\n flightCrewTrainee.EligibilityDesc = \"InvalidRole\";\n course.NonEligibleTrainees.push(flightCrewTrainee);\n });\n } // Non InProgress trainees will be marked as NonEligible (remove further ahead trainees on multiple InProgress phases)\n\n\n course.CourseTrainees.filter(function (x) {\n return !x.Selectable;\n }).forEach(function (invalidPhaseTrainee) {\n invalidPhaseTrainee.EligibilityStatus = false;\n invalidPhaseTrainee.EligibilityDesc = \"AlreadySubmitted\";\n course.NonEligibleTrainees.push(invalidPhaseTrainee);\n });\n course.CourseTrainees = course.CourseTrainees.filter(function (x) {\n return x.EligibilityStatus;\n }); // Get trainee sessions\n\n course.CourseTrainees.forEach(function (trainee) {\n var sessionTrainee = session ? session.trainees.find(function (x) {\n return x.CrewId == trainee.CrewId;\n }) : null;\n\n if (sessionTrainee) {\n trainee.Session = sessionTrainee.Session;\n } else {\n trainee.Session = {\n Released: course.selectedPhase.ModuleType == \"Training\" ? false : true,\n CrewId: trainee.CrewId,\n Items: [],\n Absent: false,\n DayGrading: {\n Comments: null,\n Grade: null,\n Competences: []\n },\n ReleaseGrading: {\n Comments: null,\n Grade: null,\n Competences: []\n }\n };\n }\n });\n /* Set default values for release option\r\n Training Modules: 'No' release as default\r\n Check Module: 'Yes' release as default\r\n */\n\n course.ReleasedPhase = course.selectedPhase.ModuleType == \"Training\" ? false : true;\n\n if (session) {\n course.Media = session.Media;\n course.ReleasedPhase = session.ReleasedPhase;\n course.TraineeEligibilty = session.TraineeEligibilty;\n }\n }\n\n function getSelectedPhase(course) {\n var hasSelectedPhase = false;\n var phases = course.CrewCoursePhases;\n phases.forEach(function (phase, index, array) {\n phase.isFirst = index == 0;\n phase.isLast = index + 1 == array.length; // Select the first InProgress & selected phase\n\n if (!hasSelectedPhase && phase.Status == \"InProgress\" && phase.isSelected) {\n phase.Selected = true;\n hasSelectedPhase = true;\n }\n }); // Select the first InProgress phase\n\n if (!hasSelectedPhase && phases.some(function (x) {\n return x.Status == \"InProgress\";\n })) {\n phases.find(function (x) {\n return x.Status == \"InProgress\";\n }).Selected = true;\n hasSelectedPhase = true;\n }\n\n if (!hasSelectedPhase) {\n phases.find(function (x) {\n return x.isFirst;\n }).Selected = true;\n }\n\n var selectedPhase = phases.find(function (x) {\n return x.Selected;\n });\n return selectedPhase;\n }\n\n function filterTraineesByEligibility(dutyId, course, session, afterRefresh) {\n var _course$CourseTrainee;\n\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(dutyId); // Trainee Eligiblity cases\n // 1. After refresh - Save newly fetched eligibility in session\n // 2. No refresh & Session exists - Get last fetched eligibility from session\n // 3. No refresh & No session exists - Rely on previously fetched eligibility (different duty - same course)\n\n var traineeEligibility = course.TraineeEligibilty;\n\n if (!afterRefresh && session && session.TraineeEligibilty) {\n traineeEligibility = session.TraineeEligibilty;\n }\n\n if (session) session.TraineeEligibilty = traineeEligibility; //update session eligibility\n // Get ground duty trainees without any training records\n\n var trainees = getGroundCourseTrainees(groundDuty, course.Id);\n var inactiveTrainees = trainees.filter(function (x) {\n return !course.CourseTrainees.some(function (z) {\n return z.CrewId == x.CrewId;\n });\n }); //Exclude Non valid trainees\n\n var eligibleTraineeIds = Object.keys(traineeEligibility).filter(function (x) {\n return traineeEligibility[x] == \"NotStarted\" || traineeEligibility[x] == \"ValidPhase\" || traineeEligibility[x] == \"FailedCertificate\";\n }).map(Number);\n var eligibleTrainees = inactiveTrainees.filter(function (x) {\n return eligibleTraineeIds.includes(x.CrewId);\n });\n eligibleTrainees.forEach(function (trainee) {\n trainee.EligibilityStatus = true;\n });\n createNewPhaseTrainees(groundDuty, course, eligibleTrainees); // Merge eligibleTrainees (inactive) with CourseTrainees (eligible & active)\n\n course.CourseTrainees.forEach(function (trainee) {\n trainee.EligibilityStatus = true;\n });\n\n (_course$CourseTrainee = course.CourseTrainees).push.apply(_course$CourseTrainee, _toConsumableArray(eligibleTrainees)); // Non eligible trainees\n\n\n var nonEligibleTrainees = inactiveTrainees.filter(function (x) {\n return !eligibleTraineeIds.includes(x.CrewId);\n });\n course.NonEligibleTrainees = nonEligibleTrainees;\n nonEligibleTrainees.forEach(function (trainee) {\n trainee.EligibilityStatus = false;\n trainee.EligibilityDesc = traineeEligibility[trainee.CrewId];\n }); // Result:\n // CourseTrainees = eligible trainees (active or new)\n // Non EligibleTrainees\n }\n /**\r\n * Create first phase foreach trainee\r\n * @param {object} groundDuty \r\n * @param {object} course \r\n * @param {array} trainees Eligible trainees that haven't yet started training\r\n */\n\n\n function createNewPhaseTrainees(groundDuty, course, trainees) {\n //Match GroundDutyNos with PhaseDutyNos\n var crewCoursePhaseDutyNos = [];\n var groundDutyTraineeDutyNos = [];\n course.CrewCoursePhases.forEach(function (coursePhase) {\n crewCoursePhaseDutyNos = crewCoursePhaseDutyNos.concat(coursePhase.GroundDutyCodes);\n });\n groundDuty.Trainees.forEach(function (relatedDuty) {\n groundDutyTraineeDutyNos.push(relatedDuty.GroundDutyNo.toString());\n });\n var relatedDutyNos = crewCoursePhaseDutyNos.filter(function (x) {\n return groundDutyTraineeDutyNos.includes(x);\n });\n var relatedPhases = course.CrewCoursePhases.filter(function (x) {\n return x.GroundDutyCodes.some(function (gdc) {\n return relatedDutyNos.includes(gdc);\n });\n }); //From related phases, select first in order\n\n relatedPhases = $filter('orderBy')(relatedPhases, 'OrderNo');\n var firstPhase = relatedPhases[0];\n trainees.forEach(function (trainee) {\n trainee.Phases = [{\n PhaseId: firstPhase.PhaseId,\n PhaseStatus: \"InProgress\",\n RepeatRequestedItems: [],\n isSelected: true //selectedPhase\n\n }];\n });\n }\n\n function getGroundCourseTrainees(groundDuty, courseId) {\n var trainees = [];\n groundDuty.RelatedGroundDuties.filter(function (x) {\n return x.Courses && x.Courses.map(function (course) {\n return course.CourseId;\n }).includes(courseId);\n }).forEach(function (item) {\n item.CrewMembers.forEach(function (crewMember) {\n var trainee = {\n AimsId: crewMember.AIMS_ID,\n CrewId: crewMember.Id,\n Name: crewMember.Name,\n PositionCode: crewMember.PositionCode\n };\n trainees.push(trainee);\n });\n });\n return trainees;\n }\n\n function calculatePhaseStatus(phase, course) {\n course.CourseTrainees.forEach(function (trainee) {\n var traineePhase = trainee.Phases.find(function (x) {\n return x.PhaseId == phase.PhaseId;\n });\n\n if (traineePhase && traineePhase.PhaseStatus == \"InProgress\") {\n phase.Status = \"InProgress\";\n } else if (!traineePhase && phase.Status != \"InProgress\") {\n phase.Status = \"Pending\";\n } else if (traineePhase && traineePhase.PhaseStatus == \"Completed\" && phase.Status != \"InProgress\") {\n phase.Status = \"Completed\";\n } //Selected phase, If at least one trainee has it selected\n\n\n if (traineePhase && !phase.isSelected) {\n phase.isSelected = traineePhase.isSelected;\n }\n });\n }\n\n function mergeSyllabusWithHistory(trainees, phases) {\n var flatSullabusItems = [];\n trainees.forEach(function (trainee) {\n trainee.Phases.forEach(function (phase) {\n phase.Sessions.forEach(function (session) {\n session.Items.forEach(function (item) {\n var flatItem = createFlatHistorySullabusItem(trainee, phase, session, item);\n flatSullabusItems.push(flatItem);\n });\n });\n });\n });\n phases.filter(function (x) {\n return x.Syllabus;\n }).forEach(function (phase, index, array) {\n phase.Syllabus.SyllabusItems.forEach(function (syllabusItem) {\n syllabusItem.History = flatSullabusItems.filter(function (item) {\n return item.ItemId == syllabusItem.Id;\n });\n });\n });\n var hasPreviousSessions = flatSullabusItems.length > 0;\n return hasPreviousSessions;\n }\n\n function createFlatHistorySullabusItem(trainee, phase, session, item) {\n var flatItem = {\n CrewId: trainee.CrewId,\n PhaseId: phase.PhaseId,\n SessionId: session.SessionId,\n SessionComments: session.SessionComments,\n SubmissionDate: item.SubmissionDate,\n RepeatRequired: item.RepeatRequired,\n Tries: item.Tries,\n ItemId: item.SyllabusItemId,\n Grade: session.Grade,\n GradeType: session.GradeType,\n InstructorName: session.InstructorName,\n InstructorAimsId: session.InstructorAimsId\n };\n return flatItem;\n }\n /**\r\n * Add Session to Storage\r\n * @memberof TrainingSessionFactory\r\n * @param {object} Session\r\n */\n\n\n function addSessionToStorage(session) {\n return IndexedDBService.add(objType, session);\n }\n\n ;\n /**\r\n * Update Session to Storage\r\n * @memberof TrainingSessionFactory\r\n * @param {object} Session\r\n */\n\n function saveSessionToStorage(session) {\n return IndexedDBService.put(objType, session);\n }\n\n ;\n\n function submitSession(submittedSession, callback) {\n var traingingApiURL = apiUrl + '/Training/SubmitTraining';\n return $http.post(traingingApiURL, submittedSession, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n /**\r\n * Authorize Trainee for submission\r\n * @param {string} credentials Trainee's password, username, crewId, position\r\n * @param {function} callback \r\n * @param {function} errorCallback \r\n */\n\n\n function authorizeTrainee(credentials, callback, errorCallback) {\n return $http.post(apiUrl + '/Training/AuthorizeTrainee', credentials, {\n 'Content-Type': 'application/json'\n }).then(callback)[\"catch\"](errorCallback);\n }\n\n function releaseSession(submittedSessions, callback, errorCallback) {\n var traingingApiURL = apiUrl + '/Training/ReleaseSession';\n return $http.post(traingingApiURL, submittedSessions, {\n 'Content-Type': 'application/json'\n }).then(callback)[\"catch\"](errorCallback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('DebugCtrl', DebugCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name DebugCtrl\r\n * @description \r\n * Manage Debug view\r\n * @ngInject\r\n */\n\n function DebugCtrl($location, $scope, UserFactory, DebugFactory, localStorageMD5Service) {\n $scope.isSecure = UserFactory.isSecure();\n $scope.adminkey = \"\";\n $scope.authorized = false;\n\n $scope.checkAuthorized = function () {\n var verify = localStorageMD5Service.md5hash($scope.adminkey);\n DebugFactory.CheckAuthorized(verify, function (responseData) {\n if ($scope.authorized != responseData.data.data) {\n $scope.authorized = responseData.data.data;\n $scope.refreshStoredValues();\n }\n })[\"catch\"](function (error) {\n $scope.authorized = responseData.Data;\n console.error('Wrong Password', error.status, error.statusText);\n });\n }; // show logged user info\n\n\n var user = UserFactory.getUser();\n $scope.logged_user_info = \"-user has not logged in-\";\n if (user) $scope.logged_user_info = user.aimsId + ' - ' + user.name;\n $scope.storedValues = [];\n $scope.addKeyName = null;\n $scope.updateAll = updateAll;\n $scope.refreshStoredValues = refreshStoredValues;\n $scope.add = add;\n $scope.update = update;\n $scope[\"delete\"] = deleteItem;\n $scope.exit = exit;\n /**\r\n * Update all the local storage \r\n * @memberof DebugCtrl\r\n */\n\n function updateAll() {\n try {\n var items = JSON.parse($scope.updateAllJson);\n\n for (var i = 0; i < items.length; i++) {\n var obj = null;\n if (items[i].value != '') obj = angular.fromJson(items[i].value);\n localStorageMD5Service.set(items[i].key, obj);\n }\n\n $scope.refreshStoredValues();\n } catch (e) {\n alert('Error: ' + e.message || e.errorMessage);\n }\n }\n /**\r\n * Refresh values from localstorage\r\n * @memberof DebugCtrl\r\n */\n\n\n function refreshStoredValues() {\n var values = [];\n\n if ($scope.authorized) {\n var keys = localStorageMD5Service.keys();\n\n if (keys) {\n var key, value, sizeActual, error;\n\n for (var i = 0; i < keys.length; i++) {\n key = keys[i];\n\n try {\n value = localStorageMD5Service.get(key);\n value = angular.toJson(value);\n sizeActual = localStorageMD5Service.usedSize(key);\n error = null;\n } catch (e) {\n error = e.message || e.errorMessage;\n }\n\n values.push({\n key: key,\n value: value,\n error: error,\n size: value ? value.length : 0,\n sizeActual: sizeActual\n });\n }\n }\n }\n\n $scope.storedValues = values;\n }\n /**\r\n * Add a new local storage key\r\n * @memberof DebugCtrl\r\n */\n\n\n function add() {\n try {\n var key = $scope.addKeyName;\n if (!key || key == '') return false;\n var keys = localStorageMD5Service.keys();\n\n if (keys && keys.indexOf(key) > 0) {\n alert('Key exists!');\n return false;\n }\n\n localStorageMD5Service.set(key, [\"empty\"]);\n $scope.refreshStoredValues();\n $scope.addKeyName = null;\n } catch (e) {\n alert('Error: ' + e.message || e.errorMessage);\n }\n }\n /**\r\n * Update an existing local storage key\r\n * @memberof DebugCtrl\r\n * @param {object} item\r\n */\n\n\n function update(item) {\n try {\n var obj = null;\n if (item.value != '') obj = angular.fromJson(item.value);\n localStorageMD5Service.set(item.key, obj);\n $scope.refreshStoredValues();\n } catch (e) {\n alert('Error: ' + e.message || e.errorMessage);\n }\n }\n /**\r\n * delete an existing local storage key\r\n * @memberof DebugCtrl\r\n * @param {object} item\r\n */\n\n\n function deleteItem(item) {\n if (confirm('Confirm deletion of key ' + item.key)) {\n localStorageMD5Service.remove(item.key);\n $scope.refreshStoredValues();\n }\n }\n /**\r\n * Redirect to main Menu\r\n * @memberof DebugCtrl\r\n */\n\n\n function exit() {\n $location.path(\"/\");\n }\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.factory('DebugFactory', DebugFactory);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name DebugFactory\r\n * @description \r\n * Authorize check from API ...\r\n * @ngInject\r\n */\n\n function DebugFactory(GenericService, $http, $q, apiUrl, LogService) {\n /**\r\n * Initialize Debug\r\n * @memberof DebugFactory\r\n */\n var service = {\n CheckAuthorized: CheckAuthorized\n };\n\n function CheckAuthorized(value, callback) {\n return $http.get(apiUrl + '/debug/CheckAuthorized/' + value, {\n 'Content-Type': 'application/json'\n }).then(callback);\n }\n\n return service;\n }\n})();\n\"use strict\";\n\n(function () {\n 'use strict';\n\n a3_pilot_reports.controller('ResetDeviceCtrl', ResetDeviceCtrl);\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ResetDeviceCtrl\r\n * @description \r\n * Manage Reset view\r\n * @ngInject\r\n */\n\n function ResetDeviceCtrl($location, $route, $scope, $log, DataCleanerFactory, UserFactory, localStorageMD5Service) {\n $scope.isSecure = UserFactory.isSecure(); // show logged user info\n\n var user = UserFactory.getUser();\n $scope.logged_user_info = \"-user has not logged in-\";\n if (user) $scope.logged_user_info = user.aimsId + ' - ' + user.name;\n $scope.resetDevice = resetDevice;\n $scope.cancelReset = cancelReset;\n /**\r\n * Reset Device storage\r\n * @memberof ResetDeviceCtrl\r\n */\n\n function resetDevice() {\n DataCleanerFactory.deleteAllData();\n bootbox.alert(\"Your device has been reset.\", function () {\n $location.path(\"/login\");\n $scope.$apply();\n });\n }\n /**\r\n * Cancel Reset and go to main page.\r\n * @memberof ResetDeviceCtrl\r\n */\n\n\n function cancelReset() {\n $location.path(\"/\");\n }\n }\n})();","//***Modal Dialog for Application Updates - non angular **/\r\nvar modalUpdates;\r\nvar isDownloanding=false;\r\nvar isCheckForUpdate=false;\r\n(function() {\r\n\tif ('applicationCache' in window && !('serviceWorker' in navigator)) {\r\n\t\tmodalUpdates = $('.modal-updating').modal({backdrop: 'static', keyboard: true, show: false});\r\n\t\tmodalUpdates.show = function(){\r\n\t\t\tmodalUpdates.removeClass('update-success');\r\n\t\t\tmodalUpdates.find('.progress').show();\r\n\t\t\tmodalUpdates.find('.message-success').hide();\r\n\t\t\tmodalUpdates.find('.message-danger').hide();\r\n\t\t\tmodalUpdates.find('.message-no-update').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-retry').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-close').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-ok').hide();\r\n\t\t\tmodalUpdates.modal('show');\r\n\t\t}\r\n\t\tmodalUpdates.hide = function(){\r\n\t\t\tmodalUpdates.modal('hide');\r\n\t\t}\r\n\t\tmodalUpdates.success = function(){\r\n\t\t\tmodalUpdates.find('.progress').hide();\r\n\t\t\tmodalUpdates.find('.message-success').show(); \r\n\t\t\tmodalUpdates.find('.message-no-update').hide();\r\n\t\t\tmodalUpdates.find('.message-danger').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-close').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-ok').show();\r\n\t\t\tmodalUpdates.addClass('update-success');\r\n\t\t\tsetTimeout(function(){modalUpdates.modal('hide');}, 2000);\r\n\t\t}\r\n\t\tmodalUpdates.noUpdate = function(){\r\n\t\t\tmodalUpdates.show();\r\n\t\t\tmodalUpdates.find('.progress').hide();\r\n\t\t\tmodalUpdates.find('.message-success').hide();\r\n\t\t\tmodalUpdates.find('.message-danger').hide();\r\n\t\t\tmodalUpdates.find('.message-no-update').show();\r\n\t\t\tmodalUpdates.find('.btn-update-retry').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-close').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-ok').show();\r\n\t\t\tisCheckForUpdate=false;\r\n\t\t}\r\n\t\tmodalUpdates.failure = function(errorMessage){\r\n\t\t\tmodalUpdates.show();\r\n\t\t\tmodalUpdates.find('.progress').hide();\r\n\t\t\tmodalUpdates.find('.message-success').hide();\r\n\t\t\tmodalUpdates.find('.message-danger').show();\r\n\t\t\tmodalUpdates.find('.message-no-update').hide();\r\n\t\t\tmodalUpdates.find('.btn-update-close').show();\r\n\t\t\tmodalUpdates.find('.btn-update-ok').hide();\r\n\r\n\t\t\tif (errorMessage && errorMessage!=''){\r\n\t\t\t\tmodalUpdates.find('.update-error').text(errorMessage);\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\tmodalUpdates.find('.update-error').text('');\r\n\t\t\t}\r\n\t\t}\r\n\t\tmodalUpdates.on('hidden.bs.modal', function (e) {\r\n\t\t\tvar b = modalUpdates.hasClass('update-success');\r\n\t\t\tif (b) location.reload(true);\r\n\t\t})\r\n\t}\r\n\r\n}).call(this);\r\n\r\n\r\n//** ApplicationCache Events & Actions **//\r\n(function() {\r\n\t////////////////////////////////////////////////////index scripts (cache)////////////////////////////////////////////////////\r\n\tif ('applicationCache' in window && !('serviceWorker' in navigator)) {\r\n\t\t// Convenience array of status values\r\n\t\t\r\n\t\tvar cacheHandler = function(){\r\n\t\t}\r\n\t\t\r\n\t\tcacheHandler.cacheStatusValues = [];\r\n\t\tcacheHandler.cacheStatusValues[0] = 'uncached';\r\n\t\tcacheHandler.cacheStatusValues[1] = 'idle';\r\n\t\tcacheHandler.cacheStatusValues[2] = 'checking';\r\n\t\tcacheHandler.cacheStatusValues[3] = 'downloading';\r\n\t\tcacheHandler.cacheStatusValues[4] = 'updateready';\r\n\t\tcacheHandler.cacheStatusValues[5] = 'obsolete';\r\n\r\n\t\tcacheHandler.onDownloading = function (e) {\r\n isDownloanding=true;\r\n\t\t\tmodalUpdates.show();\r\n\t\t\tcacheHandler.logEvent(e);\r\n\t\t}\r\n\t\tcacheHandler.onCached = function (e) {\r\n\t\t\tmodalUpdates.hide();\r\n\t\t\tcacheHandler.logEvent(e);\r\n\t\t}\r\n\t\tcacheHandler.onChecking = function (e) {\r\n\t\t\t//ShowWaitDialog();\r\n\t\t\tcacheHandler.logEvent(e);\r\n\t\t}\r\n\t\tcacheHandler.onProgress = function (e){\r\n\t\t}\r\n\t\tcacheHandler.onObsolete = function (e){\r\n\t\t}\r\n \r\n\t\tcacheHandler.onError = function (e) {\r\n\t\t\t//debugger;\r\n\t\t\tvar message = \"Could not download application updates due to an unexpected error.\\n\" + \r\n\t\t\t \"make sure that cache.manifest is being served with MIME type: text/cache-manifest\";\r\n\t\t\t//actual error message if any\r\n\t\t\tif (e.message) message = e.message;\r\n\t\t\tconsole.error(message);\r\n\t\t\t//hide update dialog if visible\r\n if(isDownloanding){\r\n modalUpdates.failure(message);\r\n }else{\r\n modalUpdates.hide();\r\n }\r\n\t\t}\r\n \r\n\t\tcacheHandler.onNoUpdate = function (e) {\r\n if(isCheckForUpdate){\r\n modalUpdates.noUpdate(); \r\n }else{\r\n modalUpdates.hide();\r\n }\r\n isDownloanding=false;\r\n\t\t\tcacheHandler.logEvent(e);\r\n\t\t}\r\n\t\tcacheHandler.onUpdateReady = function (e) {\r\n\t\t\ttry { cache.swapCache(); } catch (e) { }\r\n\t\t\tcacheHandler.logEvent(e);\r\n isDownloanding=false;\r\n\t\t\tmodalUpdates.success();\r\n\t\t\t//location.reload(true);\r\n\t\t}\r\n\t\t// Log every event to the console\r\n\t\tcacheHandler.logEvent = function (e) {\r\n\t\t\t/*\r\n\t\t\tvar status, type, message; //online, \r\n\t\t\t//online = (navigator.online) ? 'yes' : 'no';\r\n\t\t\tstatus = cacheHandler.cacheStatusValues[cache.status];\r\n\t\t\ttype = e.type;\r\n\t\t\tmessage = '';//'online: ' + online;\r\n\t\t\tmessage += 'CACHE: event: ' + type;\r\n\t\t\tmessage += ', status: ' + status;\r\n\t\t\tif (type == 'error' && navigator.online) {\r\n\t\t\t\tmessage += ' (prolly a syntax error in manifest)';\r\n\t\t\t}\r\n\t\t\tconsole.log(message);\r\n\t\t\t*/\r\n\t\t}\r\n\r\n\t\tvar cache = window.applicationCache;\r\n\t\tcache.addEventListener('cached', cacheHandler.onCached, false);\r\n\t\tcache.addEventListener('checking', cacheHandler.onChecking, false);\r\n\t\tcache.addEventListener('downloading', cacheHandler.onDownloading, false);\r\n\t\tcache.addEventListener('error', cacheHandler.onError, false);\r\n\t\t//cache.addEventListener('error', cacheHandler.logEvent, false);\r\n\t\tcache.addEventListener('noupdate', cacheHandler.onNoUpdate, false);\r\n\t\tcache.addEventListener('obsolete', cacheHandler.onObsolete, false);\r\n\t\tcache.addEventListener('progress', cacheHandler.onProgress, false);\r\n\t\tcache.addEventListener('updateready', cacheHandler.onUpdateReady, false);\r\n\t} \r\n \r\n $('#update-error-btn').click(function(){\r\n var alert=$('.hidden-update-error');\r\n if(alert.hasClass('hidden')){\r\n alert.removeClass('hidden');\r\n $('#update-error-btn').text(\"show less\");\r\n }\r\n else{\r\n alert.addClass('hidden');\r\n $('#update-error-btn').text(\"show more\");\r\n } \r\n });\r\n \r\n $('body').on('click', '#update-check-btn',function(){\r\n isCheckForUpdate=true;\r\n var url=location.origin;\r\n $.ajax({ type: \"GET\",\r\n url : url,\r\n cache:false,\r\n success: function(){ \r\n //get cache\r\n var cache = window.applicationCache;\r\n // Update the user's cache\r\n if (cache!=null || cache!=undefined){\r\n cache.update();\r\n }\r\n }/*,\r\n error: function(){ \r\n console.log('error');\r\n }*/\r\n });\r\n });\r\n \r\n}).call(this);"," $(function () {\r\n\t\tangular.bootstrap(document, ['a3.pilot.reports']);\r\n});\r\n\r\nvar a3_pilot_reports = angular.module('a3.pilot.reports', [\r\n //angular modules\r\n 'ngSanitize',\r\n 'ngRoute',\r\n 'ngTouch',\r\n \r\n //3rd party modules\r\n 'angular-md5',\r\n 'LocalStorageModule',\r\n 'ui.bootstrap',\r\n 'nya.bootstrap.select',\r\n 'ui.toggle',\r\n 'ui.sortable',\r\n \r\n //Our modules\r\n 'LocalStorageMD5Module',\r\n 'MyDirectives'\r\n]);","(function() {\r\n 'use strict';\r\n \r\n \r\n// setup routing\r\na3_pilot_reports.config(routeConfig);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name routeConfig\r\n * @description \r\n * Route configuration\r\n * @ngInject\r\n */ \r\nfunction routeConfig($routeProvider) {\r\n\t$routeProvider\r\n\t\t.when('/', {\r\n\t\t\tcontroller:'CalendarCtrl',\r\n\t\t\ttemplateUrl:'./views/calendar.html'\r\n\t\t})\r\n\t\t.when('/login', {\r\n\t\t\tcontroller:'LoginCtrl',\r\n\t\t\ttemplateUrl:'./views/login.html'\r\n\t\t})\r\n\t\t.when('/flightinfo/:flightId', {\r\n\t\t\t\tcontroller: 'FlightInfoCtrl',\r\n\t\t\t\ttemplateUrl: 'views/flight-info.html',\r\n reloadOnSearch: false\r\n\t\t})\r\n\t\t.when('/report/:reportId', {\r\n\t\t\tcontroller:'ReportCtrl',\r\n\t\t\ttemplateUrl:'./views/report.html'\r\n\t\t})\r\n\t\t.when('/report/:reportId/:flightId', {\r\n\t\t\tcontroller:'ReportCtrl',\r\n\t\t\ttemplateUrl:'./views/report.html'\r\n\t\t})\r\n\t\t.when('/pdf/:reportId', {\r\n\t\t\tcontroller:'ReportCtrl',\r\n\t\t\ttemplateUrl:'./views/report.html'\r\n\t\t})\r\n\t\t.when('/pax/:flightId', {\r\n\t\t\tcontroller: 'PaxCtrl',\r\n\t\t\ttemplateUrl: 'views/pax.html'\r\n\t\t})\r\n\t\t.when('/addflight', {\r\n\t\t\tcontroller:'AddFlightCtrl',\r\n\t\t\ttemplateUrl:'./views/addflight.html'\r\n\t\t})\r\n\t\t.when('/reset', {\r\n\t\t\tcontroller:'ResetDeviceCtrl',\r\n\t\t\ttemplateUrl:'./views/reset.html'\r\n\t\t})\r\n\t\t.when('/messages/:flightId', {\r\n\t\t\t\tcontroller: 'MessageCtrl',\r\n\t\t\t\ttemplateUrl: 'views/messages.html'\r\n\t\t })\r\n\t\t.when('/messages/', {\r\n\t\t\t\tcontroller: 'MessageCtrl',\r\n\t\t\t\ttemplateUrl: 'views/messages.html'\r\n\t\t })\r\n\t\t.when('/debug', {\r\n\t\t\tcontroller:'DebugCtrl',\r\n\t\t\ttemplateUrl:'./views/debug.html'\r\n\t\t})\r\n\t\t.when('/memos/:filter', {\r\n\t\t\tcontroller: 'MemosCtrl',\r\n\t\t\ttemplateUrl: 'views/Memos/memos.html'\r\n\t\t})\r\n\t\t.when('/memos', {\r\n\t\t\tcontroller: 'MemosCtrl',\r\n\t\t\ttemplateUrl: 'views/Memos/memos.html'\r\n\t\t})\r\n .when('/ticket', {\r\n\t\t\tcontroller: 'TicketCtrl',\r\n\t\t\ttemplateUrl: 'views/ticket.html'\r\n\t\t})\r\n\t\t.when('/bucket', {\r\n controller: 'BucketCtrl',\r\n templateUrl: 'views/Bucket/bucketCalendar.html'\r\n })\r\n\t\t.when('/bucketDay/:dutyId', {\r\n controller: 'BucketDayCtrl',\r\n templateUrl: 'views/Bucket/bucketDay.html'\r\n })\r\n .when('/leaverequest', {\r\n controller: 'LeaveRequestCtrl',\r\n templateUrl: 'views/LeaveRequest/leaveRequest.html'\r\n })\r\n .when('/groundDuty/:groundDutyId', {\r\n controller: 'GroundDutyCtrl',\r\n templateUrl: 'views/GroundDuty/groundDuty-info.html'\r\n })\r\n\t\t.when('/crewRoute/:dutyNo/:dutyDay', {\r\n\t\t\tcontroller: 'CrewRouteCtrl',\r\n\t\t\ttemplateUrl: 'views/CrewRoute/crew-route-info.html',\r\n\t\t})\r\n\t\t.when('/reportsHistory/:reportId/:flightId?/:reportType', {\r\n\t\t\tcontroller: 'ReportsHistoryCtrl',\r\n\t\t\ttemplateUrl: 'views/reportsHistory.html'\r\n\t\t})\r\n\t\t.when('/flightcourse/:courseId/:dutyNo/:dutyDay/:date',{\r\n controller: 'FlightCourseCtrl',\r\n templateUrl: 'views/Training/flightCourse.html'\r\n })\r\n .when('/flightcourse/:courseId/:dutyNo/:dutyDay/:date/:flightId',{\r\n controller: 'FlightCourseCtrl',\r\n templateUrl: 'views/Training/flightCourse.html'\r\n })\r\n\t\t .when('/groundcourse/:courseId/:dutyId/:date',{\r\n controller: 'GroundCourseCtrl',\r\n templateUrl: 'views/Training/groundCourse.html'\r\n })\r\n\t\t .when('/groundHistory/:courseId/:dutyId/:date/:phaseId',{\r\n controller: 'ModuleHistoryCtrl',\r\n\t\t\ttemplateUrl: 'views/Training/moduleHistory.html'\r\n })\r\n\t\t .when('/flightHistory/:courseId/:dutyNo/:dutyDay/:date/:phaseId',{\r\n controller: 'ModuleHistoryCtrl',\r\n\t\t\ttemplateUrl: 'views/Training/moduleHistory.html'\r\n })\r\n\t\t.when('/safetyreport/flightcrewreport/:flightId',{\r\n\t\t\tcontroller: 'SafetyCtrl',\r\n\t\t\ttemplateUrl: 'views/Safety/flightCrewReport.html'\r\n\t\t})\r\n\t\t.when('/safetyreport/fatiguereport/:flightId',{\r\n\t\t\tcontroller: 'FatigueCtrl',\r\n\t\t\ttemplateUrl: 'views/Safety/fatigueReport.html'\r\n\t\t})\r\n \r\n\t\t.otherwise({\r\n\t\t\tredirectTo:'/'\r\n\t\t})\r\n \r\n }\r\n \r\n})(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.run(runBlock);\r\n\r\n/* @ngInject */ \r\nfunction runBlock($rootScope, $timeout, $location, UserFactory, UserTokenFactory,PilotReportLocalEditFactory,SettingsMain,$anchorScroll,SWUpdateService,LogService) {\r\n\t//make sure that each route change validates that the user is still logged in\r\n\tvar valid=['/login','/reset','/debug','/ticket'];\r\n $rootScope.$on('$routeChangeStart', function (event, next, current) {\r\n if (valid.indexOf($location.$$path) < 0 && !UserFactory.isLoggedIn()) {\r\n event.preventDefault();\r\n $location.path('/login');\r\n }\r\n\r\n //START - SERVICE WORKERS\r\n if ('serviceWorker' in navigator) {\r\n SWUpdateService.initialize();\r\n \r\n navigator.serviceWorker.getRegistration().then(function(registration) {\r\n $rootScope.SWRegistration = registration;\r\n });\r\n\r\n SWUpdateService.checkUpdates($rootScope.SWRegistration);\r\n }\r\n //END - SERVICE WORKERS\r\n \r\n $anchorScroll.yOffset = 100;\r\n if(!current || !current.$$route || current.$$route.controller != next.$$route.controller){\r\n //Check if temp report of any kind exists\r\n var editingPage = SettingsMain.getEditingPage();\r\n SettingsMain.setEditingPage(null);\r\n \r\n if (editingPage == 'report') \r\n {\r\n // check if a temp report exists in local storage\r\n if (PilotReportLocalEditFactory.getPilotReportLocalEditFromTemp() != null) {\r\n $location.path(\"report/temp\");\r\n }\r\n } \r\n }\r\n \r\n });\r\n \r\n $(\"body\").on(\"click\",\".memo-body a\", function(){\r\n var link = $(this).attr(\"href\");\r\n if (link && link.indexOf(\"surveymonkey\")>0){\r\n LogService.debug(link);\r\n }\r\n \r\n })\r\n \r\n $rootScope.idbSupported = (\"indexedDB\" in window);\r\n $rootScope.isOffline = !window.navigator.onLine;\r\n \r\n window.addEventListener('offline', function (e) { $timeout($rootScope.isOffline = !window.navigator.onLine); });\r\n window.addEventListener('online', function (e) { $timeout($rootScope.isOffline = !window.navigator.onLine); });\r\n\r\n\t//maintain the user token, outside the localStorage, needed for submitting js errors\r\n\tvar user = UserFactory.getUser();\r\n\tif (user && user.token) UserTokenFactory.setToken(user.token);\r\n\telse UserTokenFactory.setToken('');\r\n};\r\n\r\n \r\n })(); ","(function () {\r\n// Warning!!! This an auto generated file. Any Changes will be lost. If u want to add or edit go to config.json \r\n\r\na3_pilot_reports.constant(\"liveVersion\", true);\r\n\r\na3_pilot_reports.constant(\"defaultCalendarDate\", null);\r\n\r\na3_pilot_reports.constant(\"defaultBucketDate\", null);\r\n\r\na3_pilot_reports.constant(\"aircraftLateArrivalReportId\", 169);\r\n\r\na3_pilot_reports.constant(\"inadequateGroundTimeReportId\", 170);\r\n\r\na3_pilot_reports.constant(\"apiUrl\", \"https://flightloguat.aegeanair.com/api/v2.0\");\r\n\r\na3_pilot_reports.constant(\"ssrCodes\", [\n\t{\n\t\t\"code\": \"AOXY\",\n\t\t\"description\": \"Airline Supplied Oxygen\"\n\t},\n\t{\n\t\t\"code\": \"AVIH\",\n\t\t\"description\": \"Animal in Hold\"\n\t},\n\t{\n\t\t\"code\": \"AVML\",\n\t\t\"description\": \"Vegetarian Hindu meal\"\n\t},\n\t{\n\t\t\"code\": \"BBNL\",\n\t\t\"description\": \"Baby meal request\"\n\t},\n\t{\n\t\t\"code\": \"BIKE\",\n\t\t\"description\": \"Request for carriage of bicycle\"\n\t},\n\t{\n\t\t\"code\": \"BLML\",\n\t\t\"description\": \"Bland meal request\"\n\t},\n\t{\n\t\t\"code\": \"BLND\",\n\t\t\"description\": \"Blind passenger information\"\n\t},\n\t{\n\t\t\"code\": \"CBBG\",\n\t\t\"description\": \"Bulky cabin baggage request\"\n\t},\n\t{\n\t\t\"code\": \"CHLD\",\n\t\t\"description\": \"Child information\"\n\t},\n\t{\n\t\t\"code\": \"CHML\",\n\t\t\"description\": \"Child Meal Request\"\n\t},\n\t{\n\t\t\"code\": \"DBML\",\n\t\t\"description\": \"Diabetic meal request\"\n\t},\n\t{\n\t\t\"code\": \"DEAF\",\n\t\t\"description\": \"Deaf passenger information\"\n\t},\n\t{\n\t\t\"code\": \"DEPA\",\n\t\t\"description\": \"Accompanied Deportee Information\"\n\t},\n\t{\n\t\t\"code\": \"DEPU\",\n\t\t\"description\": \"Deportee unaccompanied\"\n\t},\n\t{\n\t\t\"code\": \"DHCS\",\n\t\t\"description\": \"Deadhead crew seating\"\n\t},\n\t{\n\t\t\"code\": \"DPNA\",\n\t\t\"description\": \"Disabled passenger needing assistance\"\n\t},\n\t{\n\t\t\"code\": \"EMIG\",\n\t\t\"description\": \"Emigrant\"\n\t},\n\t{\n\t\t\"code\": \"ESAN\",\n\t\t\"description\": \"Passenger with emotional support/psychiatric\"\n\t},\n\t{\n\t\t\"code\": \"ESCD\",\n\t\t\"description\": \"Passenger escorting deportee\"\n\t},\n\t{\n\t\t\"code\": \"EXST\",\n\t\t\"description\": \"Request for extra seat\"\n\t},\n\t{\n\t\t\"code\": \"FAMS\",\n\t\t\"description\": \"Family seating\"\n\t},\n\t{\n\t\t\"code\": \"FPML\",\n\t\t\"description\": \"Fruit platter meal request\"\n\t},\n\t{\n\t\t\"code\": \"FRED\",\n\t\t\"description\": \"Meal and assist request\"\n\t},\n\t{\n\t\t\"code\": \"GFML\",\n\t\t\"description\": \"Gluten intolerant meal request\"\n\t},\n\t{\n\t\t\"code\": \"GPST\",\n\t\t\"description\": \"Group seating request\"\n\t},\n\t{\n\t\t\"code\": \"HAJJ\",\n\t\t\"description\": \"HAJJ Passengers\"\n\t},\n\t{\n\t\t\"code\": \"HNML\",\n\t\t\"description\": \"Hindu meal request\"\n\t},\n\t{\n\t\t\"code\": \"INAD\",\n\t\t\"description\": \"Inadmissable\"\n\t},\n\t{\n\t\t\"code\": \"INFT\",\n\t\t\"description\": \"Infant information\"\n\t},\n\t{\n\t\t\"code\": \"KSML\",\n\t\t\"description\": \"Kosher meal request\"\n\t},\n\t{\n\t\t\"code\": \"LCML\",\n\t\t\"description\": \"Low calorie meal request\"\n\t},\n\t{\n\t\t\"code\": \"LFML\",\n\t\t\"description\": \"Low fat meal request\"\n\t},\n\t{\n\t\t\"code\": \"LSML\",\n\t\t\"description\": \"Low salt meal request\"\n\t},\n\t{\n\t\t\"code\": \"MAAS\",\n\t\t\"description\": \"Meal and assist request\"\n\t},\n\t{\n\t\t\"code\": \"MEDA\",\n\t\t\"description\": \"Medical assistance information\"\n\t},\n\t{\n\t\t\"code\": \"MEQT\",\n\t\t\"description\": \"Medical equipment\"\n\t},\n\t{\n\t\t\"code\": \"MOML\",\n\t\t\"description\": \"Halaal meal request\"\n\t},\n\t{\n\t\t\"code\": \"NFML\",\n\t\t\"description\": \"No fish meal request\"\n\t},\n\t{\n\t\t\"code\": \"NLML\",\n\t\t\"description\": \"Low lactose meal request\"\n\t},\n\t{\n\t\t\"code\": \"NOML\",\n\t\t\"description\": \"Meal on board not required\"\n\t},\n\t{\n\t\t\"code\": \"PETC\",\n\t\t\"description\": \"Pet in cabin request\"\n\t},\n\t{\n\t\t\"code\": \"POXY\",\n\t\t\"description\": \"Passenger own oxygen\"\n\t},\n\t{\n\t\t\"code\": \"RVML\",\n\t\t\"description\": \"Vegetarian raw meal request\"\n\t},\n\t{\n\t\t\"code\": \"SEML\",\n\t\t\"description\": \"Seafood meal request\"\n\t},\n\t{\n\t\t\"code\": \"SFML\",\n\t\t\"description\": \"Seafood meal request\"\n\t},\n\t{\n\t\t\"code\": \"SPML\",\n\t\t\"description\": \"Special meal request\"\n\t},\n\t{\n\t\t\"code\": \"SVAN\",\n\t\t\"description\": \"Passenger with service animal in cabin\"\n\t},\n\t{\n\t\t\"code\": \"UMNR\",\n\t\t\"description\": \"Unaccompanied minor information\"\n\t},\n\t{\n\t\t\"code\": \"VGML\",\n\t\t\"description\": \"Vegetarian vegan meal request\"\n\t},\n\t{\n\t\t\"code\": \"VJML\",\n\t\t\"description\": \"Vegetarian Jain meal request\"\n\t},\n\t{\n\t\t\"code\": \"VLML\",\n\t\t\"description\": \"Vegetarian Lacto-Ovo meal request\"\n\t},\n\t{\n\t\t\"code\": \"VOML\",\n\t\t\"description\": \"Vegetarian Oriental meal request\"\n\t},\n\t{\n\t\t\"code\": \"WCBD\",\n\t\t\"description\": \"Wheelchair Dry-cell battery request\"\n\t},\n\t{\n\t\t\"code\": \"WCBW\",\n\t\t\"description\": \"Wheelchair Wet-cell battery request\"\n\t},\n\t{\n\t\t\"code\": \"WCHC\",\n\t\t\"description\": \"Wheelchair To seat request\"\n\t},\n\t{\n\t\t\"code\": \"WCHR\",\n\t\t\"description\": \"Wheelchair To aircraft door request\"\n\t},\n\t{\n\t\t\"code\": \"WCHS\",\n\t\t\"description\": \"Wheelchair Up/down stairs request\"\n\t},\n\t{\n\t\t\"code\": \"WCLB\",\n\t\t\"description\": \"Wheelchair - Lithium ion Battery\"\n\t},\n\t{\n\t\t\"code\": \"WCMP\",\n\t\t\"description\": \"Wheelchair Manual powered request\"\n\t},\n\t{\n\t\t\"code\": \"WCOB\",\n\t\t\"description\": \"Wheelchair On board request\"\n\t},\n\t{\n\t\t\"code\": \"WEAP\",\n\t\t\"description\": \"WEAP Firearms or ammunition booked & carried as checked\"\n\t},\n\t{\n\t\t\"code\": \"XBGS\",\n\t\t\"description\": \"DCS Excess Baggage Request\"\n\t}\n]);\r\n\r\na3_pilot_reports.constant(\"bookmarkThreshold\", 15);\r\n\r\na3_pilot_reports.constant(\"autolandSupportingAcTypes\", [\n\t\"319\",\n\t\"320\",\n\t\"321\",\n\t\"32Q\",\n\t\"32N\"\n]);\r\n\r\na3_pilot_reports.constant(\"turnAroundTimesSupportingAcTypes\", [\n\t\"319\",\n\t\"320\",\n\t\"321\",\n\t\"32Q\",\n\t\"32N\"\n]);\r\n\r\na3_pilot_reports.constant(\"showRecomendedWaterAcTypes\", [\n\t\"319\",\n\t\"320\",\n\t\"321\",\n\t\"32Q\",\n\t\"32N\"\n]);\r\n\r\na3_pilot_reports.constant(\"showCatIIApprachAcTypes\", [\n\t\"DH4\",\n\t\"DH8\",\n\t\"AT4\"\n]);\r\n\r\na3_pilot_reports.constant(\"showGroundInfoAcTypes\", [\n\t\"DH4\",\n\t\"DH8\",\n\t\"AT4\"\n]);\r\n\r\na3_pilot_reports.constant(\"showHotelsAcTypes\", [\n\t\"DH4\",\n\t\"DH8\",\n\t\"AT4\"\n]);\r\n\r\na3_pilot_reports.constant(\"operationalPhases\", [\n\t{\n\t\t\"key\": \"3287\",\n\t\t\"value\": \"On Stand\"\n\t},\n\t{\n\t\t\"key\": \"3288\",\n\t\t\"value\": \"Towing\"\n\t},\n\t{\n\t\t\"key\": \"9242\",\n\t\t\"value\": \"Towing - Stand to Stand\"\n\t},\n\t{\n\t\t\"key\": \"9243\",\n\t\t\"value\": \"Towing - to/from maint\"\n\t},\n\t{\n\t\t\"key\": \"3289\",\n\t\t\"value\": \"Parked\"\n\t},\n\t{\n\t\t\"key\": \"3290\",\n\t\t\"value\": \"Pushback\"\n\t},\n\t{\n\t\t\"key\": \"3291\",\n\t\t\"value\": \"Taxi-out\"\n\t},\n\t{\n\t\t\"key\": \"3292\",\n\t\t\"value\": \"Take-off\"\n\t},\n\t{\n\t\t\"key\": \"3293\",\n\t\t\"value\": \"Initial Climb\"\n\t},\n\t{\n\t\t\"key\": \"3294\",\n\t\t\"value\": \"Climb\"\n\t},\n\t{\n\t\t\"key\": \"3295\",\n\t\t\"value\": \"Cruise\"\n\t},\n\t{\n\t\t\"key\": \"3296\",\n\t\t\"value\": \"Descent\"\n\t},\n\t{\n\t\t\"key\": \"3297\",\n\t\t\"value\": \"Holding\"\n\t},\n\t{\n\t\t\"key\": \"3298\",\n\t\t\"value\": \"Approach\"\n\t},\n\t{\n\t\t\"key\": \"3299\",\n\t\t\"value\": \"Landing\"\n\t},\n\t{\n\t\t\"key\": \"3300\",\n\t\t\"value\": \"Taxi-in\"\n\t},\n\t{\n\t\t\"key\": \"3301\",\n\t\t\"value\": \"Maintenance\"\n\t},\n\t{\n\t\t\"key\": \"3302\",\n\t\t\"value\": \"All\"\n\t},\n\t{\n\t\t\"key\": \"3303\",\n\t\t\"value\": \"In Aircraft\"\n\t},\n\t{\n\t\t\"key\": \"3304\",\n\t\t\"value\": \"In Position at Aircraft\"\n\t},\n\t{\n\t\t\"key\": \"3305\",\n\t\t\"value\": \"In Transit To / From Stand\"\n\t},\n\t{\n\t\t\"key\": \"3306\",\n\t\t\"value\": \"Moving on Stand\"\n\t},\n\t{\n\t\t\"key\": \"3307\",\n\t\t\"value\": \"Positioning to Aircraft\"\n\t},\n\t{\n\t\t\"key\": \"3308\",\n\t\t\"value\": \"Removing from Aircraft\"\n\t},\n\t{\n\t\t\"key\": \"3309\",\n\t\t\"value\": \"Other\"\n\t},\n\t{\n\t\t\"key\": \"3310\",\n\t\t\"value\": \"Hover\"\n\t},\n\t{\n\t\t\"key\": \"3311\",\n\t\t\"value\": \"In Flight\"\n\t},\n\t{\n\t\t\"key\": \"3312\",\n\t\t\"value\": \"Multiple\"\n\t},\n\t{\n\t\t\"key\": \"3313\",\n\t\t\"value\": \"Parked On / By Stand\"\n\t},\n\t{\n\t\t\"key\": \"9241\",\n\t\t\"value\": \"Arrival\"\n\t},\n\t{\n\t\t\"key\": \"9244\",\n\t\t\"value\": \"Arrival - Marshaling\"\n\t},\n\t{\n\t\t\"key\": \"9245\",\n\t\t\"value\": \"Arrival - Guidance\"\n\t},\n\t{\n\t\t\"key\": \"9246\",\n\t\t\"value\": \"Servicing\"\n\t},\n\t{\n\t\t\"key\": \"9247\",\n\t\t\"value\": \"Servicing - De-icing\"\n\t},\n\t{\n\t\t\"key\": \"9248\",\n\t\t\"value\": \"Servicing - Fueling\"\n\t},\n\t{\n\t\t\"key\": \"9249\",\n\t\t\"value\": \"Servicing - Catering\"\n\t},\n\t{\n\t\t\"key\": \"9250\",\n\t\t\"value\": \"Servicing - Lavatory\"\n\t},\n\t{\n\t\t\"key\": \"9251\",\n\t\t\"value\": \"Servicing - Water\"\n\t},\n\t{\n\t\t\"key\": \"9252\",\n\t\t\"value\": \"Servicing - Cleaning\"\n\t},\n\t{\n\t\t\"key\": \"9253\",\n\t\t\"value\": \"Servicing - Line Maint\"\n\t},\n\t{\n\t\t\"key\": \"9254\",\n\t\t\"value\": \"Servicing - Coning\"\n\t},\n\t{\n\t\t\"key\": \"9255\",\n\t\t\"value\": \"Servicing - GPU\"\n\t},\n\t{\n\t\t\"key\": \"9256\",\n\t\t\"value\": \"Servicing - PCA\"\n\t},\n\t{\n\t\t\"key\": \"9257\",\n\t\t\"value\": \"Servicing - Bridging\"\n\t},\n\t{\n\t\t\"key\": \"9258\",\n\t\t\"value\": \"Servicing - Chocking\"\n\t},\n\t{\n\t\t\"key\": \"9259\",\n\t\t\"value\": \"Loading\"\n\t},\n\t{\n\t\t\"key\": \"9260\",\n\t\t\"value\": \"Loading - Passenger\"\n\t},\n\t{\n\t\t\"key\": \"9261\",\n\t\t\"value\": \"Loading - Baggage\"\n\t},\n\t{\n\t\t\"key\": \"9262\",\n\t\t\"value\": \"Loading - Cargo\"\n\t},\n\t{\n\t\t\"key\": \"9263\",\n\t\t\"value\": \"Unloading\"\n\t},\n\t{\n\t\t\"key\": \"9264\",\n\t\t\"value\": \"Unloading - Passenger\"\n\t},\n\t{\n\t\t\"key\": \"9265\",\n\t\t\"value\": \"Unloading - Baggage\"\n\t},\n\t{\n\t\t\"key\": \"9266\",\n\t\t\"value\": \"Unloading - Cargo\"\n\t}\n]);\r\n\r\n})();","(function () {\r\n// Warning!!! This an auto generated file. Any Changes will be lost. If u want to add or edit go to config.json \r\n\r\na3_pilot_reports.constant(\"version\", \"appVersion_20211203144132\");\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\n //Default Configuration For Charts\r\n\r\n a3_pilot_reports.constant('barOptions', barOptions);\r\n a3_pilot_reports.constant('pieDoughnutOptions', pieDoughnutOptions);\r\n \r\n //Default Configuration For Charts\r\n\tvar pieDoughnutOptions = {\r\n\t\t//Boolean - Whether we should show a stroke on each segment\r\n\t\tsegmentShowStroke: true,\r\n\t\t//String - The colour of each segment stroke\r\n\t\tsegmentStrokeColor: \"#fff\",\r\n\t\t//Number - The width of each segment stroke\r\n\t\tsegmentStrokeWidth: 2,\r\n\t\t//Number - The percentage of the chart that we cut out of the middle\r\n\t\tpercentageInnerCutout: 50, // This is 0 for Pie charts\r\n\t\t//Number - Amount of animation steps\r\n\t\tanimationSteps: 100,\r\n\t\t//String - Animation easing effect\r\n\t\tanimationEasing: \"easeOutBounce\",\r\n\t\t//Boolean - Whether we animate the rotation of the Doughnut\r\n\t\tanimateRotate: true,\r\n\t\t//Boolean - Whether we animate scaling the Doughnut from the centre\r\n\t\tanimateScale: false,\r\n\t\t//String - A legend template\r\n\t\tlegendTemplate: \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
\",\r\n\t\tonAnimationComplete: function() {\r\n\t\t\tthis.showTooltip(this.segments, true);\r\n\t\t},\r\n\t\ttooltipEvents: [],\r\n\t\tshowTooltips: true\r\n\t};\r\n\r\n\tvar barOptions = {\r\n\t\t///Boolean - Whether grid lines are shown across the chart\r\n\t\tscaleShowGridLines: true,\r\n\t\t//String - Colour of the grid lines\r\n\t\tscaleGridLineColor: \"rgba(0,0,0,.05)\",\r\n\t\t//Number - Width of the grid lines\r\n\t\tscaleGridLineWidth: 1,\r\n\t\t//Boolean - Whether to show horizontal lines (except X axis)\r\n\t\tscaleShowHorizontalLines: true,\r\n\t\t//Boolean - Whether to show vertical lines (except Y axis)\r\n\t\tscaleShowVerticalLines: true,\r\n\t\t//Boolean - Whether the line is curved between points\r\n\t\tbezierCurve: true,\r\n\t\t//Number - Tension of the bezier curve between points\r\n\t\tbezierCurveTension: 0.4,\r\n\t\t//Boolean - Whether to show a dot for each point\r\n\t\tpointDot: true,\r\n\t\t//Number - Radius of each point dot in pixels\r\n\t\tpointDotRadius: 4,\r\n\t\t//Number - Pixel width of point dot stroke\r\n\t\tpointDotStrokeWidth: 1,\r\n\t\t//Number - amount extra to add to the radius to cater for hit detection outside the drawn point\r\n\t\tpointHitDetectionRadius: 20,\r\n\t\t//Boolean - Whether to show a stroke for datasets\r\n\t\tdatasetStroke: true,\r\n\t\t//Number - Pixel width of dataset stroke\r\n\t\tdatasetStrokeWidth: 2,\r\n\t\t//Boolean - Whether to fill the dataset with a colour\r\n\t\tdatasetFill: true,\r\n\t\t//String - A legend template\r\n\t\tlegendTemplate: \"
    -legend\\\"><% for (var i=0; i
  • \\\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
\"\r\n\t};\r\n \r\n})();\r\n\r\n","(function() {\r\n 'use strict';\r\n\r\nangular.module('MyDirectives', [])\r\n\r\n/* Used to capture images from the device's camera\r\n* and resize them using given dimensions and quality\r\n* \r\n*/\r\n.directive('image', function($q) {\r\n'use strict'\r\n\r\nvar URL = window.URL || window.webkitURL;\r\n\r\nreturn {\r\n\trestrict: 'A',\r\n\tscope: {\r\n\t\t/*image: '=',*/\r\n\t\tmaxwidth: '@?',\r\n\t\tmaxheight: '@?',\r\n\t\tquality: '@?',\r\n\t\timagetype: '@?',\r\n\t\tonfilechange: '&'\r\n\t},\r\n\tlink: function postLink(scope, element, attrs, ctrl) {\r\n\t\tvar onFileChangeCallback = scope.onfilechange;\r\n\t\tvar onFileFailureCallback = scope.onfileerror;\r\n var filename = \"\";\r\n\t\tvar options;\r\n\r\n\t\tvar getOptions = function() {\r\n\t\t\tvar options = {\r\n\t\t\t\tmaxWidth: parseFloat(scope.maxwidth) || 1024,\r\n\t\t\t\tmaxHeight: parseFloat(scope.maxheight) || 768,\r\n\t\t\t\tquality: parseFloat(scope.quality) || 0.8,\r\n\t\t\t\timageType: scope.imagetype || 'image/jpeg',\r\n\t\t\t\tcanvas: true\r\n\t\t\t};\r\n\t\t\treturn options;\r\n\t\t}\r\n\r\n\t\tvar whenError = function(errorMessage) {\r\n\t\t\tscope.$apply(function() {\r\n\t\t\t\tif (typeof(onFileFailureCallback) == 'function') {\r\n\t\t\t\t\t//to pass data in the message, we need to have an object with attrs named as in\r\n\t\t\t\t\t//the html part, eg onfilechange=\"imageChanged(data)\"\r\n\t\t\t\t\tonFileFailureCallback({\r\n\t\t\t\t\t\terr: errorMessage\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tvar whenReady = function(img) {\r\n\t\t\tif (!(img.src || img instanceof HTMLCanvasElement)) {\r\n\t\t\t\twhenError('Loading image file failed');\r\n\t\t\t} else {\r\n\t\t\t\tvar data = img.src || img.toDataURL(options.imageType, options.quality);\r\n\t\t\t\tvar imageResult = {\r\n\t\t\t\t\tdataURL: data,\r\n fileName : filename,\r\n\t\t\t\t\tfileType: options.imageType\r\n\t\t\t\t};\r\n\t\t\t\tscope.$apply(function() {\r\n\t\t\t\t\tif (typeof(onFileChangeCallback) == 'function') {\r\n\t\t\t\t\t\t//to pass data in the message, we need to have an object with attrs named as in\r\n\t\t\t\t\t\t//the html part, eg onfilechange=\"imageChanged(data)\"\r\n\t\t\t\t\t\tonFileChangeCallback({\r\n\t\t\t\t\t\t\tdata: imageResult\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\telement.bind('change', function(evt) {\r\n\t\t\tevt.preventDefault();\r\n\t\t\t//e = e.originalEvent;\r\n\t\t\tvar target = evt.dataTransfer || evt.target;\r\n\t\t\tvar files = target && target.files;\r\n\t\t\tif (files) {\r\n\t\t\t\tvar file;\r\n\t\t\t\toptions = getOptions(); //read latest settings\r\n\t\t\t\tfor (var i = 0; i < files.length; i++) {\r\n\t\t\t\t\tfile = files[i];\r\n filename = file.name;\r\n\t\t\t\t\t//start by get metadata, to autoset the orientation of the image\r\n\t\t\t\t\tloadImage.parseMetaData(file,\r\n\t\t\t\t\t\t//when metadata are ready, use them and then load image\r\n\t\t\t\t\t\tfunction(data) {\r\n\t\t\t\t\t\t\tif (data.exif) {\r\n\t\t\t\t\t\t\t\toptions.orientation = data.exif.get('Orientation');\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (!loadImage(file, whenReady, options)) {\r\n\t\t\t\t\t\t\t\twhenError('Your browser does not support capturing images.');\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n};\r\n})\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('AirportContactFactory',AirportContactFactory);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AirportContactFactory\r\n * @description \r\n * Add, Update, Delete and Get Airport Contacts.\r\n * @ngInject\r\n */\r\nfunction AirportContactFactory(GenericService){\r\n \r\n /**\r\n * Initialize the AirportContact\r\n * @memberof AirportContactFactory\r\n */\r\n\t\tfunction Airport() {\r\n this.Iata=null;\r\n this.Contacts=null;\r\n }\r\n \r\n\t\t/*function Contact() {\r\n this.No=null;\r\n this.ContactType=null;\r\n this.Company=null;\r\n this.Terminal=null;\r\n this.IsPrimary=null;\r\n this.Address=null;\r\n this.Frequencies=null;\r\n this.Remarks=null;\r\n this.OperatingHoursMon=null;\r\n this.OperatingHoursTue=null;\r\n this.OperatingHoursWed=null;\r\n this.OperatingHoursThu=null;\r\n this.OperatingHoursFri=null;\r\n this.OperatingHoursSat=null;\r\n this.OperatingHoursSun=null;\r\n this.Persons=null;\r\n } \r\n \r\n\t\tfunction Person() {\r\n this.No=null;\r\n this.Department=null;\r\n this.Name=null;\r\n this.ContactDetails=null;\r\n } \r\n\r\n\t\tfunction ContactDetails() {\r\n this.Type=null;\r\n this.Details=null;\r\n }*/\r\n \r\n\t\tvar objType = 'airportContacts';\r\n\t\tvar objCallback = Airport; \r\n\r\n\t\tvar service = \r\n\t\t{ \r\n\t\t\tfromObjectList : fromObjectList,\r\n\t\t\tgetAirportContactsFromStorage : getAirportContactsFromStorage,\r\n\t\t\tsetAirportContactsToStorage : setAirportContactsToStorage,\r\n clearAirportContactsFromStorage : clearAirportContactsFromStorage,\r\n getAirportContacts: getAirportContacts\r\n\t\t};\r\n\r\n /**\r\n * Extend an array of Objects from the default airportContact Object\r\n * @memberof AirportContactFactory\r\n * @param {Array} objList an Array Of airportContact\r\n * @returns {Array} airportContact\r\n */\r\n\t\tfunction fromObjectList(objList) {\r\n\t\t\treturn GenericService.fromObjectList(objList,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Get airportContacts\r\n * @memberof AirportContactFactory\r\n * @returns {Array} airportContacts\r\n */\r\n\t\tfunction getAirportContactsFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Save airportContacts to storage\r\n * @memberof AirportContactFactory\r\n * @param {Array} airportContacts A list of AirportContacts\r\n */\r\n\t\tfunction setAirportContactsToStorage(airportContacts) {\r\n\t\t\tGenericService.saveAll(airportContacts,objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Remove the airportContacts of the local storage\r\n * @memberof AirportContactFactory\r\n */\r\n\t\tfunction clearAirportContactsFromStorage() {\r\n\t\t\tGenericService.removeAll(objType,objCallback);\r\n }\r\n \r\n /**\r\n * Get the contacts for a given airport\r\n * @memberof AirportContactFactory\r\n */\r\n\t\tfunction getAirportContacts(airportIata) {\r\n var all = this.getAirportContactsFromStorage();\r\n if (!all) return null;\r\n var airport = all.filter(function(item){return item.Iata == airportIata;});\r\n if (!airport || airport.length == 0) return null;\r\n //we expect a single airport item per iata\r\n return airport[0];\r\n //return GenericService.fromObjectList(airport[0].Contacts, Contact);\r\n }\r\n \r\n\treturn service;\r\n\t}\r\n\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('AirportHotelFactory',AirportHotelFactory);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AirportHotelFactory\r\n * @description \r\n * Add, Update, Delete and Get Airport Hotels.\r\n * @ngInject\r\n */\r\nfunction AirportHotelFactory(GenericService){\r\n \r\n /**\r\n * Initialize the AirportHotel\r\n * @memberof AirportHotelFactory\r\n */\r\n\t\tfunction Airport() {\r\n this.Iata=null;\r\n this.Hotels=null;\r\n }\r\n \r\n\t\tvar objType = 'airportHotels';\r\n\t\tvar objCallback = Airport; \r\n\r\n\t\tvar service = \r\n\t\t{ \r\n\t\t\tfromObjectList : fromObjectList,\r\n\t\t\tgetAirportHotelsFromStorage : getAirportHotelsFromStorage,\r\n\t\t\tsetAirportHotelsToStorage : setAirportHotelsToStorage,\r\n clearAirportHotelsFromStorage : clearAirportHotelsFromStorage,\r\n getAirportHotels: getAirportHotels\r\n\t\t};\r\n\r\n /**\r\n * Extend an array of Objects from the default airportHotel Object\r\n * @memberof AirportHotelFactory\r\n * @param {Array} objList an Array Of airportHotel\r\n * @returns {Array} airportHotel\r\n */\r\n\t\tfunction fromObjectList(objList) {\r\n\t\t\treturn GenericService.fromObjectList(objList,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Get airportHotels\r\n * @memberof AirportHotelFactory\r\n * @returns {Array} airportHotels\r\n */\r\n\t\tfunction getAirportHotelsFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Save airportHotels to storage\r\n * @memberof AirportHotelFactory\r\n * @param {Array} airportHotels A list of AirportHotels\r\n */\r\n\t\tfunction setAirportHotelsToStorage(airportHotels) {\r\n\t\t\tGenericService.saveAll(airportHotels,objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Remove the airportHotels of the local storage\r\n * @memberof AirportHotelFactory\r\n */\r\n\t\tfunction clearAirportHotelsFromStorage() {\r\n\t\t\tGenericService.removeAll(objType,objCallback);\r\n }\r\n \r\n /**\r\n * Get the Hotels for a given airport\r\n * @memberof AirportHotelFactory\r\n */\r\n\t\tfunction getAirportHotels(airportIata, fltDate) {\r\n var all = this.getAirportHotelsFromStorage();\r\n if (!all) return null;\r\n var airport = all.filter(function(item){return item.Iata == airportIata});\r\n if (!airport || airport.length == 0) return null;\r\n \r\n //for each airport hotel\r\n //from all available hotel priorities, find the one matching the active period \r\n angular.forEach(airport[0].Hotels, function(hotel) \r\n {\r\n var fltActiveHotels = hotel && hotel.HotelPriorities ? hotel.HotelPriorities.filter(function(item){return fltDate >= item.ActiveBegin && fltDate <= item.ActiveEnd}) : []; \r\n if (!fltActiveHotels || fltActiveHotels.length == 0) return ; //hotel inactive in FltDate - ActivePriority will be undefined for this hotel\r\n hotel.ActivePriority = fltActiveHotels[0].PriorityNo; //set the ActivePriority field for the hotel to be displayed in UI\r\n });\r\n \r\n\r\n //we expect a single airport item per iata\r\n return airport[0];\r\n //return GenericService.fromObjectList(airport[0].Hotels, Hotel);\r\n }\r\n \r\n\treturn service;\r\n\t}\r\n\r\n \r\n })(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('BucketCtrl', BucketCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name BucketCtrl\r\n * @description \r\n * View bucket\r\n * @ngInject\r\n */\r\n function BucketCtrl($scope, $location, BucketFactory, UserFactory, MessageFactory, $timeout,SettingsMain,defaultCalendarDate) {\r\n var ownDuties = [];\r\n var sharedDuties = [];\r\n var approvedDuties = [];\r\n\r\n $scope.state = 'bucketCalendar';\r\n var user = UserFactory.getUser();\r\n $scope.isSecure = UserFactory.isSecure();\r\n $scope.isUserSA = user.position == 'SA' ? true : false;\r\n $scope.logged_user_info = user.aimsId + ' - ' + user.name;\r\n $scope.getCalendarData = getCalendarData;\r\n $scope.showErrorMessage = false;\r\n\r\n var selectedDate = SettingsMain.getCalendarSelectedDate(); //Redirect to month that was previously selected\r\n SettingsMain.setCalendarSelectedDate(null); //Then reinitialize to current month\r\n\r\n getCalendarData();\r\n\r\n function getCalendarData(){\r\n progressBarBox(true);\r\n BucketFactory.getDutyObject(function (responseData) {\r\n ownDuties = responseData.data.data.Duties;\r\n sharedDuties = responseData.data.data.SharedDuties;\r\n approvedDuties = responseData.data.data.ApprovedDuties;\r\n setupView();\r\n progressBarBox(false);\r\n }).catch(function(error) {\r\n progressBarBox(false);\r\n $scope.showErrorMessage = true;\r\n console.error('Load duties error', error.status, error.statusText);\r\n });\r\n }\r\n \r\n function setupView() {\r\n if (!UserFactory.isLoggedIn()) {\r\n $location.path(\"/login\");\r\n }\r\n \r\n $scope.number_of_messages = MessageFactory.getMessagesFromStorage().length;\r\n $scope.number_of_messages_not_readen = MessageFactory.getCountOfUnreadMessages();\r\n\r\n\r\n /*var ownEvents = formatDuties(ownDuties, true, false);\r\n if (sharedDuties.length > 0) {\r\n var sharedEvents = formatDuties(sharedDuties, false, false);\r\n var events = ownEvents.concat(sharedEvents);\r\n } else {\r\n var events = ownEvents;\r\n }*/\r\n $scope.notification = createNotification(ownDuties);\r\n var ownEvents = formatDuties(ownDuties, true, false);\r\n var events = ownEvents;\r\n if(approvedDuties != null || approvedDuties!= undefined){\r\n if(approvedDuties.length>0){\r\n var appvovedEvents = formatDuties(approvedDuties, true, true);\r\n var events = events.concat(appvovedEvents);\r\n }\r\n }\r\n calendar(events);\r\n }\r\n\r\n\r\n /**\r\n * Transform routes in calendar events\r\n * @memberof BucketCtrl\r\n * @param {array} routes - The Scheduled Routes \r\n * @return {array} events \r\n */\r\n function formatDuties(duties, isOwnDuty, isApproved) {\r\n var dutiesEvents = [];\r\n for (var i = 0; i < duties.length; i++) {\r\n \r\n if(duties[i].IsUpdated){\r\n console.log(duties[i]);\r\n }\r\n /*************** Add main event for duty *********************/\r\n\r\n // var eType = (isOwnDuty ? 'own-' : 'shared-') + duties[i].DutyType.toLowerCase();\r\n var eClassName = getEventClassName(duties[i], isOwnDuty, isApproved);\r\n var eIcons = getEventIcons(duties[i], isOwnDuty, isApproved);\r\n var eTitle = getEventTitle(duties[i], isOwnDuty) + ((duties[i].TotalSharedDuties == undefined) ? \"\" : duties[i].TotalSharedDuties) ;\r\n var eOtherInfos = getOtherInfos(duties[i], isOwnDuty);\r\n var event = {\r\n _id: duties[i].Id,\r\n // type: eType,\r\n icons: eIcons,\r\n className: eClassName.class,\r\n title: eTitle,\r\n start : (duties[i].DutyBegin == duties[i].DutyEnd)? duties[i].DutyDateS :duties[i].DutyBegin,\r\n\t\t\t\t end : (duties[i].DutyBegin == duties[i].DutyEnd)? null : duties[i].DutyEnd,\r\n sortOrder: (isOwnDuty ? 1 : -1),\r\n otherInfos: eOtherInfos,\r\n shareable: duties[i].Shareable,\r\n isOwnDuty: isOwnDuty,\r\n isApproved: isApproved,\r\n isOwnApproved: duties[i].HasApprovedProposals,\r\n listViewColor: eClassName.color\r\n }\r\n dutiesEvents.push(event);\r\n\r\n }\r\n return dutiesEvents;\r\n }\r\n \r\n \r\n function createNotification(duties){\r\n var NewPendingProposalsCount = 0;\r\n var NewApprovedProposalsCount = 0;\r\n var NewRejectedProposalsCount = 0;\r\n var notificationText = null;\r\n \r\n for (var i = 0; i < duties.length; i++) {\r\n \r\n if(duties[i].IsUpdated){\r\n if(duties[i].HasApprovedProposals){\r\n NewApprovedProposalsCount++;\r\n }else{\r\n NewPendingProposalsCount += duties[i].NewPendingProposalsCount;\r\n NewRejectedProposalsCount += duties[i].NewRejectedProposalsCount;\r\n }\r\n }\r\n }\r\n \r\n /* var notification = {\r\n NewPendingProposalsCount : NewPendingProposalsCount,\r\n NewApprovedProposalsCount : NewApprovedProposalsCount,\r\n NewRejectedProposalsCount : NewRejectedProposalsCount\r\n }*/\r\n \r\n if((NewPendingProposalsCount + NewApprovedProposalsCount + NewRejectedProposalsCount)>0){\r\n notificationText = \"You have \"\r\n var hasPrevious = false;\r\n if(NewPendingProposalsCount){\r\n notificationText = notificationText + NewPendingProposalsCount + \" pending\";\r\n hasPrevious = true;\r\n }\r\n \r\n if(NewRejectedProposalsCount){\r\n var conjuction = (hasPrevious ? NewApprovedProposalsCount ? \", \" : \" and \" : \"\");\r\n notificationText = notificationText + conjuction + NewRejectedProposalsCount + \" rejected\";\r\n hasPrevious = true;\r\n }\r\n \r\n if(NewApprovedProposalsCount){\r\n var conjuction = (hasPrevious ? \" and \" : \"\" );\r\n notificationText = notificationText + conjuction + NewApprovedProposalsCount + \" accepted\";\r\n }\r\n \r\n notificationText = notificationText+ \" proposals.\" ; \r\n \r\n \r\n }\r\n \r\n \r\n \r\n return notificationText;\r\n \r\n }\r\n \r\n \r\n \r\n /**\r\n * Returns an array of strings for icons to display in the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {array} icons - The array of strings for icons to display in the event tile.\r\n */\r\n function getEventIcons(duty, isOwnDuty, isApproved) {\r\n var icons = [];\r\n if (!isOwnDuty) \r\n icons.push('fa-sing-in');\r\n else{\r\n if (duty.IsUpdated) icons.push('fa-star text-orange');\r\n\r\n /* if (duty.PendingProposalsCount > 0 && !isApproved) icons.push('fa-info-circle');*/\r\n if (!duty.Shareable || isApproved) icons.push('fa-lock');\r\n if (duty.Shared && !isApproved) icons.push('fa-bitbucket');\r\n\r\n \r\n\r\n }\r\n return icons;\r\n }\r\n\r\n /**\r\n * Returns the title for the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {string} title - The title to display in the event tile.\r\n */\r\n function getEventTitle(duty, isOwnDuty) {\r\n var title = '';\r\n if (isOwnDuty) title += duty.Title;\r\n else title += 'Shared duties: ';\r\n return title;\r\n }\r\n\r\n /**\r\n * Returns the class for the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {string} className - The class(es) to use for displaying the event tile.\r\n */\r\n function getEventClassName(duty, isOwnDuty, isApproved) {\r\n var eventClass = {class:'fc-bucket ', color:''};\r\n if (isOwnDuty) {\r\n eventClass.class += 'fc-own ';\r\n var hasApprovedTrade = duty.HasApprovedProposals;\r\n if(isApproved == true) {\r\n eventClass.class += 'fc-green-inverted ';\r\n eventClass.color = 'lv-green-inverted';\r\n }\r\n else if (hasApprovedTrade) {\r\n eventClass.class += 'fc-green ';\r\n eventClass.color = 'lv-green';\r\n }\r\n else if (duty.Shared) {\r\n eventClass.class += 'fc-primary-inverted ';\r\n eventClass.color = 'lv-blue';\r\n }\r\n /* else if (duty.Shareable && duty.PendingProposalsCount == 0) {\r\n eventClass.class += 'fc-blue ';\r\n eventClass.color = 'lv-blue';\r\n } else if (duty.PendingProposalsCount > 0) {\r\n eventClass.class += 'fc-orange ';\r\n eventClass.color = 'lv-orange';\r\n } else if (duty.Bookmarks != undefined && duty.Bookmarks.length > 0) {\r\n eventClass.class += 'fc-purple-inverted ';\r\n eventClass.color = 'lv-purple-inverted';\r\n } */\r\n else {\r\n eventClass.class += 'fc-white ';\r\n eventClass.color = 'lv-white';\r\n }\r\n } else {\r\n eventClass.class += 'fc-aluminum ';\r\n eventClass.color = 'lv-aluminum';\r\n }\r\n return eventClass;\r\n }\r\n\r\n /**\r\n * Returns an array of objects for infos (label, number) to display in the event tile\r\n * @memberof BucketCtrl\r\n * @param {object} duty - The Scheduled duty \r\n * @param {boolean} ownDuty - Is set to true when the duty is current user's duty, otherwise is set to false\r\n * @return {array} infos - The array of objects for infos (label, number) to display in the event tile.\r\n */\r\n function getOtherInfos(duty, isOwnDuty) {\r\n var infos = [];\r\n if (isOwnDuty) {\r\n var hasApprovedTrade = duty.HasApprovedProposals;\r\n\r\n if (!hasApprovedTrade) {\r\n if (duty.PendingProposalsCount > 0) infos.push({ label: 'Proposals', num: duty.PendingProposalsCount });\r\n if (duty.BookmarksCount > 0) infos.push({ label: 'Bookmarks', num: duty.BookmarksCount });\r\n\r\n // var totalBookmarks = (duty.bookmarks == undefined ? 0 : duty.bookmarks.length);\r\n // if (totalBookmarks > 0) infos.push({ label: 'Bookmarks', num: totalBookmarks.toString() });\r\n }\r\n }\r\n // else {\r\n // if (duty.TotalSharedDuties > 0) infos.push({ label: 'Total', num: duty.TotalSharedDuties.toString() });\r\n // //if (duty.unclaimedShared > 0) infos.push({ label: 'Unclaimed', num: duty.unclaimedShared.toString() });\r\n // }\r\n return infos;\r\n }\r\n\r\n function calendar(events) {\r\n $('#calendar').fullCalendar('destroy');\r\n \r\n $(\"#calendar\").fullCalendar({\r\n defaultView: getDefaultView(),\r\n defaultDate: defaultCalendarDate,\r\n firstDay: 1,\r\n lang: 'en',\r\n editable: false,\r\n draggable: false,\r\n selectable: false,\r\n selectHelper: false,\r\n unselectAuto: false,\r\n disableResizing: false,\r\n droppable: false,\r\n fixedWeekCount: false,\r\n nextDayThreshold: \"00:00:00\",\r\n header: {\r\n left: 'title',\r\n center: '',\r\n\t\t\t\t\tright: 'month,listMonth today prev,next'\r\n },\r\n timeFormat: 'HH:mm',\r\n displayEventEnd: true,\r\n events: events,\r\n eventOrder: \"sortOrder\",\r\n eventRender: function (event, element, icon) {\r\n element.find('.fc-title').prepend(\"
\");\r\n if($('#calendar').fullCalendar('getView').type === 'listMonth'){\r\n element.find('.fc-list-item-title').addClass('listview-icon');\r\n $.each(event.className, function (index, icon) {\r\n element.addClass(event.listViewColor);\r\n });\r\n $.each(event.icons, function (index, icon) {\r\n element.find('.listview-icon').prepend(\" \");\r\n });\r\n \r\n if (event.otherInfos != null && event.otherInfos.length > 0) {\r\n $.each(event.otherInfos, function (index, info) {\r\n if(info.label == 'Proposals')\r\n element.find('.fc-list-item-title').append(\"\" + info.num + \"\");\r\n });\r\n \r\n }\r\n }\r\n else{\r\n if (event.icons != null && event.icons.length > 0) {\r\n \r\n element.find('.fc-title').prepend(\"\");\r\n $.each(event.icons, function (index, icon) {\r\n element.find('.calendar-icon').append(\" \");\r\n });\r\n }\r\n if (event.otherInfos != null && event.otherInfos.length > 0) {\r\n $.each(event.otherInfos, function (index, info) {\r\n element.find('.fc-title').append(\"
\" + info.label + \": \" + info.num + \"
\");\r\n element.find('.fc-list-item-title').add(\"\" + info.num + \"\");\r\n });\r\n \r\n }\r\n }\r\n },\r\n eventResize: function(event, delta, revertFunc) {\r\n changeView(detectMobile(),'#calendar');\r\n },\r\n dayRender: function (date, cell) {\r\n },\r\n // dayClick: function(date, jsEvent, view) {\r\n // $timeout(function(){ gotoDayBucketView(date); })\r\n // },\r\n eventClick: function (calEvent, jsEvent, view) {\r\n if(calEvent.shareable == true && calEvent.isOwnDuty && (!calEvent.isApproved || calEvent.isOwnApproved)){\r\n $timeout(function () { gotoDayBucketView(calEvent._id); });\r\n }\r\n else if(calEvent.shareable == false && calEvent.isOwnDuty)\r\n {\r\n if(!calEvent.isApproved){ //don't allow click for approved duty\r\n $timeout(function () { unableShare(); });\r\n }\r\n }\r\n },\r\n height: 'auto'\r\n });\r\n \r\n $('.fc-listMonth-button').click(function(){\r\n SettingsMain.setCalendarViewStyle('listMonth');\r\n })\r\n \r\n $('.fc-month-button').click(function(){\r\n SettingsMain.setCalendarViewStyle('month');\r\n })\r\n\r\n if(selectedDate != null && selectedDate != undefined){\r\n $(\"#calendar\").fullCalendar('gotoDate', selectedDate);\r\n }\r\n }\r\n\r\n function getDefaultView(){\r\n var calendarStyle = SettingsMain.getCalendarViewStyle();\r\n if (calendarStyle == null){\r\n calendarStyle = detectMobile() ? \"listMonth\" : \"month\";\r\n }\r\n return calendarStyle;\r\n \r\n }\r\n \r\n\t\t\tfunction detectMobile() {\r\n\t\t\t\tvar isMobile =(window.innerWidth <= 800 && window.innerHeight <= 735); \r\n \r\n return isMobile;\t\t\r\n }\t\r\n \r\n \r\n\r\n /**\r\n * Redirects to bucket calendar day \r\n * @memberof BucketCtrl\r\n */\r\n function gotoDayBucketView(dutyId) {\r\n $location.path('/bucketDay/' + dutyId);\r\n }\r\n }\r\n function unableShare(){\r\n bootbox.dialog({\r\n message: \"
You can't share this duty, please try another shareable duty.
\",\r\n title: \"Warning\",\r\n buttons: {\r\n cancel:{\r\n label: \"Close\",\r\n className: \"btn-default\",\r\n callback: function(){}\r\n }\r\n }\r\n })\r\n }\r\n function progressBarBox( isOpen ){\r\n if(isOpen){\r\n bootbox.dialog({\r\n closeButton: false,\r\n message: '
Please wait...
',\r\n //title: \"Please wait...\"\r\n });\r\n }else {\r\n bootbox.hideAll();\r\n }\r\n\r\n }\r\n\r\n})();","(function () {\r\n 'use strict';\r\n a3_pilot_reports.factory('BucketFactory', BucketFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name BucketFactory\r\n * @description \r\n * Get Duties from API \r\n * @ngInject\r\n */\r\n function BucketFactory(GenericService, $http, $q, apiUrl, LogService) {\r\n\r\n /**\r\n * Initialize Bucket\r\n * @memberof BucketFactory\r\n */\r\n \r\n var service = {\r\n getDutyObject: getDutyObject,\r\n getDutyById: getDutyById,\r\n shareDuty: shareDuty,\r\n acknowledgeProposal : acknowledgeProposal,\r\n fetchProposal: fetchProposal,\r\n createProposal: createProposal,\r\n evaluateProposal: evaluateProposal,\r\n undoProposalStatus: undoProposalStatus,\r\n fetchSharedProposal: fetchSharedProposal\r\n };\r\n\r\n \r\n /**\r\n * Gets Bucket Calendar object\r\n * @memberof BucketFactory\r\n * @param {function} callback \r\n */\r\n function getDutyObject(callback) {\r\n return $http.get(apiUrl + '/bucket/', { 'Content-Type': 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Gets duty object and shared duties object for the BucketDay View\r\n * @memberof BucketFactory\r\n * @param {number} dutyId \r\n * @param {function} callback \r\n */\r\n function getDutyById(dutyId, callback){\r\n return $http.get(apiUrl + '/bucket/GetBucketDuty/' + dutyId, { 'Content-Type': 'application/json' })\r\n .then(callback);\r\n }\r\n \r\n /**\r\n * Shares/Unshares duty\r\n * @memberof BucketFactory\r\n * @param {object} duty \r\n * @param {function} callback \r\n * @param {function} errorCallback \r\n */\r\n function shareDuty(duty, callback, errorCallback ){\r\n var dutyMinified = {\r\n Id: duty.Id,\r\n Shareable: duty.Shareable,\r\n Shared: duty.Shared,\r\n Comments: duty.Comments,\r\n CrewInformation: {\r\n Email: null,\r\n Phone: null,\r\n Comments: null\r\n }\r\n };\r\n \r\n return $http.post(apiUrl + '/bucket/ShareDuty/', dutyMinified, {'Content-Type' : 'application/json' })\r\n .then (callback)\r\n .catch(errorCallback);\r\n }\r\n\r\n /**\r\n * Makes proposal acknowledged \r\n * @memberof BucketFactory\r\n * @param {number} proposalId \r\n * @param {function} callback \r\n */\r\n function acknowledgeProposal(proposalId, callback){\r\n return $http.get(apiUrl + '/bucket/AcknowledgeProposal?proposalId=' + proposalId, { 'Content-Type' : 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Fetches proposal info \r\n * @memberof BucketFactory\r\n * @param {number} dutyId \r\n * @param {function} callback \r\n * @returns {object} - Promise containing Proposed and Requested duties alongside Crew and Route details for each one\r\n */\r\n function fetchProposal(dutyId, callback){\r\n return $http.get(apiUrl + '/bucket/FetchProposal?id=' + dutyId, { 'Content-Type' : 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Fetches shared proposal info\r\n * @param {number} dutyId \r\n * @param {number} sharedDutyId \r\n * @param {function} callback\r\n * @returns {object} - Promise containing Proposed and Requested duties alongside Crew and Route details for each one\r\n */\r\n function fetchSharedProposal(dutyId, sharedDutyId, callback){\r\n return $http.get(apiUrl + '/bucket/FetchSharedProposal?dutyId=' + dutyId + '&sharedDutyId=' + sharedDutyId, { 'Content-Type' : 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Creates/Sends Proposal\r\n * @memberof BucketFactory\r\n * @param {object} proposal - Containing proposedDutiesIdList and requestedDutiesIdList\r\n * @param {function} callback\r\n * @returns {object} - Promise containing updated proposal \r\n */\r\n function createProposal(proposal, callback){\r\n return $http.post(apiUrl + '/bucket/CreateProposal', proposal, { 'Content-Type' : 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Approves/Rejects proposal\r\n * @memberof BucketFactory\r\n * @param {object} proposal - Containing Id and isApproved\r\n * @param {function} callback\r\n * @returns {object} - Promise containing updated proposal \r\n */\r\n function evaluateProposal(proposal, callback){\r\n return $http.put(apiUrl + '/bucket/EvaluateProposal/' + proposal.Id, proposal.isApproved, { 'Content-Type' : 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Reverts proposal to previous status\r\n * @memberof BucketFactory\r\n * @param {number} proposalId \r\n * @param {function} callback \r\n * @returns {object} - Promise containing updated proposal\r\n */\r\n function undoProposalStatus(proposalId, callback){\r\n return $http.put(apiUrl + '/bucket/UndoProposalStatus/' + proposalId, { 'Content-Type' : 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n return service;\r\n }\r\n})();","(function(){\r\n 'use strict';\r\n\r\na3_pilot_reports.controller('BucketDayCtrl', BucketDayCtrl);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name BucketDayCtrl\r\n * @description \r\n * Shows the Bucket Day informations\r\n * @ngInject\r\n */\r\n\r\n function BucketDayCtrl($scope, BucketFactory, $routeParams, $location, $uibModal, UserFactory, SettingsMain,$timeout) {\r\n var dutyId = $routeParams.dutyId;\r\n \r\n $scope.isSharedLate = false;\r\n\r\n \r\n /**\r\n * Checks if duty wont be approved in time because of the weekend \r\n * @memberof BucketDayCtrl\r\n */\r\n function checkLateShare() {\r\n var today = new Date();\r\n var dutyDay = new Date($scope.duty.DutyBegin);\r\n\r\n // how many days until duty date\r\n var trimmedToday = new Date(today);\r\n var trimmedDutyDay = new Date(dutyDay);\r\n var diffDays = Date.DifferenceInDays(trimmedToday.trimTime(), trimmedDutyDay.trimTime());\r\n\r\n //friday saturday sunday\r\n var fss = [5, 6, 0];\r\n //saturday sunday monday\r\n var ssm = [6, 0, 1]\r\n\r\n // today is Fr,Sa,Su AND duty on Sa,Su,Mo AND same weekend\r\n if (fss.contains(today.getDay()) && ssm.contains(dutyDay.getDay()) && diffDays < 4){\r\n //friday before 14:00 is not a late share\r\n if (!(today.getDay() == 5 && today.getUTCHours() < 14))\r\n $scope.isSharedLate = true;\r\n }\r\n }\r\n\r\n $scope.currentDutyId = dutyId;\r\n \r\n $scope.initialized = false;\r\n \r\n $scope.displayMessage = displayMessage;\r\n $scope.confirmUnshare = confirmUnshare;\r\n $scope.shareDuty = shareDuty;\r\n $scope.isLoading = false;\r\n\r\n var dutyId = $routeParams.dutyId;\r\n $scope.currentDutyId = dutyId;\r\n \r\n \r\n var user = UserFactory.getUser();\r\n $scope.activeTab = 0;\r\n \r\n \r\n $scope.duty = null;\r\n $scope.Duties = [];\r\n $scope.proposals = [];\r\n \r\n $scope.toggle = {\r\n Accepted:true,\r\n Rejected:false,\r\n Pending:true,\r\n Bookmarks:true\r\n }\r\n \r\n $scope.getProposalBorderStyle = getProposalBorderStyle;\r\n \r\n function getProposalBorderStyle(proposal){\r\n var textclass=\"\";\r\n if(proposal.Status == \"Bookmarked\" && proposal.State=='Out' ){\r\n textclass = \"border-left-amber\";\r\n }else if(proposal.Status == \"Pending\" && proposal.State == 'Out' ){\r\n textclass=\"border-left-light-blue\";\r\n }else if(proposal.Status == \"Rejected\" || proposal.Status == \"RejectedBySTP\"){\r\n textclass=\"border-left-red\";\r\n }else if(proposal.Status == \"Pending\" && proposal.State == 'In'){\r\n textclass=\"border-left-orange\";\r\n }else if(proposal.Status == \"Approved\" || proposal.Status == \"ApprovedBySTP\" ){\r\n textclass=\"border-left-green\";\r\n } else if( proposal.Status == \"Shared\"){\r\n textclass=\"border-left-blue-gray\";\r\n }\r\n return textclass;\r\n } \r\n \r\n \r\n $scope.logged_user_info = user.aimsId + ' - ' + user.name;\r\n\r\n \r\n $scope.hasTimeChange = false;\r\n \r\n $scope.approvedDuty = null;\r\n $scope.showMobileProposalCriteria = false;\r\n \r\n $scope.filterProposal = filterProposal;\r\n $scope.hasProposals = hasProposals;\r\n \r\n function hasProposals(){\r\n var value = false\r\n if($scope.duty && $scope.duty.Duties){\r\n for(var i=0;i<$scope.duty.Duties.length;i++) { \r\n if($scope.duty.Duties[i].Id>0){\r\n value = true;\r\n break;\r\n }\r\n }\r\n \r\n if(!value && $scope.activeTab != 1 ){\r\n $scope.activeTab = 1;\r\n }\r\n }\r\n\r\n \r\n\r\n \r\n return value;\r\n }\r\n \r\n function filterProposal(proposal){\r\n var isShown = false;\r\n if (proposal.Id>0){\r\n if(proposal.Status == \"Approved\" || proposal.Status == \"ApprovedBySTP\" ){\r\n $scope.approvedDuty = true;\r\n if($scope.toggle.Accepted)\r\n isShown = true;\r\n }else if(proposal.Status == \"Pending\" && $scope.toggle.Pending){\r\n isShown = true;\r\n }else if((proposal.Status == \"Rejected\" || proposal.Status == \"RejectedBySTP\") && ($scope.toggle.Rejected || !proposal.isAcknowledged)){\r\n console.log($scope.toggle.Rejected);\r\n console.log(proposal);\r\n isShown = true;\r\n }else if(proposal.Status == \"Bookmarked\" && $scope.toggle.Bookmarks){\r\n isShown = true;\r\n }\r\n } \r\n \r\n return isShown;\r\n }\r\n\r\n \r\n $scope.returnToBucket = returnToBucket;\r\n\r\n $scope.refresh = getData;\r\n \r\n getData();\t\r\n \r\n function getData(){\r\n $scope.isLoading = true;\r\n BucketFactory.getDutyById(dutyId, function(responseData){ \r\n $scope.initialized = true;\r\n $scope.isLoading = false;\r\n $scope.duty = responseData.data.data.duty;\r\n $scope.currentDutyDate = $scope.duty.DutyDateS;\r\n $scope.Duties = responseData.data.data.duty.Duties;\r\n $scope.totalItems = $scope.Duties.length;\r\n $scope.currentPage = 1;\r\n\r\n SettingsMain.setCalendarSelectedDate($scope.currentDutyDate);\r\n \r\n checkLateShare();\r\n initProposalsView();\r\n \r\n }).catch(function(error) {\r\n $scope.isLoading = false;\r\n console.error('Wrong AimsId', error.status, error.statusText);\r\n returnToBucket();\r\n });\r\n }\r\n\r\n\r\n \r\n function initProposalsView(){\r\n $scope.approvedDuty = false; \r\n for(var i=0;i<$scope.duty.Duties.length;i++) { \r\n if($scope.duty.Duties[i].Status == \"Approved\" || $scope.duty.Duties[i].Status == \"ApprovedBySTP\" ){ \r\n $scope.approvedDuty = true; \r\n }\r\n }\r\n } \r\n\r\n /**\r\n * Opens a dialog with information on a duty, \r\n * Depending on the duty type (in proposal, out proposal or shared by other in bucket) different options are displayed:\r\n * 1. In proposal\r\n * - Approve (available when in proposal not reviewed, will set status to Approved)\r\n * - Reject (available when in proposal not reviewed, will set status to Rejected)\r\n * - Reset (available when in proposal has been reviewed, will set status to Pending)\r\n * - Close (available always, just closes dialog, no action performed)\r\n * 2. Out proposal\r\n * - Remove (available when out proposal not reviewed, will remove request from duty)\r\n * - Close (available always, just closes dialog, no action performed)\r\n * 3. Shared in bucket\r\n * - Request (available always, will send a request for duty, will be added in out proposals)\r\n * - Close (available always, just closes dialog, no action performed)\r\n * @memberof BucketCtrl\r\n */\r\n\r\n \r\n /**\r\n * Prompts user to confirm sharing duty, if user agrees then the duty dialog will open \r\n * @memberof BucketCtrl\r\n */\r\n function shareDuty(duty) {\r\n //if (confirm('You are about to share into global bucket the selected duty. Do you wish to continue?')) {\r\n duty.fromShareBtn = true;\r\n \r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgDuty.html',\r\n controller: 'BucketModalCtrl',\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n duty: function () { return duty; },\r\n currentDutyId: function () { return dutyId; }\r\n }\r\n });\r\n \r\n modalInstance.result.then(function (refresh) {\r\n if(refresh){\r\n getData();\r\n }\r\n });\r\n //}\r\n }\r\n\r\n /**\r\n * Prompts user to confirm removing duty from shared bucket, if user agrees then all proposal for the duty will be removed (will be displayed as N/A to other users) \r\n * @memberof BucketCtrl\r\n */\r\n\r\n function confirmUnshare() {\r\n bootbox.dialog({\r\n message: \"Please confirm that you wish to Un-share your duty.

\",\r\n title: \"Unshare\",\r\n buttons: {\r\n confirm:{\r\n label: ' Confirm',\r\n className: \"btn-warning\",\r\n callback: function(){\r\n BucketFactory.shareDuty($scope.duty, function(responseData){ \r\n $scope.responseText = responseData.data.data;\r\n getData();\r\n })\r\n }\r\n }, \r\n cancel:{\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function(){}\r\n }\r\n }\r\n })\r\n } \r\n\r\n /**\r\n * Redirects to bucket' calendar\r\n * @memberof BucketCtrl\r\n */\r\n function returnToBucket() {\r\n SettingsMain.setEditingPage(null);\r\n $location.path(\"/bucket/\");\r\n }\r\n /**\r\n * Redirects to flights' calendar\r\n * @memberof BucketCtrl\r\n */\r\n function gotoFlightsCalendar() {\r\n SettingsMain.setEditingPage(null);\r\n $location.path(\"/\");\r\n }\r\n \r\n \r\n //Pagination\r\n\t\t$scope.pageOptions = [\r\n\t\t\t\t{ name: '5', value: '5' }, \r\n\t\t\t\t{ name: '8', value: '8' }, \r\n\t\t\t\t{ name: '15', value: '15' },\r\n\t\t\t\t{ name: '30', value: '30' },\r\n\t\t\t\t{ name: '50', value: '50' }\r\n\t\t];\r\n \r\n\t\t$scope.viewby = $scope.pageOptions[1].value;\r\n\t\t$scope.currentPage = 1;\r\n\t\t$scope.itemsPerPage = $scope.viewby;\r\n\t\t$scope.maxSize = 5; //Number of pager buttons to show\r\n\t\t$scope.setPage = setPage;\r\n\t\t$scope.setItemsPerPage = setItemsPerPage;\r\n\r\n\r\n /**\r\n * Set pagination page number\r\n * @memberof BucketDayCtrl\r\n * @param {number} pageNo list page number\r\n */\r\n\t\tfunction setPage(pageNo) {\r\n\t\t\t$scope.currentPage = pageNo;\r\n\t\t}\r\n /**\r\n * Set items per page \r\n * @memberof BucketDayCtrl\r\n * @param {number} num the Number of items to show per page\r\n */\r\n\t\tfunction setItemsPerPage(num) {\r\n\t\t\t$scope.itemsPerPage = num;\r\n\t\t\t$scope.currentPage = 1; //reset to first page\r\n\t\t}\r\n \r\n \r\n function displayMessage(message, hasErrors) {\r\n $scope.showResponse = true;\r\n $scope.responseText = message;\r\n $scope.responseHasErrors = hasErrors;\r\n $timeout(function () {if(!hasErrors){$scope.showResponse = false;}} , 1000);\r\n }\r\n \r\n \r\n\r\n}\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('BucketModalCtrl', BucketModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name BucketModalCtrl\r\n * @description \r\n * Shows a Share/Unshare Modal \r\n * @ngInject\r\n */\r\n\r\n function BucketModalCtrl($scope, $timeout, $uibModalInstance, duty, currentDutyId, BucketFactory){\r\n $scope.duty = duty;\r\n $scope.currentDutyId = currentDutyId;\r\n $scope.closeDuty = closeDuty;\r\n\r\n $scope.shareDuty = shareDuty;\r\n $scope.responseText = null;\r\n $scope.responseHasErrors = null;\r\n\r\n $scope.submitted = false;\r\n\r\n /**\r\n * Close the modal\r\n * @memberof BucketModalCtrl\r\n */\r\n function closeDuty(refresh){\r\n $uibModalInstance.close(refresh);\r\n }\r\n\r\n /**\r\n * Adds/Removes duty to/from global bucket\r\n * @memberof BucketModalCtrl\r\n */\r\n function shareDuty() {\r\n $scope.submitted = true;\r\n \r\n duty.Comments = $scope.duty.Comments;\r\n\r\n BucketFactory.shareDuty(duty, function (responseData) {\r\n displayMessage(\"Duty shared.\",false);\r\n $timeout(function () {closeDuty(true);} , 5000);\r\n },\r\n function (){\r\n displayMessage(\"Failed to share duty.\",true);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Displays message when share/unshare \r\n * @memberof BucketModalCtrl\r\n * @param {string} message \r\n * @param {boolean} hasErrors \r\n */\r\n function displayMessage(message, hasErrors) {\r\n $scope.responseText = message;\r\n $scope.responseHasErrors = hasErrors;\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('proposal', proposal);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name proposal\r\n * @restrict E\r\n * @description\r\n * Implementation of proposal\r\n * Initialize the proposal element of bucket\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */ \r\nfunction proposal(BucketFactory, $uibModal, $filter) {\r\n function link(scope, element, attrs){\r\n scope.isOpen = false;\r\n scope.successful = false;\r\n scope.error = false;\r\n scope.proposal.createDisabled = false;\r\n \r\n scope.duty = scope.proposal.Duty;\r\n \r\n scope.loading = false;\r\n scope.errorMessage = null;\r\n \r\n scope.ProposedDuties = new Array();\r\n scope.RequestedDuties = new Array();\r\n scope.AllDuties = new Array();\r\n\r\n scope.fetch = fetchInformation;\r\n scope.viewInfoModal = viewInfoModal;\r\n scope.createProposal = createProposal;\r\n scope.evaluateProposal = evaluateProposal;\r\n scope.undoProposalStatus = undoProposalStatus;\r\n scope.acknowledgeProposal = acknowledgeProposal;\r\n scope.confirmCreateProposal = confirmCreateProposal;\r\n scope.getFirstInfoIcon = getFirstInfoIcon;\r\n scope.getSecondInfoIcon = getSecondInfoIcon;\r\n scope.hasSecondInfoIcon = hasSecondInfoIcon;\r\n scope.getTextColor = getTextColor;\r\n scope.getFirstActionIcon = getFirstActionIcon;\r\n scope.hasFirstActionIcon = hasFirstActionIcon;\r\n scope.getSecondActionIcon = getSecondActionIcon;\r\n scope.hasSecondActionIcon = hasSecondActionIcon;\r\n scope.getFetchIcon = getFetchIcon;\r\n scope.getInfoMessage = getInfoMessage;\r\n scope.firstAction = firstAction;\r\n scope.secondaryAction = secondaryAction;\r\n scope.showEndDate = showEndDate;\r\n scope.showTime = showTime;\r\n\r\n\r\n if(scope.duty.Comments && scope.duty.Comments != \"\"){\r\n scope.dutyCommentElipsis = dutyCommentElipsis(110);\r\n scope.showFullComment = false;\r\n }\r\n \r\n scope.toggleFullCommentVisibility = toggleFullCommentVisibility;\r\n\r\n /**\r\n * Toggles proposal comment\r\n * @memberof proposal\r\n */\r\n function toggleFullCommentVisibility(){\r\n scope.showFullComment = !scope.showFullComment;\r\n }\r\n\r\n /**\r\n * Shows only the first charNo characters of the comment\r\n * @memberof proposal\r\n * @param {number} charNo \r\n */\r\n function dutyCommentElipsis(charNo){\r\n var comments = scope.duty.Comments;\r\n if(scope.duty.Comments.length > charNo){\r\n comments = scope.duty.Comments.substring(0,charNo) + \"...\";\r\n }\r\n return comments;\r\n }\r\n\r\n /**\r\n * Updates proposal when a change occurs (create, evaluate or undo)\r\n * @memberof proposal\r\n * @param {object} newProp - The updated proposal \r\n */\r\n function updateProposal(newProp){\r\n if(newProp){\r\n scope.proposal.Status = newProp.Status;\r\n scope.proposal.State = newProp.State;\r\n scope.proposal.Id = newProp.Id;\r\n scope.proposal.isAcknowledged = newProp.isAcknowledged;\r\n } \r\n }\r\n \r\n /**\r\n * Fetches proposal info (Proposed and Requested duties alongside Crew and Route details for each one) \r\n * @memberof proposal\r\n */\r\n function fetchInformation(){\r\n if(!(scope.actionDisabled && scope.proposal.Status == 'Shared')){\r\n //only fetch the first time\r\n if(!(scope.proposal.AllDuties && scope.proposal.AllDuties.length>0)){\r\n scope.loading = true;\r\n if(scope.proposal.Status == \"Shared\" && !scope.actionDisabled){\r\n\r\n BucketFactory.fetchSharedProposal(scope.currentDutyId, scope.duty.Id, insertInformation )\r\n .catch(errorCall);\r\n }else{\r\n BucketFactory.fetchProposal(scope.proposal.Id, insertInformation)\r\n .catch(errorCall);\r\n }\r\n }else{\r\n scope.isOpen = !scope.isOpen; //collapse\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Handles error from fetchSharedProposal() and fetchProposal() \r\n * @memberof proposal\r\n */\r\n function errorCall(){\r\n scope.isOpen = false;\r\n scope.loading = false;\r\n displayMessage(\"Failed to fetch information.\", true);\r\n }\r\n\r\n /**\r\n * Callback for handling the successful response of fetchSharedProposal() and fetchProposal()\r\n * @memberof proposal\r\n * @param {object} data \r\n */\r\n function insertInformation(data){\r\n var success = data.data.success;\r\n var errorMessage = data.data.errorMessage;\r\n //always show duties even if success is false\r\n if(data.data.data.duty){\r\n var ProposedDuties = data.data.data.duty.ProposedDuties;\r\n var RequestedDuties = data.data.data.duty.RequestedDuties;\r\n scope.proposal.HasMultiDuties = data.data.data.duty.HasMultiDuties;\r\n\r\n ProposedDuties = $filter('orderBy')(ProposedDuties, 'DutyDate');\r\n RequestedDuties = $filter('orderBy')(RequestedDuties, 'DutyDate');\r\n\r\n if(ProposedDuties && RequestedDuties){\r\n scope.proposal.AllDuties = []; \r\n var tableMaxRowLength = (ProposedDuties.length > RequestedDuties.length) ? ProposedDuties.length : RequestedDuties.length;\r\n \r\n for(var i = 0; i < tableMaxRowLength; i++){\r\n \r\n if(scope.proposal.Status == \"Shared\" || scope.proposal.State == \"Out\"){\r\n var matchedDuty = {\r\n Proposed : ProposedDuties[i], //you give\r\n Requested : RequestedDuties[i] //you take\r\n };\r\n }\r\n else{ //scope.proposal.State == \"In\"\r\n var matchedDuty = {\r\n Proposed : RequestedDuties[i], //you give\r\n Requested : ProposedDuties[i] //you take\r\n };\r\n }\r\n \r\n scope.proposal.AllDuties.push(matchedDuty);\r\n } \r\n \r\n scope.proposal.ProposedDuties = ProposedDuties;\r\n scope.proposal.RequestedDuties = RequestedDuties;\r\n scope.isOpen = true; \r\n }\r\n }\r\n\r\n if(!success){\r\n //if not enough rest time\r\n //if no available combinations\r\n scope.proposal.createDisabled = true;\r\n }else{\r\n scope.proposal.createDisabled = false;\r\n }\r\n\r\n //always show errorMessage even if success is true\r\n if(errorMessage && errorMessage.length > 0){\r\n displayMessage(errorMessage, true);\r\n }\r\n else{\r\n scope.errorMessage = null;\r\n }\r\n \r\n\r\n scope.loading = false;\r\n }\r\n \r\n /**\r\n * Opens modal for a specific duty in the table - Shows route and crew info \r\n * @memberof proposal\r\n * @param {number} id \r\n */\r\n function viewInfoModal(id){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Bucket/dlgProposalInfo.html',\r\n controller: 'ProposalInfoModalCtr',\r\n size: 'lg',\r\n resolve: {\r\n ProposedDuties: function () { return scope.proposal.ProposedDuties; },\r\n RequestedDuties: function () { return scope.proposal.RequestedDuties; },\r\n Id: function () {return id; },\r\n Status: function () { return scope.proposal.Status; },\r\n State: function () { return scope.proposal.State; }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Creates/Sends proposal\r\n * @memberof proposal\r\n */\r\n function createProposal(){\r\n var proposedDutiesIdList = [];\r\n var requestedDutiesIdList = [];\r\n\r\n angular.forEach(scope.proposal.ProposedDuties,function(duty){\r\n proposedDutiesIdList.push(duty.Id);\r\n });\r\n\r\n angular.forEach(scope.proposal.RequestedDuties,function(duty){\r\n requestedDutiesIdList.push(duty.Id);\r\n });\r\n\r\n\r\n //request body\r\n var proposal = {\r\n 'proposedDutiesIdList' : proposedDutiesIdList,\r\n 'requestedDutiesIdList' : requestedDutiesIdList\r\n };\r\n\r\n scope.loading = true;\r\n\r\n BucketFactory.createProposal(proposal, function (responseData) {\r\n displayMessage(\"Proposal has been sent\", false);\r\n scope.loading = false;\r\n updateProposal(responseData.data.data);\r\n if(scope.proposal.HasMultiDuties){ \r\n scope.refresh(); //needed in order to hide other duty from same proposal\r\n }\r\n })\r\n .catch(function(){\r\n displayMessage(\"Failed to sent proposal.\", true);\r\n scope.loading = false;\r\n });\r\n }\r\n\r\n /**\r\n * Approves/Rejects proposal\r\n * @memberof proposal\r\n * @param {boolean} isApproved\r\n */\r\n function evaluateProposal(isApproved){\r\n var proposal = {};\r\n proposal.Id = scope.proposal.Id;\r\n proposal.isApproved = isApproved;\r\n \r\n var onSuccessMessage, onFailureMessage;\r\n \r\n if(isApproved){\r\n proposal.Status = \"Approved\";\r\n var onSuccessMessage = \"Approved proposal.\";\r\n var onFailureMessage = \"Failed to approve proposal.\";\r\n }\r\n else{\r\n proposal.Status = \"Rejected\";\r\n var onSuccessMessage = \"Rejected proposal.\";\r\n var onFailureMessage = \"Failed to reject proposal.\";\r\n }\r\n \r\n scope.loading = true;\r\n BucketFactory.evaluateProposal(proposal).then(function (responseData) {\r\n var success = responseData.data.success;\r\n if(success){\r\n var newProp = responseData.data.data;\r\n updateProposal(newProp);\r\n if(isApproved){\r\n scope.refresh(); //needed in order to disable other proposals\r\n }\r\n displayMessage(onSuccessMessage,false);\r\n }else{\r\n displayMessage(onFailureMessage,true);\r\n }\r\n })\r\n .catch(function(){\r\n displayMessage(onFailureMessage,true);\r\n });\r\n\r\n scope.loading = false;\r\n }\r\n\r\n /**\r\n * Reverts proposal to previous status\r\n * @memberof proposal\r\n */\r\n function undoProposalStatus(){\r\n scope.loading = true;\r\n var proposal = {};\r\n proposal.Id = scope.proposal.Id;\r\n\r\n var onSuccessMessage, onFailureMessage;\r\n\r\n if((scope.proposal.Status == \"Approved\") ||\r\n (scope.proposal.Status == \"Rejected\" && scope.proposal.State=='In')){\r\n var onSuccessMessage = \"Proposal has been reset.\";\r\n var onFailureMessage = \"Failed to reset proposal.\";\r\n }else{ //(scope.proposal.Status == \"Pending\" && scope.proposal.State=='Out')\r\n var onSuccessMessage = \"Withdrew proposal.\";\r\n var onFailureMessage = \"Failed to withraw proposal.\";\r\n }\r\n\r\n \r\n BucketFactory.undoProposalStatus(proposal.Id).then(function (responseData) {\r\n var previousStatus = scope.proposal.Status;\r\n var HasMultiDuties = scope.proposal.HasMultiDuties;\r\n var newProp = responseData.data.data;\r\n displayMessage(onSuccessMessage, false);\r\n scope.loading = false;\r\n updateProposal(newProp);\r\n if(previousStatus == \"Approved\"){\r\n scope.refresh(); //needed in order to enable other proposals again \r\n }\r\n else if(previousStatus == \"Pending\" && HasMultiDuties){\r\n scope.refresh(); //needed in order to show other duties from same proposal \r\n }\r\n })\r\n .catch(function(){\r\n scope.loading = false;\r\n displayMessage(onFailureMessage,true);\r\n });\r\n\r\n }\r\n\r\n /**\r\n * Displays error or success message\r\n * @memberof proposal\r\n * @param {string} message \r\n * @param {boolean} hasErrors \r\n */\r\n function displayMessage(message, hasErrors){\r\n \r\n if(hasErrors){\r\n scope.errorMessage = message;\r\n }else{\r\n scope.errorMessage = null;\r\n }\r\n }\r\n \r\n /**\r\n * Makes proposal acknowledged \r\n * Available when status is 'RejectedBySTP' or status is 'Rejected' and state is 'Out'\r\n * @memberof proposal\r\n */\r\n function acknowledgeProposal(){\r\n scope.loading = true;\r\n var proposalId = scope.proposal.Id;\r\n var onFailureMessage = \"Failed to acknowledge proposal.\";\r\n \r\n BucketFactory.acknowledgeProposal(proposalId).then(function (responseData) {\r\n scope.proposal.isAcknowledged = true;\r\n scope.loading = false;\r\n })\r\n .catch(function(){\r\n scope.loading = false;\r\n displayMessage(onFailureMessage, true);\r\n });\r\n }\r\n \r\n /**\r\n * Changes proposal's first info icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\r\n function getFirstInfoIcon(){\r\n var icon = \"\"\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' ){\r\n icon=\"fa-thumbs-up\";\r\n }else if(scope.proposal.Status == \"Rejected\"){\r\n icon=\"fa-thumbs-down\";\r\n }else if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n icon=\"fa-thumbs-o-up\";\r\n }else if ( scope.proposal.Status == \"Shared\"){\r\n icon=\"fa-bitbucket\";\r\n }else if(scope.proposal.Status == \"Approved\"){\r\n icon = \"fa fa-handshake-o\"\r\n }else if ( scope.proposal.Status == \"ApprovedBySTP\"){\r\n icon=\"fa-thumbs-up\";\r\n }else if(scope.proposal.Status == \"RejectedBySTP\"){\r\n icon=\"fa-thumbs-o-down\";\r\n }\r\n return icon;\r\n }\r\n\r\n /**\r\n * Changes proposal's second info icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\r\n function getSecondInfoIcon(){\r\n var icon = \"\"\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' ){\r\n icon=\"fa-clock-o text-gray\";\r\n }else if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n icon=\"fa-question-circle-o\";\r\n }\r\n return icon;\r\n } \r\n\r\n /**\r\n * Determines second info icon's visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\r\n function hasSecondInfoIcon(){\r\n return (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In' ) ||(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out'); \r\n }\r\n\r\n /**\r\n * Changes column color depending on proposal's state and status\r\n * @memberof proposal\r\n * @returns {string} - Color's class\r\n */\r\n function getTextColor(){\r\n var textclass=\"\";\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' ){\r\n textclass=\"text-light-blue\";\r\n }else if(scope.proposal.Status == \"Rejected\"){\r\n textclass=\"text-red\";\r\n }else if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n textclass=\"text-orange\";\r\n }else if(scope.proposal.Status == \"Approved\" ){\r\n textclass=\"text-green\";\r\n }else if ( scope.proposal.Status == \"Shared\"){\r\n textclass=\"text-blue-gray\";\r\n }else if ( scope.proposal.Status == \"ApprovedBySTP\"){\r\n textclass=\"text-green\";\r\n }else if(scope.proposal.Status == \"RejectedBySTP\"){\r\n textclass=\"text-red\";\r\n }\r\n return textclass;\r\n }\r\n\r\n /**\r\n * Changes proposal's first action icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\r\n function getFirstActionIcon(){\r\n var icon = \"\"\r\n if(scope.proposal.createDisabled){\r\n icon = \"fa-ban text-red\"; //no action permitted\r\n }else if((scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' )\r\n ||scope.proposal.Status == \"Approved\" ){\r\n icon=\" fa-times text-gray \"; //undo\r\n }else if(scope.proposal.Status == \"Rejected\" && scope.proposal.State == \"In\"){\r\n icon=\" fa-times text-gray \"; //undo\r\n }else if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In' && !scope.actionDisabled){\r\n icon=\"fa-thumbs-o-up text-green\"; //approve\r\n }else if ( scope.proposal.Status == \"Shared\" && !scope.actionDisabled){\r\n icon=\"fa-thumbs-o-up text-light-blue\"; //create\r\n }\r\n \r\n return icon;\r\n }\r\n \r\n /**\r\n * Changes proposal's fetch icon if create action is disabled \r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\r\n function getFetchIcon(){\r\n var icon = \"\";\r\n if(scope.proposal.createDisabled){\r\n icon = \"fa-ban text-red\";\r\n }\r\n else{\r\n icon = \"fa-search\";\r\n }\r\n return icon;\r\n }\r\n\r\n /**\r\n * Changes proposal's second action icon depending on its state and status\r\n * @memberof proposal\r\n * @returns {string} - Icon name\r\n */\r\n function getSecondActionIcon(){\r\n var icon = \"\"\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n icon=\"fa-thumbs-o-down text-red\"; //reject\r\n }\r\n return icon;\r\n\r\n } \r\n \r\n /**\r\n * Determines first action icon's visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\r\n function hasFirstActionIcon(){\r\n return !( scope.proposal.Status == \"ApprovedBySTP\" || scope.proposal.Status == \"RejectedBySTP\") ;\r\n }\r\n \r\n /**\r\n * Determines second action icon's visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\r\n function hasSecondActionIcon(){\r\n return (scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In') || ( scope.proposal.Status == \"Shared\");\r\n }\r\n \r\n /**\r\n * Returns info message depending on proposal's state and status\r\n * @memberof proposal\r\n * @returns {string} - Message\r\n */\r\n function getInfoMessage(){\r\n var text=\"\";\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' ){\r\n text=\"your proposal is pending\";\r\n }else if(scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'Out'){\r\n text=\"your proposal has been rejected\";\r\n }\r\n else if(scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'In'){\r\n text=\"you have rejected the proposal\";\r\n }else if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n text=\"your response is pending\";\r\n }else if(scope.proposal.Status == \"Approved\" && scope.proposal.State == 'In' ){\r\n text=\"you have accepted the proposal. Your request is sent for approval\";\r\n }else if(scope.proposal.Status == \"Approved\" && scope.proposal.State == 'Out' ){\r\n text=\"your proposal has been accepted! Your request is sent for approval\";\r\n }else if ( scope.proposal.Status == \"ApprovedBySTP\"){\r\n text=\"your request has been approved!\";\r\n }else if(scope.proposal.Status == \"RejectedBySTP\"){\r\n text=\"your request has been rejected by STP\";\r\n }\r\n \r\n return text;\r\n }\r\n\r\n /**\r\n * Determines duty's endDate visibility\r\n * @memberof proposal\r\n * @returns {boolean}\r\n */\r\n function showEndDate(duty){\r\n var show = false;\r\n var diffMin = Date.DifferenceInMinutes(duty.DutyBegin, duty.DutyEnd);\r\n var diffHours = diffMin / 60;\r\n if(diffHours >= 24){ //endDate will show if duty exceeds 24 hours\r\n show = true;\r\n }\r\n return show;\r\n }\r\n\r\n /**\r\n * Hides duty begin and end time if needed\r\n * @param {object} duty \r\n */\r\n function showTime(duty){\r\n var show = true;\r\n var diffMin = Date.DifferenceInMinutes(duty.DutyBegin, duty.DutyEnd);\r\n if(!diffMin){ //Time will not show if duty lasts all day (ex. Day Off: 00:00 - 00:00)\r\n show = false;\r\n }\r\n return show;\r\n }\r\n\r\n /**\r\n * Chooses first icon's action depending on proposal's state and status\r\n * @memberof proposal\r\n */\r\n function firstAction(){\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'Out' ){\r\n undoProposalStatus();\r\n }else if(scope.proposal.Status == \"Approved\" ){\r\n confirmUndoApproved();\r\n }else if(scope.proposal.Status == \"Rejected\" && scope.proposal.State == 'In'){\r\n undoProposalStatus();\r\n }else if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n evaluateProposal(true); //approve\r\n }else if( scope.proposal.Status == \"Shared\" && !scope.proposal.createDisabled){\r\n if(scope.errorMessage && scope.errorMessage.length > 0){\r\n confirmCreateProposal(); //fetch success with errorMessage\r\n }\r\n else{\r\n createProposal();\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Chooses second icon's action depending on proposal's state and status\r\n * @memberof proposal\r\n */\r\n function secondaryAction(){\r\n if(scope.proposal.Status == \"Pending\" && scope.proposal.State == 'In'){\r\n evaluateProposal(false); // reject proposal\r\n }\r\n }\r\n\r\n /**\r\n * Opens confirmation modal when undo is requested on an approved proposal\r\n * @memberof proposal\r\n */\r\n function confirmUndoApproved() {\r\n bootbox.dialog({\r\n message: \"You are about to cancel your accepted proposal.

\",\r\n title: \"Caution!\",\r\n buttons: {\r\n confirm:{\r\n label: 'Confirm',\r\n className: \"btn-danger\",\r\n callback: function(){\r\n undoProposalStatus();\r\n }\r\n }, \r\n cancel:{\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function(){}\r\n }\r\n }\r\n })\r\n }\r\n \r\n /**\r\n * Opens confirmation modal when create is requested on an alternate proposal\r\n * @memberof proposal\r\n */\r\n function confirmCreateProposal() {\r\n bootbox.dialog({\r\n message: \"Would you like to proceed with the alternate proposal?

\",\r\n title: \"Send request\",\r\n buttons: {\r\n confirm:{\r\n label: 'Confirm',\r\n className: \"btn-success\",\r\n callback: function(){\r\n createProposal();\r\n }\r\n }, \r\n cancel:{\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function(){}\r\n }\r\n }\r\n })\r\n } \r\n\r\n }\r\n \r\n return {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n templateUrl: 'views/bucket/proposal.tpl.html',\r\n\t\t\tscope : {\r\n proposal: '=',\r\n displayMessage : '&onDisplay',\r\n refresh : '&onRefresh',\r\n actionDisabled: '=',\r\n currentDutyDate: '=',\r\n currentDutyId : '=',\r\n sharedCount : '='\r\n },\r\n link: link\r\n }\r\n}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('ProposalInfoModalCtr', ProposalInfoModalCtr)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ProposalInfoModalCtr\r\n * @description \r\n * Shows duty crew and route info\r\n * @ngInject\r\n */\r\n\r\n function ProposalInfoModalCtr($scope, $uibModalInstance, ProposedDuties, RequestedDuties, Id, Status, State){\r\n $scope.RequestedDuties = RequestedDuties;\r\n $scope.ProposedDuties = ProposedDuties;\r\n\r\n $scope.cancel = cancel; \r\n $scope.next = next;\r\n $scope.previous = previous;\r\n\r\n var allDuties = [];\r\n\r\n //\"You give\" items are put first in list\r\n if(Status == \"Shared\" || State == \"Out\"){\r\n allDuties = ProposedDuties.concat(RequestedDuties);\r\n }\r\n else{ //State == \"In\"\r\n allDuties = RequestedDuties.concat(ProposedDuties);\r\n }\r\n \r\n for(var i = 0; i < allDuties.length; i++){\r\n if(allDuties[i].Id == Id){\r\n $scope.currentPage = i+1;\r\n break;\r\n }\r\n }\r\n\r\n $scope.allDuties = allDuties;\r\n \r\n /**\r\n * Moves to next duty\r\n * @memberof ProposalInfoModalCtr\r\n */\r\n function next(){\r\n if($scope.currentPage != allDuties.length)\r\n $scope.currentPage++;\r\n }\r\n\r\n /**\r\n * Moves to previous duty\r\n * @memberof ProposalInfoModalCtr\r\n */\r\n function previous(){\r\n if($scope.currentPage != 1)\r\n $scope.currentPage--;\r\n }\r\n\r\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\r\n function cancel() {\r\n $uibModalInstance.close('cancel');\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('DataCleanerFactory', DataCleanerFactory)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name DataCleanerFactory\r\n * @description \r\n * Cleans the Data of the application\r\n * @ngInject\r\n */\r\n function DataCleanerFactory(localStorageMD5Service, IndexedDBService, GenericService) {\r\n var objCallbackRatings = objCallbackRatings;\r\n\r\n var service = {\r\n deleteAllReports: deleteAllReports,\r\n deleteAllServerData: deleteAllServerData,\r\n deleteAllData: deleteAllData,\r\n deleteOrphanedLocalFlights: deleteOrphanedLocalFlights,\r\n deleteOrphanedLocalReports: deleteOrphanedLocalReports,\r\n deleteSynchedLocalPilotReports: deleteSynchedLocalPilotReports,\r\n deleteOldCrewMealsRatings:deleteOldCrewMealsRatings\r\n }\r\n /**\r\n * Delete All Cabin Reports\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteAllReports() {\r\n localStorageMD5Service.remove('pilotReportLocalEdits');\r\n localStorageMD5Service.remove('pilotReportLocalEdit_TEMP');\r\n deleteOrphanedLocalFlights();\r\n };\r\n\r\n /**\r\n * Delete Basic Server data\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteAllServerData() {\r\n localStorageMD5Service.remove('flights');\r\n localStorageMD5Service.remove('reportGuids');\r\n localStorageMD5Service.remove('aircraftTypes');\r\n localStorageMD5Service.remove('pilotReportTemplate');\r\n localStorageMD5Service.remove('syncLog');\r\n localStorageMD5Service.remove('pilotReportSyncResults');\r\n localStorageMD5Service.remove('FAQItem');\r\n localStorageMD5Service.remove('PaxInfo');\r\n localStorageMD5Service.remove('aircaftpositions');\r\n localStorageMD5Service.remove('scheduleChanges');\r\n localStorageMD5Service.remove('CheckIn');\r\n localStorageMD5Service.remove('flightCheckIns');\r\n\r\n \r\n deleteOrphanedLocalFlights();\r\n };\r\n\r\n /**\r\n * Delete All Server data\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteAllData() {\r\n localStorageMD5Service.clearAll();\r\n\r\n IndexedDBService.deleteDatabase();\r\n };\r\n\r\n /**\r\n * Delete local flights that have no stored local reports\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteOrphanedLocalFlights() {\r\n\r\n var existingLocalFlights = localStorageMD5Service.get('localFlights');\r\n if (existingLocalFlights == null)\r\n return;\r\n\r\n var finalLocalFlights = new Array();\r\n\r\n var pilotReportLocalEdits = localStorageMD5Service.get('pilotReportLocalEdits');\r\n if (pilotReportLocalEdits == null)\r\n pilotReportLocalEdits = new Array();\r\n\r\n // check every local flight that has a saved pilot report\r\n for (var i = 0; i < existingLocalFlights.length; i++) {\r\n\r\n var hasPilotReport = false;\r\n\r\n for (var j = 0; j < pilotReportLocalEdits.length; j++) {\r\n\r\n if ((pilotReportLocalEdits[j].FlightId != null && pilotReportLocalEdits[j].FlightId == existingLocalFlights[i].FlightId) || (pilotReportLocalEdits[j].FlightAimsId != null && pilotReportLocalEdits[j].FlightAimsId == existingLocalFlights[i].FlightAimsId)) {\r\n hasPilotReport = true;\r\n break;\r\n }\r\n\r\n }\r\n\r\n // if it has a pilot report, add it to the flights to save\r\n if (hasPilotReport)\r\n finalLocalFlights.push(existingLocalFlights[i]);\r\n }\r\n\r\n // save the resulting local flights\r\n localStorageMD5Service.set('localFlights', finalLocalFlights);\r\n }\r\n\r\n /**\r\n * Delete local reports that have no stored local flights\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteOrphanedLocalReports() {\r\n var existingLocalPilotReports = localStorageMD5Service.get('pilotReportLocalEdits');\r\n var flights = localStorageMD5Service.get('flights');\r\n\r\n if (existingLocalPilotReports == null || flights == null || existingLocalPilotReports.length == 0 || flights.length == 0)\r\n return 0;\r\n\r\n var finalLocalPilotReports = new Array();\r\n\r\n for (var i = 0; i < existingLocalPilotReports.length; i++) {\r\n var remove = false;\r\n\r\n if (existingLocalPilotReports[i].Status == 'synched') {\r\n remove = true;\r\n if (existingLocalPilotReports[i].FlightId != null || existingLocalPilotReports[i].FlightAimsId != null) {\r\n for (var j = 0; j < flights.length; j++) {\r\n if (\r\n (existingLocalPilotReports[i].FlightId != null && existingLocalPilotReports[i].FlightId == flights[j].FlightId) || (existingLocalPilotReports[i].FlightAimsId != null && existingLocalPilotReports[i].FlightAimsId == flights[j].FlightAimsId)\r\n ) {\r\n remove = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!remove)\r\n finalLocalPilotReports.push(existingLocalPilotReports[i]);\r\n }\r\n\r\n // save the resulting local reports\r\n localStorageMD5Service.set('pilotReportLocalEdits', finalLocalPilotReports);\r\n\r\n }\r\n\r\n /**\r\n * Delete Synched Local PilotReports\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteSynchedLocalPilotReports() {\r\n\r\n var existingLocalPilotReports = localStorageMD5Service.get('pilotReportLocalEdits');\r\n var flights = localStorageMD5Service.get('flights');\r\n if (existingLocalPilotReports == null || flights == null || existingLocalPilotReports.length == 0 || flights.length == 0)\r\n return 0;\r\n\r\n var finalLocalPilotReports = new Array();\r\n var deleted = 0;\r\n var flight = null;\r\n\r\n var user = localStorageMD5Service.get('user');;\r\n // check every saved cabin report\r\n for (var i = 0; i < existingLocalPilotReports.length; i++) {\r\n\r\n var remove = false;\r\n\r\n if (existingLocalPilotReports[i].Status == 'synched') {\r\n if (existingLocalPilotReports[i].FlightId != null || existingLocalPilotReports[i].FlightAimsId != null) {\r\n for (var j = 0; j < flights.length; j++) {\r\n if (\r\n (existingLocalPilotReports[i].FlightId != null && existingLocalPilotReports[i].FlightId == flights[j].FlightId) || (existingLocalPilotReports[i].FlightAimsId != null && existingLocalPilotReports[i].FlightAimsId == flights[j].FlightAimsId)\r\n ) {\r\n for (var h = 0; h < flights[j].pilotReports.length; h++) {\r\n if (flights[j].pilotReports[h].AuthorAimsId == user.aimsId) {\r\n remove = true;\r\n deleted++;\r\n }\r\n\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!remove)\r\n finalLocalPilotReports.push(existingLocalPilotReports[i]);\r\n }\r\n\r\n // save the resulting local reports\r\n localStorageMD5Service.set('pilotReportLocalEdits', finalLocalPilotReports);\r\n\r\n return deleted;\r\n }\r\n\r\n /**\r\n * Deletes CrewMealRatings that are older than 20 days\r\n * @memberof DataCleanerFactory\r\n */\r\n function deleteOldCrewMealsRatings(){\r\n var res = GenericService.list(\"CrewMealRatings\", objCallbackRatings);\r\n var lastDate = new Date();\r\n lastDate.setDate(lastDate.getDate() - 20);\r\n var crewMealIdsFiltered = res.filter(r => new Date(r.TimeStamp) >= lastDate);\r\n GenericService.saveOne(crewMealIdsFiltered,\"CrewMealRatings\");\r\n }\r\n\r\n function objCallbackRatings(){\r\n this.CrewMealId = null,\r\n this.TimeStamp = null\r\n }\r\n\r\n return service;\r\n };\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.filter('fltSplit',fltSplit) \r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name messageFilter\r\n * @description \r\n * Filters messages in order to show only the unread.\r\n * @ngInject\r\n */\r\nfunction fltSplit() {\r\n\t\treturn function(fltSplit) {\r\n var formattedFltNo = fltSplit;\r\n if(typeof fltSplit === 'string' || fltSplit instanceof String){\r\n formattedFltNo = fltSplit.replace(/(\\w{2})/, '$1 ');\r\n }\r\n\t\t\treturn formattedFltNo;\r\n\t\t};\r\n\t}\r\n})();","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.factory('GenericService', GenericService);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GenericService\r\n * @description \r\n * Generic add, edit or remove\r\n * @ngInject\r\n */\r\n function GenericService(localStorageMD5Service) {\r\n\r\n\t\tvar objectType = null ;\r\n\t\tvar objectCallback = null;\r\n\t\t\r\n\t\tvar service = \r\n\t\t{\r\n\t\t\tinitiate : initiate,\r\n\t\t\tget : get,\r\n\t\t\tgetOne : getOne,\r\n\t\t\tlist : list,\r\n\t\t\tsave : save,\r\n\t\t\tsaveOne : saveOne,\r\n\t\t\tsaveAll : saveAll,\r\n\t\t\tremove : remove,\r\n\t\t\tremoveAll : removeAll,\r\n\t\t\tadd : add,\r\n\t\t\tconstructor : constructor,\r\n\t\t\tfromObject : fromObject,\r\n\t\t\tfromObjectList : fromObjectList\r\n\t\t};\r\n\r\n /**\r\n * initiate type and callback\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @memberof GenericService\r\n */\r\n\t\tfunction initiate(type,callback){\r\n\t\t\tobjectType = type;\r\n\t\t\tobjectCallback = callback;\r\n\t\t}\r\n\t\t\r\n /**\r\n * Get the requested object\r\n * @memberof GenericService\r\n * @param {number} id The unique identifier\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} result\r\n */\r\n\t\tfunction get(id,type,callback){\r\n\t\t\tinitiate(type,callback);\r\n\t\t\tvar objects = list(type,callback);\r\n\t\t\tif (objects == null)\r\n\t\t\t\treturn null;\r\n\t\t\r\n\t\t\tvar result = null;\r\n\t\t\r\n\t\t\tvar arrayLength = objects.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (objects[i].GetId() == id)\t{\r\n\t\t\t\t\tresult = objects[i];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn result;\r\n\t\t}\r\n\r\n /**\r\n * Get all the objects\r\n * @memberof GenericService\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {array} objectList\r\n */\r\n\t\tfunction list(type,callback){\r\n\t\t\tinitiate(type,callback);\r\n\t\t\tvar objects = localStorageMD5Service.get(objectType);\r\n\t\t\treturn fromObjectList(objects,callback);\r\n\t\t}\r\n\r\n \r\n /**\r\n * Get the unique object of this storage\r\n * @memberof GenericService\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @return {object} object\r\n */\r\n\t\tfunction getOne(type,callback){\r\n\t\t\tinitiate(type,callback);\r\n\t\t\tvar object = localStorageMD5Service.get(objectType);\r\n\t\t\treturn fromObject(object,callback);\r\n\t\t}\r\n\t\t\t\t\r\n\t\tfunction saveOne(obj,type,callback){\r\n\t\t\tlocalStorageMD5Service.set(type,obj);\r\n\t\t}\r\n\r\n\t\tfunction save(object,type,callback){\r\n\t\t\tinitiate(type,callback)\r\n\t\t\tvar objects = list(type,callback);\r\n\t\t\tvar updatedobject = fromObject(object,callback);\r\n\r\n\t\t\tvar arrayLength = objects.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (objects[i].GetId() == updatedobject.GetId())\t{\r\n\t\t\t\t\tobjects[i] = updatedobject;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\tsaveAll(objects,type,callback);\r\n\t\t}\r\n\r\n\t\tfunction saveAll(objects,type,callback){\r\n\t\t\tinitiate(type,callback);\r\n\t\t\tlocalStorageMD5Service.set(objectType,objects);\r\n\t\t}\r\n\r\n\t\tfunction remove(Id,type,callback){\r\n\t\t\tinitiate(type,callback);\r\n\t\t\tvar objects = list(type,callback);\r\n\t\t\tvar newObjects = [];\r\n\t\t\t\t\r\n\t\t\tvar arrayLength = objects.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (objects[i].GetId() != Id)\t{\r\n\t\t\t\t\tnewObjects.push(objects[i])\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\r\n\t\t\tsaveAll(newObjects,type,callback);\r\n\t\t}\r\n\r\n\t\tfunction removeAll(type,callback){\r\n\t\t\tinitiate(type,callback);\r\n\t\t\tlocalStorageMD5Service.remove(objectType);\r\n\t\t}\r\n\t\t\r\n\t\tfunction add(obj,type,callback){\r\n\t\t\tvar objects = list(type,callback);\r\n\t\t\tobjects.push(obj);\r\n\t\t\tsaveAll(objects,type,callback);\r\n\t\t}\r\n\t\t\r\n\t\tfunction constructor(callback){\r\n\t\t\tvar object = new callback();\r\n\t\t\treturn object;\r\n\t\t}\r\n\t\t\r\n\t\tfunction fromObject(obj,callback){\r\n\t\t\tif (obj==null) return null;\r\n\t\t\tvar object = new callback();\r\n\t\t\tangular.extend(object, obj);\r\n\t\t\treturn object;\r\n\t\t}\r\n\t\t\r\n\t function fromObjectList(objList,callback) {\r\n\t\tif (objList==null)\r\n\t\t\treturn [];\r\n\t\t\r\n\t\tvar arrayLength = objList.length;\r\n\t\tvar objects = new Array();\r\n\t\t\r\n\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\tobjects.push(fromObject(objList[i],callback));\r\n\t\t}\r\n\t\t\r\n\t\treturn objects;\r\n\t}\r\n\r\n\treturn service;\r\n\t}\r\n\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.factory('GenericModalFactory', GenericModalFactory)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GenericModalFactory\r\n * @description \r\n * Initialize generic Modals\r\n * @ngInject\r\n */ \r\n function GenericModalFactory() {\r\n\t\t\r\n\t\tvar service = {\r\n\t\t\tcreateNew : createNew,\r\n\t\t\tfromObject : fromObject,\r\n\t\t\tdeleteFromList : deleteFromList,\r\n\t\t\tfromObjectList : fromObjectList\r\n\t\t}\r\n\t\t\t\r\n /**\r\n * Greate new Object based on given constructor\r\n * @memberof GenericModalFactory\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} result\r\n */\r\n\t\tfunction createNew(callback) {\r\n\t\t\tvar result = new callback();\r\n\t\t\tresult.Id = guid();\r\n\t\t\treturn result;\r\n\t\t}\r\n \r\n /**\r\n * Extend given object \r\n * @memberof GenericModalFactory\r\n * @param {object} obj The object that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} object\r\n */\r\n\t\tfunction fromObject(obj,callback) {\r\n\t\t\tif (obj == null) return null;\r\n\t\t\tvar object = new callback();\r\n\t\t\tangular.extend(object, obj);\r\n\t\t\treturn object;\r\n\t\t}\r\n\r\n /**\r\n * Delete an object from given List\r\n * @memberof GenericModalFactory\r\n * @param {object} obj The object that will be removed\r\n * @param {array} objList A list that will be modified\r\n * @returns {array} objList\r\n */\r\n\t\tfunction deleteFromList(obj, objList) {\r\n\r\n\t\t\t// find the current item in the array (if present)\r\n\t\t\tvar arrayLength = objList.length;\r\n\t\t\tvar itemIndex = -1;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (objList[i].Id == obj.Id) {\r\n\t\t\t\t\titemIndex = i;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\tif (itemIndex >= 0)\r\n\t\t\t\tobjList.splice(itemIndex, 1);\r\n\r\n\t\t\treturn objList;\r\n\t\t}\r\n\t\t \r\n /**\r\n * Extend given object list\r\n * @memberof GenericModalFactory\r\n * @param {array} objList The list of objects that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} objList\r\n */\r\n\t\tfunction fromObjectList(objList,callback) {\r\n\t\t\tif (objList == null) return [];\r\n\r\n\t\t\tvar arrayLength = objList.length;\r\n\t\t\tvar newobjList = []\r\n\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tvar obj = new callback();\r\n\t\t\t\tangular.extend(obj, objList[i]);\r\n\t\t\t\tnewobjList.push(obj);\r\n\t\t\t}\r\n\r\n\t\t\treturn newobjList;\r\n\t\t}\r\n\r\n\treturn service;\r\n \t}\r\n\r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.factory('GenericValuesFactory', GenericValuesFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GenericValuesFactory\r\n * @description \r\n * Generic add, edit or remove for list of values\r\n * @ngInject\r\n */ \r\n function GenericValuesFactory(localStorageMD5Service) {\r\n\t\t \r\n\t\tvar service = {\r\n\t\t\tfromObject : fromObject,\r\n\t\t\tfromObjectList : fromObjectList,\r\n\t\t\tobjList : objList,\r\n\t\t\tgetValuesFromStorage : getValuesFromStorage,\r\n\t\t\tsetValuesToStorage : setValuesToStorage,\r\n\t\t\tclearValuesFromStorage : clearValuesFromStorage,\r\n\t\t\tgetValuesFromStorageAsStrings : getValuesFromStorageAsStrings\r\n\t\t}\r\n \r\n /**\r\n * Extend given object \r\n * @memberof GenericValuesFactory\r\n * @param {object} obj The object that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} object\r\n */\r\n\t\tfunction fromObject(obj,callback) {\r\n\t\t\tif (obj == null) return null;\r\n\t\t\tvar newObj = new callback();\r\n\t\t\tnewObj.Code = obj;\r\n\t\t\treturn newObj;\r\n\t\t}\r\n \r\n /**\r\n * Extend given object list\r\n * @memberof GenericValuesFactory\r\n * @param {array} objList The list of objects that will be extended\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {object} objList\r\n */\r\n\t\tfunction fromObjectList(objList,callback) {\r\n\t\t\tif (objList == null) return null;\r\n\r\n\t\t\tvar arrayLength = objList.length;\r\n\t\t\tvar newObjList = [];\r\n\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tvar newObj = new callback();\r\n\t\t\t\tnewObj.Code = objList[i];\r\n\t\t\t\tnewObjList.push(newObj);\r\n\t\t\t}\r\n\r\n\t\t\treturn newObjList;\r\n\t\t}\r\n\r\n /**\r\n * Get all the object's Code from given list\r\n * @memberof GenericValuesFactory\r\n * @param {array} objectList An object list\r\n * @returns {array} objectList\r\n */\r\n\t\tfunction objList(objList) {\r\n\t\t\tif (objList == null) return [];\r\n\r\n\t\t\tvar arrayLength = objList.length;\r\n\t\t\tvar newObjList = [];\r\n\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tnewObjList.push(objList[i].Code);\r\n\t\t\t}\r\n\r\n\t\t\treturn newObjList;\r\n\t\t}\r\n \r\n /**\r\n * Get all the objects\r\n * @memberof GenericValuesFactory\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {array} objectList\r\n */\r\n\t\tfunction getValuesFromStorage(callback,type) {\r\n\t\t\tvar objects = localStorageMD5Service.get(type);\r\n\t\t\treturn fromObjectList(objects,callback);\r\n\t\t}\r\n \r\n /**\r\n * Set all the objects\r\n * @memberof GenericValuesFactory\r\n * @param {array} objects A list of objects.\r\n * @param {string} type A string which identifies the local storage name\r\n */\r\n\t\tfunction setValuesToStorage(objects,type) {\r\n\t\t\tlocalStorageMD5Service.set(type, objects);\r\n\t\t}\r\n \r\n /**\r\n * Remove all the objects\r\n * @memberof GenericValuesFactory\r\n * @param {string} type A string which identifies the local storage name\r\n */\r\n\t\tfunction clearValuesFromStorage(type) {\r\n\t\t\tlocalStorageMD5Service.remove(type);\r\n\t\t}\r\n \r\n /**\r\n * Get all the objects codes from local storage\r\n * @memberof GenericValuesFactory\r\n * @param {string} type A string which identifies the local storage name\r\n * @param {function} callback A callback function that behaves as a constructor\r\n * @returns {array} objectList\r\n */\r\n\t\tfunction getValuesFromStorageAsStrings(callback,type) {\r\n\t\t\tvar result = [];\r\n\t\t\tvar objs = getValuesFromStorage(callback,type);\r\n\t\t\tif (objs != null || objs != undefined) {\r\n\t\t\t\tfor (var i = 0; i < objs.length; i++) {\r\n\t\t\t\t\tresult.push(objs[i].Code);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\r\n\treturn service;\r\n\t}\r\n\r\n\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n a3_pilot_reports.factory('IndexedDBService', IndexedDBService);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name IndexedDBService\r\n * @description \r\n * Generic add, edit or remove for IndexedDB\r\n * @ngInject\r\n */\r\n function IndexedDBService($q,LogService) {\r\n var idbSupported = (\"indexedDB\" in window);\r\n if (!idbSupported){\r\n LogService.debug(\"No IndexedDb is supported for this browser's version\");\r\n }\r\n return {\r\n /**\r\n * initiate or update indexedDB storage\r\n * @memberof IndexedDBService\r\n * @returns {object} promise\r\n */\r\n init: function() {\r\n var deferred = $q.defer();\r\n var request = indexedDB.open(\"a3.pilot.reports\",5);\r\n\r\n request.onupgradeneeded = function(e) {\r\n // The database did not previously exist, so create object stores and indexes.\r\n var db = request.result;\r\n if (e.oldVersion<1){\r\n var gameStore = db.createObjectStore(\"Memos\", { keyPath: \"Id\" });\r\n gameStore.createIndex(\"id_idx\", \"Id\", { unique: true });\r\n }\r\n if (e.oldVersion<2){\r\n var gameStore1 = db.createObjectStore(\"MemoImages\", { keyPath: \"imageId\" });\r\n gameStore1.createIndex(\"id_idx\", \"imageId\", { unique: true });\r\n gameStore1.createIndex(\"memoId\", \"memoId\", { unique: false });\r\n }\r\n if (e.oldVersion <= 3 && !db.objectStoreNames.contains('Courses')) {\r\n var gameStore3 = db.createObjectStore(\"Courses\", {\r\n keyPath: \"Id\"\r\n });\r\n gameStore3.createIndex(\"id_idx\", \"Id\", {\r\n unique: true\r\n });\r\n \r\n var store4 = db.createObjectStore(\"TrainingSessions\", {\r\n keyPath: ['day', 'courseId','dutyId']\r\n });\r\n \r\n store4.createIndex(\"id_idx\", ['day', 'courseId','dutyId'], {\r\n unique: true\r\n });\r\n \r\n store4.createIndex(\"day_idx\", \"day\", {\r\n unique: false\r\n });\r\n \r\n store4.createIndex(\"courseId_idx\", \"courseId\", {\r\n unique: false\r\n });\r\n \r\n }\r\n if (e.oldVersion <= 4 && !db.objectStoreNames.contains('FlightSessions')) {\r\n \r\n var store = db.createObjectStore(\"FlightSessions\", {\r\n keyPath: ['day', 'courseId','dutyNo', 'dutyDay']\r\n });\r\n \r\n store.createIndex(\"id_idx\", ['day', 'courseId', 'dutyNo', 'dutyDay'], {\r\n unique: true\r\n });\r\n \r\n store.createIndex(\"day_idx\", \"day\", {\r\n unique: false\r\n });\r\n \r\n store.createIndex(\"courseId_idx\", \"courseId\", {\r\n unique: false\r\n });\r\n }\r\n };\r\n\r\n request.onsuccess = function() {\r\n deferred.resolve(request.result);\r\n };\r\n\r\n request.onerror = function() {\r\n deferred.reject(request.error);\r\n };\r\n\r\n return deferred.promise;\r\n },\r\n\r\n deleteDatabase: function () {\r\n indexedDB.deleteDatabase(\"a3.pilot.reports\");\r\n },\r\n\r\n /**\r\n * Add the object\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {object} entity The object to add\r\n * @returns {object} promise\r\n */\r\n add: function(storeName, entity) {\r\n var deferred = $q.defer();\r\n\r\n var add = function(db) {\r\n var tx = db.transaction([storeName], \"readwrite\");\r\n var store = tx.objectStore(storeName);\r\n\r\n store.add(entity);\r\n\r\n tx.oncomplete = function(e) {\r\n // All requests have succeeded and the transaction has committed.\r\n deferred.resolve(entity.id);\r\n };\r\n\r\n tx.onerror = function(ex) {\r\n deferred.reject(ex);\r\n };\r\n tx.onabort = function(ex) {\r\n deferred.reject(ex);\r\n };\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(add);\r\n }else{\r\n deferred.resolve();\r\n }\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * Add all the objects\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {array} entity The objects to add\r\n * @returns {object} promise\r\n */\r\n addAll: function(storeName, entity) {\r\n var deferred = $q.defer();\r\n\r\n var add = function(db) {\r\n\r\n var tx = db.transaction([storeName], \"readwrite\");\r\n var store = tx.objectStore(storeName);\r\n var count=0;\r\n //Insert several objects: [{obj},{obj},{obj}]\r\n for(var i= 0; i< entity.length; i++){\r\n store.add(entity[i]);\r\n count++;\r\n }\r\n tx.oncomplete = function(e) {\r\n // All requests have succeeded and the transaction has committed.\r\n deferred.resolve(count);\r\n };\r\n\r\n tx.onerror = function(ex) {\r\n deferred.reject(ex);\r\n };\r\n tx.onabort = function(ex) {\r\n deferred.reject(ex);\r\n };\r\n\r\n //db.close();\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(add);\r\n }else{\r\n deferred.resolve();\r\n }\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * update object\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {array} entity The object to update\r\n * @returns {object} promise\r\n */\r\n put: function(storeName, entity) {\r\n var deferred = $q.defer();\r\n\r\n var put = function(db) {\r\n var tx = db.transaction([storeName], \"readwrite\");\r\n var store = tx.objectStore(storeName);\r\n\r\n store.put(entity);\r\n\r\n tx.oncomplete = function() {\r\n // All requests have succeeded and the transaction has committed.\r\n deferred.resolve(tx.result);\r\n };\r\n\r\n tx.onerror = function() {\r\n deferred.reject(tx);\r\n };\r\n tx.onabort = function() {\r\n deferred.reject(tx);\r\n };\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(put);\r\n }else{\r\n deferred.resolve();\r\n } \r\n\r\n return deferred.promise;\r\n },\r\n\r\n /**\r\n * Get the requested object by the default index\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\r\n getById: function(storeName, id) {\r\n var deferred = $q.defer();\r\n\r\n var getById = function(db) {\r\n\r\n var tx = db.transaction([storeName], \"readonly\");\r\n var store = tx.objectStore(storeName);\r\n var index = store.index(\"id_idx\");\r\n\r\n var request = index.get(id);\r\n\r\n request.onsuccess = function() {\r\n deferred.resolve(request.result);\r\n };\r\n\r\n request.onerror = function() {\r\n deferred.reject(request.error);\r\n };\r\n tx.onabort = function() {\r\n deferred.reject(tx.error);\r\n };\r\n }\r\n\r\n\r\n if (idbSupported){\r\n this.init().then(getById);\r\n }else{\r\n deferred.resolve(null);\r\n }\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * Get the requested object by the selected index\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\r\n getByIndex: function(storeName, indexName, value) {\r\n var deferred = $q.defer();\r\n\r\n var getByIndex = function(db) {\r\n\r\n var tx = db.transaction([storeName], \"readonly\");\r\n var store = tx.objectStore(storeName);\r\n var index = store.index(indexName);\r\n var request = index.openCursor(IDBKeyRange.only(value)); //IDBKeyRange.only(value)\r\n var results = [];\r\n request.onsuccess = function() {\r\n var cursor = request.result;\r\n if (cursor) {\r\n results.push(cursor.value);\r\n cursor.continue();\r\n } else {\r\n deferred.resolve(results);\r\n }\r\n };\r\n request.onerror = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n tx.onabort = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(getByIndex);\r\n }else{\r\n deferred.resolve(null);\r\n }\r\n\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * Get the all objects of the selected store\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name (optional)\r\n * @returns {object} promise\r\n */\r\n getAll: function(storeName, indexName) {\r\n var deferred = $q.defer();\r\n if (indexName === undefined) indexName = 'id_idx';\r\n\r\n var all = function(db) {\r\n var tx = db.transaction([storeName], \"readonly\");\r\n var store = tx.objectStore(storeName);\r\n //var index = store.index(indexName);\r\n\r\n var request = store.openCursor(); //IDBKeyRange.only(\"Fred\")\r\n var results = [];\r\n request.onsuccess = function() {\r\n var cursor = request.result;\r\n if (cursor) {\r\n results.push(cursor.value);\r\n cursor.continue();\r\n } else {\r\n deferred.resolve(results);\r\n }\r\n };\r\n request.onerror = function() {\r\n deferred.reject(request.error);\r\n };\r\n tx.onabort = function() {\r\n deferred.reject(tx.error);\r\n };\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(all);\r\n }else{\r\n deferred.resolve([]);\r\n }\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * Count all objects of the selected store\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name (optional)\r\n * @returns {object} promise\r\n */\r\n count: function(storeName, indexName) {\r\n var deferred = $q.defer();\r\n if (indexName === undefined) indexName = 'id_idx';\r\n\r\n var count = function(db) {\r\n var tx = db.transaction([storeName], \"readonly\");\r\n var store = tx.objectStore(storeName);\r\n var index = store.index(indexName);\r\n\r\n var request = index.count();\r\n request.onsuccess = function() {\r\n deferred.resolve(request.result);\r\n };\r\n request.onerror = function() {\r\n deferred.reject(request.error);\r\n };\r\n tx.onabort = function() {\r\n deferred.reject(tx.error);\r\n };\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(count);\r\n }else{\r\n deferred.resolve(0);\r\n }\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * Delete the requested object\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\r\n remove: function(storeName, id) {\r\n var deferred = $q.defer();\r\n\r\n var remove = function(db) {\r\n\r\n var tx = db.transaction([storeName], \"readwrite\");\r\n var store = tx.objectStore(storeName);\r\n\r\n store.delete(id);\r\n\r\n tx.oncomplete = function(e) {\r\n // All requests have succeeded and the transaction has committed.\r\n deferred.resolve(id);\r\n };\r\n\r\n tx.onerror = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n tx.onabort = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n }\r\n\r\n\r\n if (idbSupported){\r\n this.init().then(remove);\r\n }else{\r\n deferred.resolve();\r\n }\r\n\r\n return deferred.promise;\r\n }, \r\n /**\r\n * Delete the requested object by the selected index\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @param {string} indexName A string which identifies the index name (optional)\r\n * @param {number} id The unique identifier\r\n * @returns {object} promise\r\n */\r\n removeByIndex: function(storeName, indexName, value) {\r\n var deferred = $q.defer();\r\n\r\n var removeByIndex = function(db) {\r\n\r\n var tx = db.transaction([storeName], \"readwrite\");\r\n var store = tx.objectStore(storeName);\r\n var index = store.index(indexName);\r\n var request = index.openKeyCursor(IDBKeyRange.only(value)); //IDBKeyRange.only(value)\r\n var results = [];\r\n\r\n request.onsuccess = function() {\r\n var cursor = request.result;\r\n if (cursor) {\r\n store.delete(cursor.primaryKey);\r\n cursor.continue();\r\n } else {\r\n deferred.resolve(results);\r\n }\r\n };\r\n request.onerror = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n tx.onabort = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n }\r\n\r\n\r\n if (idbSupported){\r\n this.init().then(removeByIndex);\r\n }else{\r\n deferred.resolve();\r\n }\r\n\r\n return deferred.promise;\r\n },\r\n /**\r\n * Delete all the objects\r\n * @memberof IndexedDBService\r\n * @param {string} storeName A string which identifies the IndexedDB storage\r\n * @returns {object} promise\r\n */\r\n removeAll: function(storeName){\r\n var deferred = $q.defer();\r\n\r\n var remove = function(db) {\r\n\r\n var tx = db.transaction([storeName], \"readwrite\");\r\n var store = tx.objectStore(storeName);\r\n\r\n store.clear();\r\n\r\n tx.oncomplete = function(e) {\r\n // All requests have succeeded and the transaction has committed.\r\n deferred.resolve('success');\r\n };\r\n\r\n tx.onerror = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n tx.onabort = function(r) {\r\n deferred.reject(r.error);\r\n };\r\n\r\n //db.close();\r\n }\r\n\r\n if (idbSupported){\r\n this.init().then(remove);\r\n }else{\r\n deferred.resolve();\r\n }\r\n\r\n return deferred.promise;\r\n\r\n }\r\n };\r\n }\r\n\r\n})();\r\n","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.service(\"PushNotifier\", PushNotifier);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name PushNotifier\r\n * @description \r\n * Push notification functionality\r\n * @ngInject\r\n */\r\n\tfunction PushNotifier($q,FlightFactory, PaxInfoFactory) {\r\n\r\n\t\t\tvar service = {\r\n\t\t\tGenerate: Generate,\r\n\t\t\tformatInfoToCompare: formatInfoToCompare,\r\n\t\t\tcompareAndExtractChanges: compareAndExtractChanges,\r\n\t\t\tMessageGenerator: BodyGenerator,\r\n\t\t\tCheckForPermissionsAndSupport: CheckForPermissionsAndSupport\r\n\t\t}\r\n\r\n\r\n\t\tvar browserSupportsNotifications = (\"Notification\" in window);\r\n\r\n\t\tfunction CheckForPermissionsAndSupport() {\r\n\r\n\t\t\tvar deferred = $q.defer();\r\n\r\n\t\t\t// Let's check if the browser supports notifications\r\n\t\t\tif (!browserSupportsNotifications) {\r\n\t\t\t\tconsole.debug(\"This browser does not support system notifications\");\r\n\t\t\t\tdeferred.resolve(false);\r\n\t\t\t}\r\n\r\n\t\t\t// Otherwise, we need to ask the user for permission\r\n\t\t\tif (browserSupportsNotifications && Notification.permission !== 'denied') {\r\n\r\n\t\t\t\tvar permissionQ = Notification.requestPermission();\r\n \r\n if (permissionQ){\r\n permissionQ.then(function (result) {\r\n var value = (result === \"granted\");\r\n\r\n deferred.resolve(value);\r\n }), function (reason) {\r\n LogService.error(reason);\r\n deferred.reject(reason);\r\n };\r\n }else{\r\n deferred.resolve(false);\r\n }\r\n \r\n\t\t\t}else {\r\n deferred.resolve(false);\r\n }\r\n \r\n\t\t\treturn deferred.promise;\r\n\t\t}\r\n\r\n\r\n\t\tfunction Generate(title, body) {\r\n\r\n\t\t\t// Let's check whether notification permissions have already been granted\r\n\t\t\tif (browserSupportsNotifications && Notification.permission === \"granted\") {\r\n\t\t\t\t// If it's okay let's create a notification\r\n\t\t\t\tvar notification = new Notification(title, { body: body, icon: './img/a3_logo.png' });\r\n\t\t\t\tsetTimeout(function () {\r\n\t\t\t\t\tnotification.close();\r\n\t\t\t\t}, 5000);\r\n\t\t\t}\r\n\t\t}\r\n \r\n\t\tfunction formatInfoToCompare(flightId) {\r\n\t\t\tvar flightInfo = FlightFactory.getFlightFromStorage(flightId);\r\n\t\t\tvar paxinfo = PaxInfoFactory.getPaxInfoFromStorage(flightId);\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tCTOT: flightInfo.CTOT,\r\n\t\t\t\tATD: flightInfo.ATD,\r\n\t\t\t\tETA: flightInfo.ETA,\r\n\t\t\t\tETD: flightInfo.ETD\r\n\t\t\t};\r\n\r\n\t\t\tdata['Departure Gate'] = flightInfo.DepartureGate;\r\n\t\t\tdata['Departure Stand'] = flightInfo.DepartureStand;\r\n\t\t\tdata['Scheduled Departure Time UTC'] = flightInfo.ScheduledDepartureTimeUTC;\r\n\t\t\tdata['Passenger Info'] = paxinfo ? new Date(paxinfo.LastRun).toString('dd-MM-yyyy HH:mm') : null;\r\n\r\n\t\t\treturn data;\r\n\t\t}\r\n\r\n\t\tfunction compareAndExtractChanges(currentData, updatedData) {\r\n\t\t\tvar changes = [];\r\n\t\t\tfor (var key in currentData) {\r\n\t\t\t\tif (currentData[key] != updatedData[key]) {\r\n\r\n\t\t\t\t\tvar ovalue = currentData[key];\r\n\t\t\t\t\tvar nvalue = updatedData[key];\r\n\r\n\t\t\t\t\tif(key ===\"CTOT\" || key ===\"ATD\" || key ===\"ETA\" || key ===\"ETD\" || key === \"Scheduled Departure Time UTC\"){\r\n\t\t\t\t\t\tif(currentData[key] != null){\r\n\t\t\t\t\t\t\tovalue = moment.utc(currentData[key]).format('HH:mm')\r\n\t\t\t\t\t\t} \r\n\r\n\t\t\t\t\t\tif(updatedData[key] != null){\r\n\t\t\t\t\t\t\tnvalue = moment.utc(updatedData[key]).format('HH:mm')\r\n\t\t\t\t\t\t} \r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tchanges.push({ type: key, oldValue: ovalue, newValue: nvalue });\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn changes;\r\n\t\t}\r\n\t\tfunction BodyGenerator(changes) {\r\n\t\t\tvar message = '';\r\n\t\t\tchanges.forEach(function (x) {\r\n\t\t\t\tvar phrase = null;\r\n\r\n\t\t\t\tif (x.type == 'Passenger Info') {\r\n\t\t\t\t\tphrase = \"Passenger Info have been updated. \\n\";\r\n\t\t\t\t}\r\n\t\t\t\telse if (!x.oldValue) {\r\n\t\t\t\t\tphrase = x.type + \": \" + x.newValue + \" \\n\";\r\n\t\t\t\t} else if (x.oldValue && x.newValue) {\r\n\t\t\t\t\tphrase = x.type + \": \" + x.oldValue + \"\\u2192\" + x.newValue + \" \\n\";\r\n\t\t\t\t}else {\r\n\t\t\t\t\tphrase = x.type +\" has no value\\n\";\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmessage = message + phrase;\r\n\t\t\t});\r\n\r\n\t\t\treturn message;\r\n\t\t}\r\n\r\n\t\treturn service;\r\n\t}\r\n})();\r\n","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('SettingsMain',SettingsMain);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name SettingsMain\r\n * @description \r\n * Generic add, edit or remove\r\n * @ngInject\r\n */\r\nfunction SettingsMain(localStorageMD5Service){\r\n /**\r\n * Initialize the PageMainSettings\r\n * @memberof SettingsMain\r\n */\r\n\t\tfunction PageMainSettings() {\r\n this.EditingPage = null;\r\n this.selectedDate = null;\r\n\t\t}\r\n\t\t\t\t\r\n var service = {\r\n getSettings : getSettings,\r\n setSettings : setSettings,\r\n getEditingPage : getEditingPage,\r\n setEditingPage : setEditingPage,\r\n setCalendarViewStyle : setCalendarViewStyle,\r\n getCalendarViewStyle : getCalendarViewStyle,\r\n getCalendarSelectedDate : getCalendarSelectedDate,\r\n setCalendarSelectedDate : setCalendarSelectedDate\r\n }\r\n \r\n /**\r\n * Get Application Settings\r\n * @memberof SettingsMain\r\n * @returns {object} settings \r\n */\r\n\t\tfunction getSettings(){\r\n\t\t\tvar settings = new PageMainSettings();\r\n\t\t\tvar settingsStored = localStorageMD5Service.get('settingsMain');\r\n\t\t\tif (settingsStored){\r\n\t\t\t\tif (settingsStored.EditingPage) \r\n\t\t\t\t\tsettings.EditingPage = settingsStored.EditingPage;\t\t\r\n \r\n settings.calendarViewStyle = settingsStored.calendarViewStyle;\r\n settings.selectedDate = settingsStored.selectedDate;\r\n\t\t\t}\r\n\t\t\treturn settings;\r\n\t\t}\r\n \r\n\t /**\r\n * Set Application Settings\r\n * @param {object} settings\r\n * @memberof SettingsMain\r\n */\r\n\t\tfunction setSettings(settings){\r\n\t\t\tlocalStorageMD5Service.set('settingsMain',settings);\r\n\t\t}\r\n /**\r\n * Get editing page\r\n * @memberof SettingsMain\r\n * @returns {string} EditingPage\r\n */\t\t\r\n\t\tfunction getEditingPage(){\r\n\t\t\tvar settings = getSettings();\r\n\t\t\treturn settings.EditingPage;\r\n\t\t}\r\n /**\r\n * Set editing page\r\n * @param {string} value\r\n * @memberof SettingsMain\r\n */\r\n\t\tfunction setEditingPage (value){\r\n\t\t\tvar settings = getSettings();\r\n\t\t\tsettings.EditingPage = value;\r\n\t\t\tsetSettings(settings);\r\n\t\t}\r\n \r\n /**\r\n * Get prefered calendar view style\r\n * @memberof SettingsMain\r\n * @returns {string} viewStyle\r\n */\r\n\t\tfunction getCalendarViewStyle() {\r\n\t\t\tvar settings = getSettings();\r\n var viewStyle = settings.calendarViewStyle;\r\n \r\n return viewStyle;\r\n\t\t}\r\n \r\n /**\r\n * Set prefered calendar view style\r\n * @param {string} value\r\n * @memberof SettingsMain\r\n */\r\n\t\tfunction setCalendarViewStyle(value) {\r\n\t\t\tvar settings = getSettings();\r\n\t\t\tsettings.calendarViewStyle = value;\r\n\t\t\tsetSettings(settings);\r\n\t\t}\r\n \r\n\t\t\t\t\r\n\t\t/**\r\n * Get selected calendar date\r\n * @memberof SettingsMain\r\n * @returns {string} selectedDate\r\n */\r\n function getCalendarSelectedDate() {\r\n var settings = getSettings();\r\n var selectedDate = settings.selectedDate;\r\n \r\n return selectedDate;\r\n }\r\n /**\r\n * Set selected calendar date\r\n * @param {string} value\r\n * @memberof SettingsMain\r\n */\r\n function setCalendarSelectedDate(value) {\r\n var settings = getSettings();\r\n settings.selectedDate = value;\r\n setSettings(settings);\r\n }\r\n\r\n\treturn service;\r\n};\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.service(\"UpdateService\", UpdateService);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name UpdateService\r\n * @description \r\n * Update functionality\r\n * @ngInject\r\n */\r\nfunction UpdateService(SyncLogFactory) {\r\n /**\r\n * Version patcher\r\n * @memberof UpdateService\r\n * @returns {string} NeedsSync \r\n */\r\n function patcher (version) {\r\n var NeedsSync=false;\r\n if (version==\"1.0\"){\r\n SyncLogFactory.updateSyncVersion(\"1.1\")\r\n //patching to next version \r\n // patcher(\"1.1\"); \r\n NeedsSync=true;\r\n }\r\n \r\n return NeedsSync;\r\n \r\n }\r\n return {\r\n /**\r\n * updates application \r\n * @memberof UpdateService\r\n * @returns {string} NeedsSync \r\n */\r\n updater : function() {\r\n var synclog=SyncLogFactory.getSyncLog();\r\n if (synclog==undefined || synclog==null)\r\n {\r\n return false;\r\n }\r\n else if (synclog.isUpdated){\r\n return true;\r\n }\r\n else\r\n {\r\n var NeedsSync=patcher(synclog.version);\r\n return NeedsSync;\r\n }\r\n } \r\n };\r\n }\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.service(\"UtilsService\", UtilsService);\r\n\r\n/* @ngInject */ \r\nfunction UtilsService() {\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\treturn {\r\n\t\t/**\r\n\t\t * Convert content length to fixed string\r\n\t\t * @static\r\n\t\t * @param {Number} n - number of byte kibibyte or mibi..., cannot not be NaN, indefinite or negative\r\n\t\t * @param {Number} [f=0] - max fraction digits in range of 0..20\r\n\t\t * @param {Number} [e=0] - exponent based 1024, Math.pow(1024,e) stands for the unit of n\r\n\t\t * @return {String}\r\n\t\t * @throws {RangeError}\r\n\t\t */\r\n\t\ttoSizeString: function (n,f,e){\r\n\t\t\tn=parseFloat(n);\r\n\t\t\tf>>>=0;\r\n\t\t\te>>>=0;\r\n\t\t\tif(n!==n||1/n<0||1/n===-1/n||f<0||f>20||e<0){\r\n\t\t\t\tthrow new RangeError(\"One of the three argument (number, fraction, exponent) is out of range\");\r\n\t\t\t}\r\n\t\t\tvar kibi=1024,mibi=1048576,gibi=1073741824,tebi=1099511627776;\r\n\t\t\tvar v,u;\r\n\t\t\tn*=Math.pow(1024,e);\r\n\t\t\tif(n 0) {\r\n var aegeanFlights = getAEFlightsForCurrentMonth(flights);\r\n flightsLeft = getFlightsLeftForCurrentMonth(aegeanFlights);\r\n totalAegeanFlights = aegeanFlights.length;\r\n }\r\n var autoland = { autolandCount: AutolandOperations, totalAEFlights: totalAegeanFlights, flightsLeft: flightsLeft, showAutolandModal: true }\r\n GenericService.saveOne(autoland, objType, objCallback);\r\n }\r\n /**\r\n * Update autoland object to storage\r\n * @memberof AutolandFactory\r\n * @param {bool} canShowModal whether the modal can be display\r\n */\r\n function showAutolandModal(canShowModal){\r\n var autoland = GenericService.getOne(objType, objCallback);\r\n autoland.showAutolandModal = canShowModal;\r\n GenericService.saveOne(autoland, objType, objCallback);\r\n \r\n }\r\n /**\r\n * Gets the value of showAutolandModal property\r\n * @memberof AutolandFactory\r\n * @returns {bool} returns the value of showAutolandModal property\r\n */\r\n function canShowAutolandModal(){\r\n var autoland = GenericService.getOne(objType, objCallback);\r\n return autoland && autoland.showAutolandModal; \r\n }\r\n\r\n /**\r\n * Get the count of fligths after the current time\r\n * @memberof AutolandFactory\r\n * @param {object} flights the flight object of sync response\r\n * @returns {number} returns the count of fligths after the current time\r\n */\r\n function getFlightsLeftForCurrentMonth(flights) {\r\n var flightDates = flights.map(a => a.ScheduledArrival);\r\n var date = new Date();\r\n //uncomment for testig purposes\r\n //var date = new Date(2016, 1, 8);\r\n var filteredDays = flightDates.filter(x => moment.utc(x) >= moment.utc(date))\r\n return filteredDays.length;\r\n }\r\n\r\n /**\r\n * Get Aegean Flights For Current Month\r\n * @memberof AutolandFactory\r\n * @param {object} flights the flight object of sync response\r\n * @returns {Array} returns array of fligths that the user is not DHC the flight is for aegean and the userposition is CP\r\n */\r\n function getAEFlightsForCurrentMonth(flights) {\r\n var date = new Date();\r\n var firstDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1);\r\n var lastDayOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0);\r\n \r\n //Uncomment for testing purposes\r\n // var firstDayOfMonth = new Date(2016, 1, 1);\r\n // var lastDayOfMonth = new Date(2016, 1, 30);\r\n return flights.filter(x => x.Position == \"CP\"\r\n && x.IsDHC == false\r\n && autolandSupportingAcTypes.includes(x.AcType)\r\n && moment.utc(x.DutyDate) >= moment.utc(firstDayOfMonth)\r\n && moment.utc(x.DutyDate) <= moment.utc(lastDayOfMonth));\r\n }\r\n return service;\r\n }\r\n\r\n})();","(function () {\r\n 'use strict';\r\n a3_pilot_reports.directive('calendarNotifications', calendarNotifications);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name calendarNotifications\r\n * @restrict E\r\n * @description\r\n * Implementation of crew meals\r\n *\r\n * Display the notifications\r\n * @attr {String} draftReport \r\n * @attr {String} completedReports \r\n * @example\r\n * Usage:\r\n * \r\n * \r\n * @ngInject\r\n */\r\n function calendarNotifications($location, MessageFactory, MemoFactory, AutolandFactory, ScheduleAcknowledgeFactory, LeaveRequestFactory, $uibModal, CheckInFactory, GroundDutyFactory, $route) {\r\n\r\n function link($scope, attrs) {\r\n $scope.gotoUnreadMemos = gotoUnreadMemos;\r\n $scope.gotoMessages = gotoMessages;\r\n $scope.gotoLeaves = gotoLeaves;\r\n $scope.reportsCounter = getReportsCounter();\r\n $scope.acknowledge = acknowledge;\r\n\r\n $scope.showPanel = false;\r\n $scope.showAutolandReminder = false;\r\n $scope.showScheduleChangesReminder = false;\r\n $scope.hasScheduleChanges = false;\r\n $scope.openCheckIn = openCheckInModal;\r\n $scope.showCheckInAction = false;\r\n\r\n $scope.hasManualEntry = false;\r\n $scope.gotoGroundDutyInfo = gotoGroundDutyInfo;\r\n $scope.removeManualEntry = removeManualEntry;\r\n\r\n setupView();\r\n function setupView() {\r\n\r\n $scope.number_of_messages = MessageFactory.getMessagesFromStorage().length;\r\n $scope.number_of_messages_not_readen = MessageFactory.getCountOfUnreadMessages();\r\n\r\n $scope.leaveRequest = LeaveRequestFactory.getLeaveRequestInformation();\r\n $scope.leaveRequestCloseDate = $scope.leaveRequest ? moment($scope.leaveRequest.CloseDate).format('Do of MMMM') : null;\r\n\r\n //Get count of unread memos but remove the ones that belong in 'Training Surveys' Category\r\n var unreadMemosCount = 0;\r\n MemoFactory.getUnreadMemos(function (memos) {\r\n\r\n //remove memos that belong in \"Training Surveys\" category\r\n for (var i = 0; i < memos.length; i++) {\r\n if (memos[i].Category != \"Training Surveys\") {\r\n unreadMemosCount++;\r\n }\r\n }\r\n $scope.unreadMemosCount = unreadMemosCount;\r\n $scope.hasScheduleChanges = ScheduleAcknowledgeFactory.hasScheduleChanges();\r\n $scope.showCheckInAction = showCheckInAction();\r\n prepareAutolandData();\r\n $scope.showPanel = showNotificationPanel();\r\n $scope.showScheduleChangesReminder = showScheduleChangesReminder();\r\n showReminderModal();\r\n\r\n });\r\n\r\n // Used for pending trainings notification \r\n\t\t\t $scope.manualGroundDuties = GroundDutyFactory.getManualGroundDutiesFromStorage();\r\n\t\t\t findManualEntries($scope.manualGroundDuties);\r\n\r\n }\r\n\r\n function prepareAutolandData() {\r\n //Get autoland procedures\r\n var autoland = AutolandFactory.getAutolandFromStorage();\r\n $scope.autolandCount = 0;\r\n $scope.flightsLeft = 0;\r\n $scope.hasAEFlights = false;\r\n var totalAEFlights = 0;\r\n if (autoland != null) {\r\n $scope.autolandCount = autoland.autolandCount;\r\n $scope.flightsLeft = autoland.flightsLeft;\r\n totalAEFlights = autoland.totalAEFlights;\r\n $scope.hasAEFlights = autoland.totalAEFlights > 0;\r\n }\r\n\r\n if (AutolandFactory.canShowAutolandModal() && $scope.autolandCount == 0 && $scope.hasAEFlights && totalAEFlights > 4 && $scope.flightsLeft > 0 && $scope.flightsLeft < 10) {\r\n $scope.showAutolandReminder = true;\r\n }\r\n else {\r\n $scope.showAutolandReminder = false\r\n }\r\n\r\n }\r\n\r\n function showScheduleChangesReminder() {\r\n return ScheduleAcknowledgeFactory.showScheduleChangesModal();\r\n }\r\n\r\n function showCheckInAction() {\r\n var retVal = false;\r\n var checkInInfo = CheckInFactory.getCheckInInfoFromStorage();\r\n if (checkInInfo && checkInInfo.AimsId > 0) {\r\n var now = moment.utc();\r\n\r\n //Fetch FROM\r\n //Convert from Date UTC to Moment UTC\r\n\r\n var std = moment.utc(checkInInfo.STD);\r\n var minFetchTime = moment(std).add(-2, 'hours');\r\n\r\n //Fetch UNTIL \r\n var maxFetchTime = moment(std).add(10, 'minutes');\r\n\r\n var isAfter = now.isAfter(minFetchTime);\r\n var isBefore = now.isBefore(maxFetchTime);\r\n\r\n if (isAfter && isBefore) {\r\n retVal = true;\r\n }\r\n\r\n //console.log({\"isAfter\":isAfter, \"isBefore\": isBefore, \"now\":now, \"std\":std, \"minFetchTime\":minFetchTime,\"maxFetchTime\":maxFetchTime});\r\n\r\n }\r\n\r\n\r\n return retVal;\r\n }\r\n\r\n function showNotificationPanel() {\r\n var showPanel = false;\r\n if (($scope.draftReports + $scope.completedReports) > 9\r\n || !$scope.$root.idbSupported\r\n || ($scope.unreadMemosCount > 0\r\n || $scope.number_of_messages_not_readen > 0)\r\n || $scope.hasAEFlights\r\n || ($scope.leaveRequest && $scope.leaveRequest.GroupStatus == 'OPEN')\r\n || $scope.hasScheduleChanges\r\n || $scope.showCheckInAction) {\r\n showPanel = true;\r\n }\r\n return showPanel;\r\n }\r\n\r\n /**\r\n * Finds the dates with manual pending training entries on their schedule\r\n * @memberof CalendarCtrl \r\n */\r\n\t\t\tfunction findManualEntries(manualDuties) {\r\n\t\t\t\tfor (var i = 0; i < manualDuties.length; i++) { \r\n\t\t\t\t\tif (manualDuties[i].hasPendingCourse) {\r\n\t\t\t\t\t\t$scope.hasManualEntry = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n function getReportsCounter() {\r\n return parseInt($scope.draftReports) + parseInt($scope.completedReports);\r\n }\r\n /**\r\n * Redirect to Library Info with filter enabled\r\n * @memberof calendarNotifications\r\n */\r\n function gotoUnreadMemos() {\r\n $location.path('/memos/unread');\r\n }\r\n\r\n /**\r\n * Redirect to messages\r\n * @memberof calendarNotifications\r\n */\r\n function gotoMessages() {\r\n $location.path('/messages/');\r\n }\r\n\r\n /**\r\n * Redirect to leaves\r\n * @memberof CalendarCtrl\r\n */\r\n function gotoLeaves() { \r\n $location.path('/leaverequest/');\r\n }\r\n\r\n /**\r\n * Redirect to groundDuty Info\r\n * @memberof CalendarCtrl\r\n */\r\n function gotoGroundDutyInfo(GroundDutyId) {\r\n $location.path('/groundDuty/' + GroundDutyId);\r\n }\r\n\r\n /** Removes manual training entry */\r\n function removeManualEntry(groundDuty) {\r\n GroundDutyFactory.removeGroundDuty(groundDuty);\r\n $route.reload();\r\n }\r\n\r\n /**\r\n * Shows the bootbox for autoland and schedule acknowledge reminder\r\n * @memberof calendarNotifications\r\n */\r\n function showReminderModal() {\r\n\r\n if ($scope.showAutolandReminder || $scope.showScheduleChangesReminder) {\r\n\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/CalendarNotifications/dlgReminderModal.html',\r\n controller: 'ReminderModalCtrl',\r\n size: 'md',\r\n backdrop: 'static',\r\n keyboard: false,\r\n resolve: {\r\n showAutolandReminder: function () {\r\n return $scope.showAutolandReminder;\r\n },\r\n showScheduleChangesReminder: function () {\r\n return $scope.showScheduleChangesReminder;\r\n }\r\n }\r\n });\r\n\r\n\r\n\r\n // bootbox.dialog({\r\n // message: `
Autoland for this Month is pending.
`,\r\n // title: \"Autoland Reminder\",\r\n // buttons: {\r\n // confirm: {\r\n // label: ' I understand',\r\n // className: \"btn-success\",\r\n // callback: function () { \r\n // AutolandFactory.showAutolandModal(false);\r\n\r\n // }\r\n // }\r\n // }\r\n // })\r\n }\r\n }\r\n\r\n /**\r\n * Open the \"Acknowledge schedule changes\" Modal\r\n * @memberof CalendarCtrl\r\n */\r\n function acknowledge() {\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/CalendarNotifications/dlgAcknowledgeChanges.html',\r\n controller: 'AcknowledgeModalCtrl',\r\n size: 'lg',\r\n backdrop: 'static',\r\n keyboard: false\r\n });\r\n\r\n\r\n }\r\n\r\n /**\r\n * Open Check in Modal\r\n * @memberof CalendarCtrl\r\n */\r\n function openCheckInModal() {\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgCheckIn.html',\r\n controller: 'CheckInModalCtrl',\r\n size: 'lg',\r\n backdrop: 'static',\r\n keyboard: false\r\n });\r\n }\r\n\r\n\r\n\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: true,\r\n templateUrl: 'views/CalendarNotifications/calendarNotifications.tpl.html',\r\n scope: {\r\n draftReports: '@',\r\n completedReports: '@',\r\n hasUnsetTraining: '@'\r\n },\r\n link: link\r\n }\r\n }\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('ReminderModalCtrl', ReminderModalCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ReminderModalCtrl\r\n * @description \r\n * Warning Modal about autoland and acknowledge schedule changes\r\n * @ngInject\r\n */\r\n function ReminderModalCtrl(showAutolandReminder, showScheduleChangesReminder, AutolandFactory, ScheduleAcknowledgeFactory, $scope, $uibModalInstance) {\r\n \r\n $scope.cancel = cancel;\r\n //from parent view:\r\n $scope.showAutolandReminder = showAutolandReminder;\r\n $scope.showScheduleChangesReminder = showScheduleChangesReminder;\r\n \r\n\r\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\r\n function cancel() {\r\n if($scope.showAutolandReminder){\r\n AutolandFactory.showAutolandModal(false);\r\n }\r\n if($scope.showScheduleChangesReminder){\r\n ScheduleAcknowledgeFactory.updateShowScheduleChangesModal(false);\r\n }\r\n\r\n $uibModalInstance.close('cancel');\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.factory('CheckInFactory', CheckInFactory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CheckInFactory\r\n * @description \r\n * Get list, Update list & Acknowledge schedule changes\r\n * @ngInject\r\n */\r\n\tfunction CheckInFactory(GenericService, $http, apiUrl) {\r\n /**\r\n * Initialize the ScheduleChanges\r\n * @memberof CheckInFactory\r\n */\r\n function CheckIn() {\r\n \r\n }\r\n\r\n var objType = 'CheckIn';\r\n var objCallback = CheckIn;\r\n\r\n var response = { success: false, \r\n message: '', \r\n checkInInfo: null\r\n };\r\n\r\n\t\tvar service = {\r\n\t\t\tsetCheckInInfoToStorage : setCheckInInfoToStorage,\r\n\t\t\tgetCheckInInfoFromStorage : getCheckInInfoFromStorage,\r\n checkIn : checkIn,\r\n saveCheckInDelay: saveCheckInDelay\r\n\t\t};\r\n\r\n\t\t/**\r\n\t\t * Save check in info\r\n\t\t * @param {array} checkInInfo \r\n\t\t */\r\n function setCheckInInfoToStorage(checkInInfo) {\r\n if(checkInInfo == undefined || checkInInfo == null){\r\n GenericService.removeAll(objType);\r\n }\r\n else{\r\n GenericService.saveOne(checkInInfo, objType, objCallback);\r\n }\r\n }\r\n\r\n\t\t/**\r\n\t\t * Get check in info\r\n\t\t */\r\n function getCheckInInfoFromStorage(){\r\n return GenericService.getOne(objType, objCallback);;\r\n\t\t}\r\n\r\n \r\n /**\r\n * Check In\r\n * @returns {promise} response\r\n */\r\n function checkIn(confirmed){\r\n return $http.get(apiUrl + '/CrewCheckIn/CheckIn?confirmed=' + confirmed, { 'Content-Type' : 'application/json' })\r\n .then(res => updateCheckInCallBack(res))\r\n .catch(res => checkInFailedCallBack(res));\r\n }\r\n\r\n /**\r\n * Update Schedule changes dates\r\n * @param {object} res \r\n * @param {object} objectToAdd \r\n * @returns {object} response\r\n */\r\n function updateCheckInCallBack(res) {\r\n response.success = res.data.success;\r\n if (res.data.success) {\r\n //update local storage\r\n setCheckInInfoToStorage(res.data.data);\r\n response.checkInInfo = res.data.data;\r\n if(response.checkInInfo && response.checkInInfo.Confirmed && response.checkInInfo.ErrorExplanation === \"\"){\r\n response.message = \"Success! Check In Confirmed.\";\r\n }else if(response.checkInInfo && !response.checkInInfo.Confirmed && response.checkInInfo.ErrorExplanation === \"\"){\r\n response.message = \"Ready for Check In.\";\r\n }else if(response.checkInInfo){\r\n response.message = response.checkInInfo.ErrorExplanation;\r\n }else{\r\n response.message = \"You have not pending Check In.\";\r\n }\r\n }\r\n else {\r\n response.message = res.data.errorMessage\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * The callback function upon failure on submit\r\n * @returns {object} response\r\n */\r\n function checkInFailedCallBack(res) {\r\n \r\n response.success = false;\r\n response.message = \"Oops! Something went wrong\"\r\n\r\n //TODO::Check status=500 error: returns res = {data: {…}, status: 500, config: {…}, statusText: \"Internal Server Error\", headers: ƒ}\r\n // res.data.data is null\r\n if(res.data.data ){\r\n response.checkInInfo = res.data.data;\r\n }else{\r\n //log results\r\n console.log(res);\r\n }\r\n return response;\r\n }\r\n\r\n /**\r\n * Save Check In Delay\r\n * @returns {promise} response\r\n */\r\n function saveCheckInDelay(delayMinutes){\r\n var checkInInfo = getCheckInInfoFromStorage();\r\n checkInInfo.DelayMinutes = +delayMinutes;\r\n return $http.post(apiUrl + '/CrewCheckIn/SaveCheckInDelay', checkInInfo, { 'Content-Type': 'application/json' })\r\n .then(res => updateCheckInDelayCallBack(res))\r\n .catch(res => checkInFailedCallBack(res));\r\n }\r\n function updateCheckInDelayCallBack(res) {\r\n response.success = res.data.success;\r\n if (res.data.success) {\r\n response.message = \"Success! Delay message was sent.\";\r\n }\r\n else {\r\n response.message = res.data.errorMessage\r\n }\r\n\r\n return response;\r\n }\r\n\t\treturn service;\r\n\t}\r\n})();\r\n","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('CheckInModalCtrl', CheckInModalCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CheckInModalCtrl\r\n * @description \r\n * Check in Modal\r\n * @ngInject\r\n */\r\n function CheckInModalCtrl($scope, CheckInFactory, $route, $uibModalInstance) {\r\n $scope.showContent = 'actions';\r\n $scope.cancel = cancel;\r\n $scope.checkInInfo = null; \r\n $scope.CheckInAction = CheckInAction;\r\n $scope.BackToActions = BackToActions;\r\n $scope.ConfirmCheckIn = ConfirmCheckIn;\r\n $scope.SendDelayMessage = SendDelayMessage;\r\n $scope.GetCheckInInfoFromServer = GetCheckInInfoFromServer;\r\n $scope.responseObj = { success: false, message: '', checkInInfo: null };\r\n $scope.results = [];\r\n\r\n $scope.selectedDelayMinutes = 10;\r\n $scope.onMinutesChange = onMinutesChange;\r\n $scope.numberDown = numberDown;\r\n $scope.numberUp = numberUp;\r\n GetCheckInInfoFromServer();\r\n \r\n \r\n function GetCheckInInfoFromServer(){\r\n $scope.showContent = 'loading';\r\n var confirmCheckIn = false;\r\n CheckInFactory.checkIn(confirmCheckIn)\r\n .then(res => handleRefreshResponse(res))\r\n .catch(res => handleRefreshResponse(res));\r\n \r\n } \r\n function handleRefreshResponse(res) {\r\n $scope.showContent = 'actions';\r\n $scope.responseObj = res;\r\n }\r\n\r\n function CheckInAction(){\r\n $scope.showContent = 'confirm';\r\n }\r\n function BackToActions(){\r\n $scope.showContent = 'actions';\r\n }\r\n\r\n function ConfirmCheckIn(){\r\n $scope.showContent = 'loading';\r\n var confirmCheckIn = true;\r\n CheckInFactory.checkIn(confirmCheckIn)\r\n .then(res => handleSubmitResponse(res))\r\n .catch(res => handleSubmitResponse(res));\r\n \r\n }\r\n\r\n function handleSubmitResponse(res) {\r\n $scope.showContent = 'results';\r\n $scope.responseObj = res;\r\n }\r\n\r\n\r\n function onMinutesChange(minutes){\r\n $scope.selectedDelayMinutes = minutes;\r\n }\r\n\r\n\r\n function SendDelayMessage(){\r\n $scope.showContent = 'loading';\r\n CheckInFactory.saveCheckInDelay($scope.selectedDelayMinutes)\r\n .then(res => handleDelayMessageResponse(res))\r\n .catch(res => handleDelayMessageResponse(res));\r\n }\r\n\r\n function handleDelayMessageResponse(res) {\r\n $scope.showContent = 'results';\r\n $scope.responseObj.success = res.success;\r\n $scope.responseObj.message = res.message;\r\n }\r\n\r\n /**\r\n * Decrease field value by 5\r\n */\r\n function numberDown(selectedDelayMinutes){\r\n if(selectedDelayMinutes > 0){\r\n $scope.selectedDelayMinutes = selectedDelayMinutes - 5;\r\n }\r\n } \r\n\r\n /**\r\n * Increase field value by 5\r\n */\r\n function numberUp(selectedDelayMinutes){\r\n $scope.selectedDelayMinutes = selectedDelayMinutes + 5;\r\n }\r\n\r\n /**\r\n * Closes modal\r\n */\r\n function cancel() {\r\n $uibModalInstance.close('cancel');\r\n\r\n // if($scope.responseObj.success){\r\n // $route.reload();\r\n // }\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.controller('CrewCallCtrl', CrewCallCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CrewCallCtrl\r\n * @description \r\n * View confirmation warning when clicking on a crew member's telephone - Monitor call requests\r\n * @ngInject\r\n */\r\n\tfunction CrewCallCtrl($scope, $uibModalInstance, crew, flightId, CrewCallFactory, UserFactory, LogCallFactory) {\r\n\r\n $scope.close = close;\r\n $scope.call = call;\r\n $scope.beforeCall = true;\r\n $scope.crew = crew;\r\n \r\n /**\r\n * Close the modal\r\n */\r\n\t\tfunction close() {\r\n\t\t\t$uibModalInstance.close(false);\r\n\t\t}\r\n\r\n /**\r\n * Confirm Call\r\n * @param {number} crewId Requested user \r\n */\r\n function call(crewId){\r\n $scope.beforeCall = false;\r\n var user = UserFactory.getUser();\r\n\r\n var logData = {\r\n Requester : user.id,\r\n Requestee : crewId,\r\n FlightId : flightId,\r\n Date : moment.utc()\r\n };\r\n\r\n if($scope.isOffline){\r\n //Offline: save audit to local storage, send later on sync\r\n LogCallFactory.saveLogCall(logData);\r\n }\r\n else{\r\n //Online : API call to save audit right now\r\n CrewCallFactory.LogCall(logData, function (responseData) {});\r\n }\r\n }\r\n\t}\r\n\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('CrewCallFactory', CrewCallFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewCallFactory\r\n * @ngInject\r\n */\r\n function CrewCallFactory(GenericService, $http, apiUrl) {\r\n function CrewCall() {\r\n\t\t\tthis.FlightId = null;\r\n this.CrewId = null;\r\n this.phoneNumber = null;\r\n\t\t}\r\n\r\n var objType ='crewCall';\r\n\t\tvar objCallback = CrewCall; \r\n\r\n var service = {\r\n getCrewCallsFromStorage : getCrewCallsFromStorage,\r\n setCrewCallsToStorage : setCrewCallsToStorage,\r\n getCrewCallFromStorage : getCrewCallFromStorage,\r\n getFlightCrewCallsFromStorage : getFlightCrewCallsFromStorage,\r\n saveCrewCall : saveCrewCall,\r\n cleanOldData : cleanOldData,\r\n LogCall: LogCall,\r\n cleanFlightCrewNumbers : cleanFlightCrewNumbers,\r\n saveFlightPhoneNumbers : saveFlightPhoneNumbers\r\n };\r\n\r\n /**\r\n * Get Crew Phone Numbers.\r\n * @memberof CrewCallFactory\r\n * @returns {Array} CrewPhoneNumbers \r\n */\r\n\t\tfunction getCrewCallsFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Get Crew Phone Numbers for specified flight\r\n * @memberof CrewCallFactory\r\n * @param {number} flightId\r\n * @returns {Array} CrewPhoneNumbers \r\n */\r\n\t\tfunction getFlightCrewCallsFromStorage(flightId) {\r\n\t\t\tvar phoneNumbers = GenericService.list(objType,objCallback);\r\n return phoneNumbers.filter(x => x.FlightId == flightId);\r\n\t\t}\r\n\r\n /**\r\n * Save Crew Phone Numbers to storage\r\n * @memberof CrewCallFactory\r\n * @param {Array} CrewPhoneNumbers\r\n */\r\n\t\tfunction setCrewCallsToStorage(objList) {\r\n\t\t\tGenericService.saveAll(objList,objType);\r\n }\r\n\r\n /**\r\n * Get Crew Phone Number from storage \r\n * @memberof CrewCallFactory\r\n * @param {number} crewId\r\n * @param {number} flightId\r\n * @return {object} crew phone number\r\n */\r\n\t\tfunction getCrewCallFromStorage(crewId, flightId) {\r\n var phoneNumbers = getCrewCallsFromStorage();\r\n\r\n return phoneNumbers.find(x => x.FlightId == flightId && x.CrewId == crewId);\r\n\t\t}\r\n \r\n /**\r\n\t\t * Save a fetched crew phone number\r\n * @memberof CrewCallFactory\r\n\t\t * @param {object} crewCall \r\n\t\t */\r\n\t\tfunction saveCrewCall(crewCall){\r\n GenericService.add(crewCall, objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Clean ls from old flight phone numbers\r\n * @param {array} flights Synced flights\r\n */\r\n function cleanOldData(flights){\r\n var flightIds = flights.map(x => x.FlightId);\r\n var phoneNumbers = getCrewCallsFromStorage();\r\n //Filter out phone numbers of old flights\r\n phoneNumbers = phoneNumbers.filter(x => flightIds.includes(x.FlightId));\r\n \r\n var now = moment.utc();\r\n var keepingPhoneNumbers = [];\r\n phoneNumbers.forEach(function(item){\r\n\r\n //Fetch FROM\r\n //Convert from Date UTC to Moment UTC\r\n var dateSTD = new Date(item.STD).fromUTC();\r\n var std = moment(dateSTD).utc(); \r\n var minFetchTime = moment(std).add(-24, 'hours');\r\n\r\n //Fetch UNTIL\r\n //Convert from Date UTC to Moment UTC\r\n var dateSTA = new Date(item.STA).fromUTC();\r\n var sta = moment(dateSTA).utc(); \r\n var maxFetchTime = moment(sta).add(2, 'hours');\r\n \r\n var isAfter = now.isAfter(minFetchTime);\r\n var isBefore = now.isBefore(maxFetchTime);\r\n\r\n if(isAfter && isBefore){\r\n keepingPhoneNumbers.push(item);\r\n }\r\n \r\n });\r\n\r\n setCrewCallsToStorage(keepingPhoneNumbers);\r\n }\r\n\r\n /**\r\n * Log call request\r\n * @param {string} logData Requester, Requestee, FlightId\r\n * @param {function} callback \r\n * @param {function} errorCallback \r\n */\r\n function LogCall(logData, callback, errorCallback) {\r\n return $http.post(apiUrl + '/Info/LogCrewMemberCall', logData, { 'Content-Type': 'application/json' })\r\n .then(callback)\r\n .catch(errorCallback);\r\n }\r\n\r\n /**\r\n * Clean all stored phone numbers for selected flight\r\n * @param {number} flightId \r\n */\r\n function cleanFlightCrewNumbers(flightId){\r\n var phoneNumbers = getCrewCallsFromStorage();\r\n\t\t\tphoneNumbers = phoneNumbers.filter(x => x.FlightId != flightId);\r\n\t\t\tsetCrewCallsToStorage(phoneNumbers);\r\n }\r\n\r\n /**\r\n * Save any found crew phone numbers for specified flight\r\n * @param {number} flightId \r\n * @param {array} crew \r\n * @param {datetime} sta \r\n * @param {datetime} std \r\n */\r\n function saveFlightPhoneNumbers(flightId, crew, sta, std){\r\n crew.forEach(function(user){\r\n if(user.PhoneNumber){\r\n var crewPhone = {\r\n FlightId : flightId,\r\n CrewId : user.id,\r\n PhoneNumber : user.PhoneNumber,\r\n STA : sta, //sta & std values will be used during sync to check timerange eligibility (-24h sta / +2h std)\r\n STD : std\r\n };\r\n saveCrewCall(crewPhone);\r\n }\r\n });\r\n }\r\n\r\n\r\n return service;\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('FlightCheckInsFactory', FlightCheckInsFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightCheckInsFactory\r\n * @ngInject\r\n */\r\n function FlightCheckInsFactory(GenericService) {\r\n function FlightCheckIn() {\r\n\t\t\tthis.FlightId = null;\r\n this.CrewId = null;\r\n this.CheckIn - null;\r\n this.WillBeThereAt = null;\r\n\r\n\t\t}\r\n\r\n var objType ='flightCheckIns';\r\n\t\tvar objCallback = FlightCheckIn; \r\n\r\n var service = {\r\n updateFlightCrewCheckInToStorage : updateFlightCrewCheckInToStorage,\r\n getFlightCrewCheckInFromStorage : getFlightCrewCheckInFromStorage,\r\n cleanOldData: cleanOldData\r\n };\r\n\r\n /**\r\n * Get Crew Check-Ins.\r\n * @memberof CrewCallFactory\r\n * @returns {Array} CrewPhoneNumbers \r\n */\r\n\t\tfunction getCrewCheckInFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Save crew checkIns to storage\r\n * @memberof CrewCallFactory\r\n * @param {Array} CrewPhoneNumbers\r\n */\r\n\t\tfunction setCrewCheckInToStorage(objList) {\r\n\t\t\tGenericService.saveAll(objList,objType);\r\n }\r\n\r\n /**\r\n * Update Crew CheckIns for specified flight\r\n * @memberof CrewCallFactory\r\n * @param {} flight duty\r\n * @returns {Array} CrewFlightCrewCheckIns \r\n */\r\n function updateFlightCrewCheckInToStorage(duty){\r\n //Get all checkIns exept current flight from storage\r\n var storedCheckIns = getCrewCheckInFromStorage();\r\n var storedCheckInsFiltered = storedCheckIns.filter(f=>f.FlightId != duty.FlightId);\r\n //Get checkIns from duty and add new crew checkIns to list\r\n if(duty && duty.FlightInfo && duty.FlightInfo.crew){\r\n duty.FlightInfo.crew.forEach(function(item){\r\n storedCheckInsFiltered.push({\"FlightId\": duty.FlightId, \"CrewId\": item.id, \"CheckIn\": item.CheckIn,\"WillBeThereAt\": item.WillBeThereAt});\r\n });\r\n //save checkIns\r\n setCrewCheckInToStorage(storedCheckInsFiltered);\r\n }\r\n }\r\n\r\n /**\r\n * Get Crew CheckIns for specified flight\r\n * @memberof CrewCallFactory\r\n * @param {number} flightId\r\n * @returns {Array} CrewFlightCrewCheckIns \r\n */\r\n\t\tfunction getFlightCrewCheckInFromStorage(flightId) {\r\n\t\t\tvar storedCheckIns = getCrewCheckInFromStorage();\r\n return storedCheckIns.filter(x => x.FlightId == flightId);\r\n\t\t}\r\n\r\n\r\n /**\r\n * Clean ls from old flights crew check-ins\r\n * @param {array} flights Synced flights\r\n */\r\n function cleanOldData(flights){\r\n var flightIds = flights.map(x => x.FlightId);\r\n var previousCheckIns = getCrewCheckInFromStorage();\r\n \r\n //Filter out crew check-ins of old flights\r\n previousCheckIns = previousCheckIns.filter(x => flightIds.includes(x.FlightId));\r\n \r\n setCrewCheckInToStorage(previousCheckIns);\r\n }\r\n\r\n return service;\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('crewInfo', crewInfo);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name crewInfo\r\n * @restrict E\r\n * @description\r\n * Crew Table with a double row per crew member\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function crewInfo($uibModal, UserFactory) {\r\n function link(scope, element, attrs) {\r\n scope.user = UserFactory.getUser();\r\n scope.openPhoneConfirmation = openPhoneConfirmation;\r\n scope.showInfoRow = showInfoRow;\r\n\r\n if(scope.type==\"flight\"){\r\n scope.crewMembers = scope.crew.filter(x => (x.position =='CP' || x.position == \"FO\") && !x.isDHC );\r\n }\r\n else if(scope.type==\"cabin\"){\r\n scope.crewMembers = scope.crew.filter(x => (x.position =='SA' || x.position == \"FA\") && !x.isDHC );\r\n }\r\n else{\r\n scope.crewMembers = scope.crew.filter(x => x.isDHC );\r\n }\r\n\r\n function openPhoneConfirmation(crew){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/CrewInfo/dlgConfirmCrewCall.html',\r\n controller: 'CrewCallCtrl',\r\n size: 'md',\r\n resolve: {\r\n crew: function () {return crew;},\r\n flightId: function () {return scope.flightId;}\r\n }\r\n });\r\n modalInstance.result.then(function (confirm) {\r\n \r\n });\r\n }\r\n\r\n function showInfoRow(item){\r\n var differentUser = scope.user.aimsId != item.aimsId \r\n var phoneAvailable = item.PhoneNumber && item.PhoneNumber != '';\r\n var previousDutyAvailable = item.PreviousDuty && item.PreviousDuty.isDifferent;\r\n var phonesAvailable = scope.crew.filter(x => x.PhoneNumber && x.PhoneNumber != '').length > 0;\r\n var checkInStatusAvailable = scope.crew.filter(x => x.CheckIn || x.WillBeThereAt).length > 0;\r\n\r\n return differentUser && (phoneAvailable || previousDutyAvailable || phonesAvailable || checkInStatusAvailable);\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/CrewInfo/crewInfo.tpl.html',\r\n scope: {crew:\"=\", type:\"=\", flightId:\"=\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('crewPreviousInfo', crewPreviousInfo);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name crewPreviousInfo\r\n * @restrict E\r\n * @description\r\n * Crew Table with a double row per crew member showing previous duty info\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function crewPreviousInfo($uibModal, UserFactory) {\r\n function link(scope, element, attrs) {\r\n scope.user = UserFactory.getUser();\r\n scope.filterByPreviousDuty = filterByPreviousDuty;\r\n\r\n if(scope.type==\"flight\"){\r\n scope.crewMembers = scope.crew.filter(x => (x.position =='CP' || x.position == \"FO\") && !x.isDHC );\r\n }\r\n else if(scope.type==\"cabin\"){\r\n scope.crewMembers = scope.crew.filter(x => (x.position =='SA' || x.position == \"FA\") && !x.isDHC );\r\n }\r\n else{\r\n scope.crewMembers = scope.crew.filter(x => x.isDHC );\r\n }\r\n\r\n function filterByPreviousDuty(){\r\n return function( crew ) {\r\n return crew.PreviousDuty && crew.PreviousDuty.isDifferent;\r\n };\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/CrewInfo/crewPreviousInfo.tpl.html',\r\n scope: {crew:\"=\", type:\"=\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('LogCallFactory', LogCallFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name LogCallFactory\r\n * @ngInject\r\n */\r\n function LogCallFactory(GenericService, $http, apiUrl) {\r\n function LogCall() {\r\n this.Requester = null;\r\n this.Requestee = null;\r\n\t\t\tthis.FlightId = null;\r\n this.Date = null;\r\n\t\t}\r\n \r\n var objType ='logCall';\r\n\t\tvar objCallback = LogCall; \r\n\r\n var service = {\r\n getLogCallsFromStorage : getLogCallsFromStorage,\r\n cleanLogsFromStorage : cleanLogsFromStorage,\r\n saveLogCall : saveLogCall\r\n };\r\n\r\n /**\r\n * Get Offline Logged Calls.\r\n * @memberof LogCallFactory\r\n */\r\n\t\tfunction getLogCallsFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Clean local storage\r\n * @memberof CrewCallFactory\r\n */\r\n\t\tfunction cleanLogsFromStorage() {\r\n GenericService.removeAll(objType,objCallback);\r\n }\r\n\r\n\r\n /**\r\n\t\t * Save an offline call request\r\n * @memberof CrewCallFactory\r\n\t\t * @param {object} logData \r\n\t\t */\r\n\t\tfunction saveLogCall(logData){\r\n GenericService.add(logData, objType, objCallback);\r\n\t\t}\r\n\r\n return service;\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('PreviousDutyFactory', PreviousDutyFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PreviousDutyFactory\r\n * @ngInject\r\n */\r\n function PreviousDutyFactory(GenericService, $http, apiUrl) {\r\n function PreviousDuty() {\r\n\t\t\tthis.FlightId = null;\r\n this.CrewId = null;\r\n this.PreviousDuty = null;\r\n\t\t}\r\n\r\n var objType ='previousDuty';\r\n\t\tvar objCallback = PreviousDuty; \r\n\r\n var service = {\r\n getPreviousDutiesFromStorage : getPreviousDutiesFromStorage,\r\n setPreviousDutiesToStorage : setPreviousDutiesToStorage,\r\n getPreviousDutyFromStorage : getPreviousDutyFromStorage,\r\n getFlightPreviousDutiesFromStorage : getFlightPreviousDutiesFromStorage,\r\n savePreviousDuty : savePreviousDuty,\r\n cleanOldData : cleanOldData,\r\n cleanFlightPreviousDuties : cleanFlightPreviousDuties,\r\n saveFlightPreviousDuties : saveFlightPreviousDuties\r\n };\r\n\r\n /**\r\n * Get Crew Phone Numbers.\r\n * @memberof PreviousDutyFactory\r\n * @returns {Array} PreviousDuties \r\n */\r\n\t\tfunction getPreviousDutiesFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Get Crew Phone Numbers for specified flight\r\n * @memberof PreviousDutyFactory\r\n * @param {number} flightId\r\n * @returns {Array} PreviousDuties \r\n */\r\n\t\tfunction getFlightPreviousDutiesFromStorage(flightId) {\r\n\t\t\tvar previousDuties = GenericService.list(objType,objCallback);\r\n return previousDuties.filter(x => x.FlightId == flightId);\r\n\t\t}\r\n\r\n /**\r\n * Save Crew Phone Numbers to storage\r\n * @memberof PreviousDutyFactory\r\n * @param {Array} PreviousDuties\r\n */\r\n\t\tfunction setPreviousDutiesToStorage(objList) {\r\n\t\t\tGenericService.saveAll(objList,objType);\r\n }\r\n\r\n /**\r\n * Get Previous Duty from storage \r\n * @memberof PreviousDutyFactory\r\n * @param {number} crewId\r\n * @param {number} flightId\r\n * @return {object} previous duty info\r\n */\r\n\t\tfunction getPreviousDutyFromStorage(crewId, flightId) {\r\n var previousDuties = getPreviousDutiesFromStorage();\r\n\r\n return previousDuties.find(x => x.FlightId == flightId && x.CrewId == crewId);\r\n\t\t}\r\n \r\n /**\r\n\t\t * Save a fetched previous duty\r\n * @memberof PreviousDutyFactory\r\n\t\t * @param {object} previousDuty \r\n\t\t */\r\n\t\tfunction savePreviousDuty(previousDuty){\r\n GenericService.add(previousDuty, objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Clean ls from old flight previous duties\r\n * @param {array} flights Synced flights\r\n */\r\n function cleanOldData(flights){\r\n var flightIds = flights.map(x => x.FlightId);\r\n var previousDuties = getPreviousDutiesFromStorage();\r\n \r\n //Filter out previous duties of old flights\r\n previousDuties = previousDuties.filter(x => flightIds.includes(x.FlightId));\r\n \r\n setPreviousDutiesToStorage(previousDuties);\r\n }\r\n\r\n /**\r\n * Clean all stored previous duties for selected flight\r\n * @param {number} flightId \r\n */\r\n function cleanFlightPreviousDuties(flightId){\r\n var previousDuties = getPreviousDutiesFromStorage();\r\n\t\t\tpreviousDuties = previousDuties.filter(x => x.FlightId != flightId);\r\n\t\t\tsetPreviousDutiesToStorage(previousDuties); \r\n }\r\n\r\n /**\r\n * Save previous duty info for each flight crew member that has one \r\n * @param {number} flightId \r\n * @param {array} crew \r\n */\r\n function saveFlightPreviousDuties(flightId, crew){\r\n\t\t\t\tcrew.forEach(function(user){\r\n\t\t\t\t\tif(user.PreviousDuty){\r\n\t\t\t\t\t\tvar previousDuty = {\r\n\t\t\t\t\t\t\tFlightId : flightId,\r\n\t\t\t\t\t\t\tCrewId : user.id,\r\n\t\t\t\t\t\t\tPreviousDuty : user.PreviousDuty\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tsavePreviousDuty(previousDuty);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n }\r\n \r\n return service;\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('CrewHotelFactory', CrewHotelFactory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewHotelFactory\r\n * @description \r\n * Get hotels\r\n * @ngInject\r\n */\r\n function CrewHotelFactory(GenericService, showHotelsAcTypes) {\r\n\r\n var objType = 'crewHotel';\r\n var objCallback = CrewHotel;\r\n\r\n var service = {\r\n getCrewHotelsFromStorage: getCrewHotelsFromStorage,\r\n setCrewHotelsToStorage: setCrewHotelsToStorage,\r\n showHotelsInCalendar: showHotelsInCalendar \r\n };\r\n\r\n /**\r\n * Initialize the CrewHotel\r\n * @memberof CrewHotelFactory\r\n */\r\n function CrewHotel() {\r\n this.AimsId = null;\r\n this.CrewName = null;\r\n this.DutyDate = null;\r\n this.Base = null;\r\n this.Airport = null;\r\n this.HotelNo = null;\r\n this.HotelName = null;\r\n this.GroundTime = null;\r\n }\r\n\r\n /**\r\n * Get Crew Hotels\r\n * @memberof CrewHotelFactory\r\n * @returns {Array} CrewHotels \r\n */\r\n function getCrewHotelsFromStorage() {\r\n return GenericService.list(objType, objCallback);\r\n }\r\n\r\n /**\r\n * Save Crew Hotels to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} objList A list of Crew Hotels\r\n */\r\n function setCrewHotelsToStorage(objList) {\r\n GenericService.saveAll(objList, objType);\r\n }\r\n\r\n\r\n /**\r\n * Get flights for a specific duty date. Show hotels check depend on ac types\r\n * @memberof AutolandFactory\r\n * @param {object} flights the flight object of sync response\r\n * @returns {bool} showHotelsInCalendar\r\n */\r\n function showHotelsInCalendar(flights) {\r\n var oaFlights = flights.filter(x => x.IsDHC == false && showHotelsAcTypes.includes(x.AcType));\r\n return oaFlights.length > 0;\r\n }\r\n\r\n\r\n return service;\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('CrewMealFactory', CrewMealFactory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewMealFactory\r\n * @description \r\n * Get and Update Crew Meals \r\n * @ngInject\r\n */\r\n function CrewMealFactory(GenericService, $http, apiUrl) {\r\n\r\n var objType = 'crewMeal';\r\n var objCallback = CrewMeal;\r\n var objCallbackRatings = RatingObj;\r\n var ratingSubmitResponseObj = { success: false, message: '' }\r\n\r\n var service = {\r\n getCrewMealsFromStorage: getCrewMealsFromStorage,\r\n setCrewMealsToStorage: setCrewMealsToStorage,\r\n getCrewMealFromStorage: getCrewMealFromStorage,\r\n sendCrewMealsRatingReport: sendCrewMealsRatingReport,\r\n hasRating: hasRating,\r\n getCrewMealsDidNotEatReasons: getCrewMealsDidNotEatReasons\r\n };\r\n\r\n /**\r\n * Initialize the CrewMeal\r\n * @memberof CrewMealFactory\r\n */\r\n function CrewMeal() {\r\n this.CateringMealId = null;\r\n this.Title = null;\r\n this.Description = null;\r\n }\r\n\r\n function RatingObj() {\r\n this.CrewMealId = null,\r\n this.TimeStamp = null\r\n\r\n }\r\n\r\n /**\r\n * Get Crew Meals\r\n * @memberof CrewMealFactory\r\n * @returns {Array} CrewMeals \r\n */\r\n function getCrewMealsFromStorage() {\r\n return GenericService.list(objType, objCallback);\r\n }\r\n\r\n /**\r\n * Save Crew Meals to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} objList A list of Crew Meals\r\n */\r\n function setCrewMealsToStorage(objList) {\r\n GenericService.saveAll(objList, objType);\r\n }\r\n\r\n /**\r\n * Get a specific Crew Meal\r\n * @memberof CrewMealFactory\r\n * @returns {object} CrewMeal\r\n */\r\n function getCrewMealFromStorage(cateringMealId) {\r\n var crewMeals = getCrewMealsFromStorage();\r\n if (crewMeals == null)\r\n return [];\r\n var arrayLength = crewMeals.length;\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (crewMeals[i].CateringMealId == cateringMealId) {\r\n return crewMeals[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks if the specified crew meal has rating\r\n * @memberof CrewMealFactory\r\n * @returns {boolean} response\r\n */\r\n function hasRating(crewMealId) {\r\n var res = GenericService.list(\"CrewMealRatings\", objCallbackRatings);\r\n return res.some(e => e.CrewMealId === crewMealId.toString());\r\n }\r\n\r\n /**\r\n * Sends the crew meals rating report\r\n * @memberof CrewMealFactory\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\r\n function sendCrewMealsRatingReport(ratingForm) {\r\n var objectToAdd = { CrewMealId: ratingForm.CrewMealId, TimeStamp: new Date() }\r\n return $http.post(apiUrl + '/CrewMealsRating/SaveReport', ratingForm, { 'Content-Type': 'application/json' })\r\n .then(res => saveReportSuccessCallBack(res, objectToAdd))\r\n .catch(res => saveReportFailedCallBack(res));\r\n }\r\n\r\n\r\n /**\r\n * The callback function if the seve report succeed\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\r\n function saveReportSuccessCallBack(res, objectToAdd) {\r\n ratingSubmitResponseObj.success = res.data.success;\r\n if (res.data.success) {\r\n GenericService.add(objectToAdd, \"CrewMealRatings\", objCallbackRatings);\r\n ratingSubmitResponseObj.message = \"Thank you for your feedback\";\r\n }\r\n else {\r\n ratingSubmitResponseObj.message = res.data.errorMessage\r\n }\r\n return ratingSubmitResponseObj;\r\n }\r\n\r\n /**\r\n * Gets the choices for the dropdown if a crew member did not eat their meal\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\r\n function getCrewMealsDidNotEatReasons() {\r\n return $http.get(apiUrl + '/CrewMealsRating/GetCrewMealsDidNotEatReasons', { 'Content-Type': 'application/json' })\r\n .then((res) => {\r\n return res.data;\r\n });\r\n }\r\n\r\n /**\r\n * The callback function if the seve report fail\r\n * @returns {ratingSubmitResponseObj} ratingSubmitResponseObj\r\n */\r\n function saveReportFailedCallBack(res) {\r\n ratingSubmitResponseObj.success = false;\r\n ratingSubmitResponseObj.message = \"Something went wrong!\"\r\n return ratingSubmitResponseObj;\r\n }\r\n\r\n return service;\r\n }\r\n\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('CrewRouteCtrl', CrewRouteCtrl);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CrewRouteCtrl\r\n * @description \r\n * Shows the crew route information\r\n * @ngInject\r\n */\r\n function CrewRouteCtrl($scope, $filter, $routeParams, $route, FlightFactory, GroundDutyFactory, CrewRouteFactory, $location, $uibModal, SyncLogFactory) {\r\n var dutyNo = $routeParams.dutyNo;\r\n var dutyDay = $routeParams.dutyDay;\r\n $scope.crewRouteDuty = CrewRouteFactory.getCrewRouteFromStorage(dutyNo, dutyDay);\r\n \r\n var groundDuties = GroundDutyFactory.getGroundDutiesByDutyNo(dutyNo, dutyDay);\r\n if(groundDuties.length > 0){ //there are ground duties in this crew route\r\n angular.forEach(groundDuties, function(groundDuty)\r\n {\r\n groundDuty.DutyType = \"Ground\";\r\n groundDuty.Start = groundDuty.DutyBegin;\r\n });\r\n }\r\n\r\n var flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay);\r\n if(flights.length > 0){ //there are flights in this crew route\r\n angular.forEach(flights, function(flight)\r\n {\r\n flight.DutyType = \"Flight\";\r\n flight.Start = flight.ScheduledDeparture;\r\n });\r\n }\r\n\r\n var crewRoute = groundDuties.concat(flights);\r\n crewRoute = $filter('orderBy')(crewRoute, 'Start', false);\r\n $scope.crewRoute = crewRoute;\r\n $scope.currentDutyDay = null;\r\n $scope.differentDay = differentDay;\r\n $scope.currentPage = 1;\r\n $scope.previous = previous;\r\n $scope.next = next;\r\n $scope.openRefresh = openRefresh;\r\n $scope.dutyNo = dutyNo;\r\n $scope.dutyDay = dutyDay;\r\n\r\n /**\r\n * Checks if two dates have the same day\r\n * @param {string} day1 \r\n * @param {string} day2 \r\n */\r\n function differentDay(day1, day2){\r\n day1 = new Date(day1).trimTime().getDay();\r\n day2 = new Date(day2).trimTime().getDay();\r\n return !(day1==day2);\r\n }\r\n\r\n /**\r\n * Moves pager to previous page\r\n */\r\n function previous(){\r\n if($scope.currentPage != 1)\r\n $scope.currentPage--;\r\n }\r\n\r\n /**\r\n * Moves pager to next page\r\n */\r\n function next(){\r\n if($scope.currentPage != crewRoute.length)\r\n $scope.currentPage++;\r\n }\r\n\r\n \r\n /**\r\n * Opens refresh modal\r\n */\r\n function openRefresh(){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/CrewRoute/dlgCrewRouteRefresh.html',\r\n controller: 'CrewRouteRefreshModalCtrl',\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n crewroute: function () { return $scope.crewRoute}, \r\n crewRouteDuty: function () { return $scope.crewRouteDuty; },\r\n }\r\n });\r\n \r\n modalInstance.result.then(function (transferData) {\r\n if(transferData.sync){\r\n SyncLogFactory.forceSync();\r\n $location.path(\"/\"); //crew route has significantly changed\r\n }\r\n else if(transferData.refresh){\r\n $route.reload(); //crew route was updated\r\n }\r\n });\r\n }\r\n\r\n }\r\n })();\r\n","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('CrewRouteFactory', CrewRouteFactory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CrewRouteFactory\r\n * @description \r\n * Get and Update Crew Routes \r\n * @ngInject\r\n */ \r\nfunction CrewRouteFactory(GenericService, FlightFactory) {\r\n\r\n\t\tvar objType ='crewRoute';\r\n\t\tvar objCallback = CrewRoute;\r\n\r\n\t\tvar service = {\r\n getCrewRoutesFromStorage : getCrewRoutesFromStorage,\r\n setCrewRoutesToStorage : setCrewRoutesToStorage,\r\n getCrewRouteFromStorage: getCrewRouteFromStorage,\r\n setCourseCompleted: setCourseCompleted,\r\n setCoursePending : setCoursePending\r\n };\r\n \r\n /**\r\n * Initialize the CrewRoute\r\n * @memberof CrewRouteFactory\r\n */\r\n\t\tfunction CrewRoute() {\r\n this.DutyDay = null; \r\n this.DutyNo = null; \r\n this.Route = null;\r\n this.DutyBegin = null;\r\n this.DutyEnd = null;\r\n this.CrewMeals = [];\r\n\r\n }\r\n \r\n /**\r\n * Get Crew Routes\r\n * @memberof CrewRouteFactory\r\n * @returns {Array} CrewRoutes \r\n */\r\n\t\tfunction getCrewRoutesFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Save Crew Routes to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} objList A list of Crew Routes\r\n */\r\n\t\tfunction setCrewRoutesToStorage(objList) {\r\n\t\t\tGenericService.saveAll(objList,objType);\r\n }\r\n\r\n /**\r\n * Get a specific Crew Route\r\n * @memberof CrewRouteFactory\r\n * @returns {object} CrewRoute\r\n */\r\n function getCrewRouteFromStorage(dutyNo, dutyDay){\r\n var crewRoutes = getCrewRoutesFromStorage();\r\n\t\t\tif (crewRoutes == null)\r\n\t\t\t\treturn [];\r\n\t\t\tvar arrayLength = crewRoutes.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (crewRoutes[i].DutyNo == dutyNo && crewRoutes[i].DutyDay == dutyDay) {\r\n\t\t\t\t\treturn crewRoutes[i];\r\n\t\t\t\t}\r\n }\r\n }\r\n\r\n function setCourseCompleted(dutyNo, dutyDay, courseId, date){\r\n var crewRoutes = getCrewRoutesFromStorage();\r\n var crewRoute = crewRoutes.find(cr => cr.DutyNo == dutyNo && cr.DutyDay == dutyDay);\r\n\r\n var flightIds = crewRoute.FlightIds\r\n var flights = FlightFactory.getFlightsFromStorage().filter(x => flightIds.includes(x.FlightId));\r\n\r\n var crewRouteCourse = crewRoute.Courses.find(x => x.CourseId == courseId && new moment(x.Date).isSame(date));\r\n if(crewRouteCourse) crewRouteCourse.Status = \"Completed\"; \r\n \r\n flights.forEach(function(flight){\r\n var flightCourse = flight.Courses.find(x => x.CourseId == courseId && new moment(x.Date).isSame(date));\r\n if(flightCourse) {\r\n flightCourse.Status = \"Completed\"; \r\n FlightFactory.updateFlight(flight);\r\n }\r\n });\r\n\r\n GenericService.saveAll(crewRoutes, objType, objCallback);\r\n }\r\n\r\n function setCoursePending(dutyNo, dutyDay, courseId, date){\r\n var crewRoutes = getCrewRoutesFromStorage();\r\n var crewRoute = crewRoutes.find(cr => cr.DutyNo == dutyNo && cr.DutyDay == dutyDay);\r\n var crewRouteCourse = crewRoute.Courses.find(x => x.CourseId == courseId && new moment(x.Date).isSame(date));\r\n if(crewRouteCourse) crewRouteCourse.Status = \"Pending\"; \r\n \r\n GenericService.saveAll(crewRoutes, objType, objCallback);\r\n }\r\n \r\n\t\treturn service;\r\n\t}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('CrewRouteRefreshModalCtrl', CrewRouteRefreshModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CrewRouteRefreshModalCtrl\r\n * @description \r\n * \r\n * @ngInject\r\n */\r\n\r\n function CrewRouteRefreshModalCtrl($scope, FlightFactory, GroundDutyFactory, $timeout, $uibModalInstance, crewroute, crewRouteDuty, InfoAPIService, SyncAPIService, $filter, FlightSessionFactory, CourseFactory, $routeParams){\r\n $scope.crewroute = crewroute;\r\n $scope.crewRouteDuty = crewRouteDuty;\r\n $scope.isRefreshing = true;\r\n $scope.refreshResultsVisible = false;\r\n $scope.error = false;\r\n $scope.sync = false;\r\n $scope.collapse = collapse\r\n\r\n $scope.close = close;\r\n \r\n var dutyNo = Number($routeParams.dutyNo);\r\n var dutyDay = Number($routeParams.dutyDay);\r\n\r\n //add DataStatus to each duty\r\n for(var i = 0; i < crewroute.length; i++){\r\n if(crewroute[i].DutyType == 'Flight'){\r\n crewroute[i].DataStatus = [\r\n {\r\n datatype: \"Flight Status\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Aircraft Movement\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Crew Info\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Pax Info\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Meals\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Connections\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Training Info\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n }\r\n ]\r\n } \r\n else if(crewroute[i].DutyType == 'Ground'){\r\n if(crewroute[i].isTraining){\r\n crewroute[i].DataStatus = [\r\n {\r\n datatype: \"Duty Info\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Instructors\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n },\r\n {\r\n datatype: \"Trainees\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n }\r\n ]\r\n }\r\n else{\r\n crewroute[i].DataStatus = [\r\n {\r\n datatype: \"Duty Info\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n }\r\n ]\r\n }\r\n \r\n }\r\n \r\n }\r\n \r\n //separate flights and groundDuties \r\n var currentFlights = [];\r\n var currentGroundDuties = [];\r\n for(var i = 0; i < crewroute.length; i++){\r\n if(crewroute[i].DutyType == 'Flight') currentFlights.push(crewroute[i]);\r\n else if(crewroute[i].DutyType == 'Ground') currentGroundDuties.push(crewroute[i]);\r\n \r\n crewroute[i].isCollapsed = false;\r\n }\r\n\r\n //get latest info\r\n InfoAPIService.refreshCrewRoute(crewRouteDuty, function (responseData) {\r\n $scope.isRefreshing = false;\r\n\r\n var newFlights = responseData.data.data.flights;\r\n var newGroundDuties = responseData.data.data.groundDuties;\r\n\r\n //if there are significant changes in crew route user should sync\r\n if(needsSynch(currentFlights, newFlights, currentGroundDuties, newGroundDuties)){\r\n $scope.sync = true;\r\n }\r\n else{\r\n //Manage details info and Update local storage\r\n if(newFlights.length){\r\n setupFlightInfo(newFlights); \r\n updateFlights(newFlights); \r\n \r\n //Save training\r\n newFlights.forEach(function(flight){\r\n var trainingCourses = flight.TrainingCourses;\r\n if(trainingCourses && trainingCourses.length && flight.FlightInfo){\r\n trainingCourses.forEach(function(trainingCourse){\r\n CourseFactory.upsertCourse(trainingCourse, function(course) {\r\n FlightSessionFactory.applyTraineeInfoToSession(course, course.Id, new moment(flight.FlightInfo.FlightDate).format(\"YYYY-MM-DD\"), dutyNo, dutyDay, function(session) {\r\n });\r\n });\r\n });\r\n }\r\n });\r\n \r\n }\r\n if(newGroundDuties.length){\r\n setupGroundInfo(newGroundDuties);\r\n updateGroundDuties(newGroundDuties);\r\n }\r\n\r\n $scope.refreshResultsVisible = true;\r\n }\r\n })\r\n .catch(function(){\r\n $scope.error = true;\r\n $scope.isRefreshing = false;\r\n });\r\n\r\n /**\r\n * Checks if crew route has significantly changed and needs sync\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} currentFlights Array of current flights\r\n * @param {array} newFlights Array of newly fetched flights\r\n * @param {array} currentGroundDuties Array of current ground duties\r\n * @param {array} newGroundDuties Array of newly fetched ground duties\r\n */\r\n function needsSynch(currentFlights, newFlights, currentGroundDuties, newGroundDuties){\r\n var sync = false;\r\n //1.Crew Route may not exist any more\r\n if(!newFlights.length && !newGroundDuties.length){\r\n sync = true;\r\n }\r\n //2.Duties may have been added/removed \r\n else if( (newFlights.length != currentFlights.length) || (newGroundDuties.length != currentGroundDuties.length) ){\r\n sync = true; //different size arrays\r\n }\r\n else{ //same size arrays\r\n if(currentFlights.length && newFlights.length){ //compare current with new flights\r\n \r\n currentFlights = $filter('orderBy')(currentFlights, 'FlightId');\r\n newFlights = $filter('orderBy')(newFlights, 'FlightInfo.FlightId');\r\n for(var i = 0; i < currentFlights.length; i ++){\r\n if(newFlights[i].FlightInfo && currentFlights[i].FlightId != newFlights[i].FlightInfo.FlightId){\r\n sync = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if(currentGroundDuties.length && newGroundDuties.length){ //compare current with new ground duties\r\n currentGroundDuties = $filter('orderBy')(currentGroundDuties, 'Id');\r\n newGroundDuties = $filter('orderBy')(newGroundDuties, 'Id');\r\n for(var i = 0; i < currentGroundDuties.length; i ++){\r\n if(currentGroundDuties[i].Id != newGroundDuties[i].Id){\r\n sync = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n return sync;\r\n }\r\n\r\n /**\r\n * Updates Flight in Local Storage\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newFlights \r\n */\r\n function updateFlights(newFlights){\r\n for(var i = 0; i < newFlights.length; i++){\r\n InfoAPIService.updateFlightLocalStorage(newFlights[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Updates Flight's Data Status\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newFlights \r\n */\r\n function setupFlightInfo(newFlights){\r\n\r\n newFlights = $filter('orderBy')(newFlights, 'Start', false);\r\n currentFlights = $filter('orderBy')(currentFlights, 'Start', false);\r\n\r\n for(var i = 0; i < newFlights.length; i++){\r\n InfoAPIService.updateFlightStatusSetter(newFlights[i], currentFlights[i].DataStatus);\r\n }\r\n }\r\n\r\n /**\r\n * Updates Ground Duty's Data Status\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newGroundDuties \r\n */\r\n function setupGroundInfo(newGroundDuties){\r\n newGroundDuties = $filter('orderBy')(newGroundDuties, 'Start', false);\r\n currentGroundDuties = $filter('orderBy')(currentGroundDuties, 'Start', false);\r\n\r\n for(var i = 0; i < newGroundDuties.length; i++){\r\n InfoAPIService.updateGroundStatusSetter(newGroundDuties[i], currentGroundDuties[i].DataStatus);\r\n }\r\n }\r\n\r\n /**\r\n * Updates Ground Duty in Local Storage\r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {array} newFlights \r\n */\r\n function updateGroundDuties(newGroundDuties){\r\n for(var i = 0; i < newGroundDuties.length; i++){\r\n InfoAPIService.updateGroundDutyLocalStorage(newGroundDuties[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Shows Details \r\n * @memberof CrewRouteRefreshModalCtrl\r\n * @param {object} duty \r\n */\r\n function collapse(duty){\r\n if(!$scope.isRefreshing && $scope.refreshResultsVisible) \r\n duty.isCollapsed = !duty.isCollapsed;\r\n }\r\n\r\n /**\r\n * Closes the modal\r\n * @memberof CrewRouteRefreshModalCtrl\r\n */\r\n function close(){\r\n $uibModalInstance.close({sync: $scope.sync, refresh: $scope.refreshResultsVisible});\r\n }\r\n\r\n }\r\n})();","// array functions\r\nArray.prototype.dynamicSort = function(property,orderByAsc) {\r\n function dynamicSortComparator(property,orderByAsc) {\r\n var sortOrder = orderByAsc ? 1 : -1;\r\n\r\n return function (a,b) {\r\n var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;\r\n return result * sortOrder;\r\n }\r\n }\r\n \r\n var sortedArray = this;\r\n if(property!=null && property != undefined){\r\n orderByAsc = orderByAsc == null || orderByAsc == undefined ? true : orderByAsc; \r\n sortedArray = this.sort(dynamicSortComparator(property,orderByAsc))\r\n }\r\n\treturn sortedArray;\r\n};\r\n\r\nArray.prototype.unique = function() {\r\n var arr = [];\r\n for(var i = 0; i < this.length; i++) {\r\n if(!arr.contains(this[i])) {\r\n arr.push(this[i]);\r\n }\r\n }\r\n return arr; \r\n};\r\nArray.prototype.contains = function(v) {\r\n for(var i = 0; i < this.length; i++) {\r\n if(this[i] === v) return true;\r\n }\r\n return false;\r\n};","// date functions\r\nDate.prototype.toUTC = function() {\r\n\treturn new Date(this.getTime() + this.getTimezoneOffset() * 60 * 1000);\r\n};\r\n\r\nDate.prototype.fromUTC = function() {\r\n\treturn new Date(this.getTime() - this.getTimezoneOffset() * 60 * 1000);\r\n};\r\n\r\nDate.prototype.trimTime = function() {\r\n\tthis.setHours(0, 0, 0, 0);\r\n\treturn this;\r\n};\r\n\r\nvar _DatetoJSON = Date.prototype.toJSON;\r\nDate.prototype.toJSON = function() {\r\n try {\r\n return _DatetoJSON.call(this);\r\n } catch(e) {\r\n if (e instanceof RangeError) {\r\n return null;\r\n }\r\n throw e;\r\n }\r\n};\r\n\r\nDate.DifferenceInMinutes = function(firstDate, secondDate) {\r\n var diffInMins = null;\r\n if(firstDate && secondDate){\r\n var _MS_TO_MINUTES = 1000 * 60;\r\n var date1 = new Date(firstDate);\r\n var date2 = new Date(secondDate);\r\n diffInMins = Math.floor((date2.getTime() - date1.getTime()) / _MS_TO_MINUTES);\r\n }\r\n return diffInMins;\r\n};\r\n\r\nDate.DifferenceInDays = function (firstDate, secondDate) {\r\n var diffInDays = null;\r\n if (firstDate && secondDate){\r\n var _MS_TO_DAYS = 1000 * 3600 * 24;\r\n diffInDays = Math.floor((secondDate.getTime() - firstDate.getTime()) / _MS_TO_DAYS);\r\n }\r\n return diffInDays;\r\n}\r\n\r\n\r\nDate.MinutesToString = function(minutes){\r\n var hours = Math.floor( minutes / 60); \r\n var mins = minutes % 60;\r\n return (hours > 0 ? hours + (hours == 1 ? \"hr \": \"hrs \") : \"\") + (mins > 0 ? mins + (mins == 1 ? \"min\": \"mins\") : \"\");\r\n}\r\n\r\nDate.prototype.AddDays = function(days) {\r\n var date = new Date(this.valueOf());\r\n date.setDate(date.getDate() + days);\r\n return date;\r\n}","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('GroundDutyCtrl', GroundDutyCtrl);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name GroundDutyCtrl\r\n * @description \r\n * Shows the ground duty information\r\n * @ngInject\r\n */\r\n function GroundDutyCtrl(GroundDutyFactory, CourseFactory, TrainingSessionFactory, $scope, $location, $routeParams) {\r\n $scope.toggleCrewList = toggleCrewList\r\n $scope.toggleEditMode = toggleEditMode;\r\n $scope.selectTrainee = selectTrainee;\r\n\r\n $scope.refresh = refresh;\r\n $scope.refreshSuccess = true;\r\n $scope.isRefreshing = false;\r\n\r\n var groundDutyId = Number($routeParams.groundDutyId);\r\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(groundDutyId);\r\n $scope.dutyCourses = GroundDutyFactory.getGroundDutyActiveCourses(groundDutyId);\r\n\r\n if (!groundDuty) {\r\n // go to dashboard if no groundDuty\r\n $location.path(\"/\");\r\n } else {\r\n\r\n //Toggle trainees\r\n groundDuty.Trainees.forEach(function(relatedTrainees) {\r\n relatedTrainees.isCollapsed = false;\r\n relatedTrainees.dynamicSize = 10;\r\n });\r\n\r\n //Collect all trainees in list\r\n var traineesFlat = [];\r\n groundDuty.Trainees.forEach(function(related) {\r\n related.CrewMembers.forEach(function(trainee) {\r\n traineesFlat.push(trainee);\r\n });\r\n });\r\n\r\n groundDuty.traineesFlat = traineesFlat;\r\n\r\n if (groundDuty.RelatedGroundDuties) {\r\n $scope.courses = GroundDutyFactory.getGroundDutyActiveCourses(groundDutyId);\r\n }\r\n\r\n $scope.groundDuty = groundDuty;\r\n $scope.groundDutyId = groundDutyId;\r\n\r\n }\r\n\r\n function toggleCrewList(relatedTrainees) {\r\n relatedTrainees.isCollapsed = !relatedTrainees.isCollapsed;\r\n\r\n if (relatedTrainees.isCollapsed) relatedTrainees.dynamicSize = relatedTrainees.CrewMembers.length;\r\n else relatedTrainees.dynamicSize = 10;\r\n }\r\n\r\n function toggleEditMode(elem, className) {\r\n $('body').find('div#' + elem + ' > div').not('.tip').hide(\"slow\");\r\n $('body').find('div#' + elem + ' div.' + className).not('.tip').show(\"slow\");\r\n }\r\n\r\n\r\n /**\r\n * Edit ground duty's attendance list\r\n * @param {object} trainee \r\n */\r\n function selectTrainee(trainee) {\r\n //Value will be saved in ground duty's crew members\r\n trainee.Absent = !trainee.Absent;\r\n GroundDutyFactory.updateGroundDuty($scope.groundDuty);\r\n }\r\n\r\n \r\n /**\r\n * Sync ground duty\r\n */\r\n function refresh(){\r\n var courseIds = $scope.dutyCourses.map(x => x.CourseId).filter(onlyUnique);\r\n\r\n var refreshGroundDuty = {\r\n DutyId: groundDutyId,\r\n CourseIds : courseIds\r\n };\r\n\r\n $scope.isRefreshing = true;\r\n\r\n //get latest info\r\n GroundDutyFactory.refresh(refreshGroundDuty, function (responseData) {\r\n $scope.isRefreshing = false;\r\n $scope.refreshSuccess = true;\r\n\r\n //Save training\r\n var trainingCourses = responseData.data.TrainingCourses;\r\n if(trainingCourses && trainingCourses.length){\r\n trainingCourses.forEach(function(trainingCourse){\r\n CourseFactory.upsertCourse(trainingCourse, function(course) {\r\n TrainingSessionFactory.applyTraineeInfoToSession(course, course.Id, $scope.groundDuty.DutyDateS, groundDutyId, function(session) {\r\n });\r\n });\r\n });\r\n }\r\n })\r\n .catch(function () {\r\n $scope.refreshSuccess = false;\r\n $scope.isRefreshing = false;\r\n });\r\n }\r\n\r\n function onlyUnique(value, index, self) {\r\n return self.indexOf(value) === index;\r\n }\r\n }\r\n})();","// generic string functions\r\nString.prototype.endsWith = function(suffix) {\r\n return this.indexOf(suffix, this.length - suffix.length) !== -1;\r\n};\r\n\r\nif (typeof String.prototype.startsWith != 'function') {\r\n\t // see below for better implementation!\r\n\t String.prototype.startsWith = function (str){\r\n\t return this.indexOf(str) == 0;\r\n\t };\r\n}\r\n\r\nString.prototype.reverse = function() {\r\n\treturn this.split(\"\").reverse().join(\"\");\r\n}\r\n\r\nString.prototype.getHash = function() {\r\n\tvar shaObj = new jsSHA(\"SHA-512\", \"TEXT\");\r\n\tshaObj.update(this);\r\n\tvar hash = shaObj.getHash(\"HEX\");\r\n\treturn hash;\r\n};\r\n\r\n\r\n\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('autorefresh', autorefresh);\r\n\r\n function autorefresh($interval, $timeout, PushNotifier, InfoAPIService, FlightFactory, PaxInfoFactory, AircaftPositionsFactory, CrewCallFactory, PreviousDutyFactory) {\r\n\r\n function link($scope, element, attrs) {\r\n\r\n var flight = $scope.flight;\r\n\r\n //Auto refresh functionality start\r\n var browserNotificationsEnabled = false;\r\n var autoUpdateInterval = null;\r\n var autoUpdateIntervalTimeOffset = null;\r\n $scope.showAlternativeNotifications = false;\r\n $scope.showAutoUpdatePanel = false;\r\n\r\n //Check if push notification are enabled\r\n PushNotifier.CheckForPermissionsAndSupport().then(function (res) {\r\n browserNotificationsEnabled = res\r\n });\r\n\r\n var ScheduledDepartureTimeStamp = 0;\r\n if(flight){\r\n ScheduledDepartureTimeStamp = moment.utc(flight.ScheduledDeparture).valueOf();\r\n }\r\n var now = moment().valueOf();\r\n\r\n $scope.showAutoUpdatePanel = (ScheduledDepartureTimeStamp - (70 * 60000)) <= now\r\n && (ScheduledDepartureTimeStamp + (30 * 60000)) >= now\r\n && flight.DepartureEU;\r\n\r\n $scope.radioModel = false;\r\n\r\n $scope.$watch('radioModel', function (value) {\r\n if (value == true)\r\n autoflightInfoInterval();\r\n if (value == false) {\r\n $interval.cancel(autoUpdateInterval);\r\n autoUpdateInterval = null;\r\n }\r\n });\r\n\r\n function autoflightInfoInterval() {\r\n\r\n var currentInfo = null;\r\n currentInfo = PushNotifier.formatInfoToCompare(flight.FlightId);\r\n\r\n var intervalTime = timerDelayGenerator(flight.ScheduledDeparture);\r\n\r\n if (intervalTime > 0) {\r\n InfoAPIService.getPax(flight.FlightId)\r\n .then(function (responseData) {\r\n $scope.flight = FlightFactory.getFlightFromTotalFlights(flight.FlightId);\r\n $scope.paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flight.FlightId);\r\n $scope.aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId(flight.FlightId);\r\n\r\n $scope.flightETA = $scope.flight.ETA ?\r\n moment(flight.ETA).valueOf() : new Date(flight.ScheduledArrival).getTime();\r\n\r\n var updatedInfo = PushNotifier.formatInfoToCompare(flight.FlightId);\r\n var changes = PushNotifier.compareAndExtractChanges(currentInfo, updatedInfo);\r\n var message = PushNotifier.MessageGenerator(changes);\r\n\r\n //UPDATE CREW INFO\r\n //1. First remove all additional info (phone numbers & previous duties) for this flight\r\n CrewCallFactory.cleanFlightCrewNumbers(flight.FlightId);\r\n PreviousDutyFactory.cleanFlightPreviousDuties(flight.FlightId);\r\n\r\n //2. Then save any fetched info\r\n if( responseData.data.data.FlightInfo){\r\n var crew = responseData.data.data.FlightInfo.crew;\r\n CrewCallFactory.saveFlightPhoneNumbers(flight.FlightId, crew, flight.ScheduledArrival, flight.ScheduledDeparture);\r\n PreviousDutyFactory.saveFlightPreviousDuties(flight.FlightId, crew);\r\n }\r\n\r\n if (changes && changes.length > 0) {\r\n if (browserNotificationsEnabled) {\r\n try {\r\n PushNotifier.Generate('Changes', message);\r\n } catch (e) {\r\n $scope.changes = changes;\r\n $scope.showAlternativeNotifications = true;\r\n }\r\n } else {\r\n $scope.changes = changes;\r\n $scope.showAlternativeNotifications = true;\r\n }\r\n }\r\n \r\n flight = $scope.flight;\r\n\r\n\r\n $scope.flight = false;\r\n $timeout(function() {\r\n $scope.flight = flight\r\n }, 100);\r\n \r\n },\r\n function (responseData) {\r\n if (browserNotificationsEnabled && window.navigator.onLine) {\r\n try {\r\n PushNotifier.Generate('Changes', 'Update failed');\r\n } catch (ex){\r\n //TODO: add related messagge KVEN,EPAP\r\n }\r\n }\r\n });\r\n if (intervalTime != autoUpdateIntervalTimeOffset) {\r\n autoUpdateIntervalTimeOffset = intervalTime;\r\n $interval.cancel(autoUpdateInterval);\r\n autoUpdateInterval = $interval(autoflightInfoInterval, autoUpdateIntervalTimeOffset);\r\n }\r\n } else {\r\n $interval.cancel(autoUpdateInterval);\r\n $scope.showAutoUpdatePanel = false;\r\n }\r\n }\r\n\r\n function timerDelayGenerator(departureTime) {\r\n var intervalTime = -1;\r\n var depTimestamp = moment.utc(departureTime).valueOf();\r\n var nowTimeStamp = moment().valueOf();\r\n\r\n var minutes = 60000;\r\n if (depTimestamp - 70 * minutes <= nowTimeStamp && depTimestamp + 30 * minutes >= nowTimeStamp) {\r\n var absoluteMinuteDiff = Math.abs(depTimestamp - nowTimeStamp);\r\n if (absoluteMinuteDiff <= 10 * minutes) {\r\n intervalTime = 2 * minutes;\r\n } else if (absoluteMinuteDiff <= 15 * minutes) {\r\n intervalTime = 3 * minutes;\r\n } else {\r\n intervalTime = 5 * minutes;\r\n }\r\n }\r\n return intervalTime;\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'views/directives/autofresh.tpl.html',\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('basicFooter', basicFooter);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name basicFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of basicFooter (appears in groundDuty-info view)\r\n *\r\n * Initialize a basic Footer Template and its Navigation Functionality\r\n * Used in groundDuty and crewRoute view\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function basicFooter($location, SettingsMain, UserFactory, DataCleanerFactory) {\r\n /**\r\n * Initialize basicFooter and events\r\n * @memberof basicFooter\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attrs attribute of this element\r\n */\r\n function link(scope, element, attrs) {\r\n if (scope.groundDuty || scope.crewRoute) {\r\n var state = scope.state;\r\n var user = UserFactory.getUser();\r\n var delay = 60000;\r\n\r\n /**\r\n * Open a modal from which u can Logout from the application\r\n * @memberof groundFooter \r\n */\r\n function logout() {\r\n var isSecure = UserFactory.isSecure()\r\n bootbox.dialog({\r\n message: (isSecure ?\r\n \"Due to the fact that you are working over a public computer, all stored data will be deleted on logout!

\" :\r\n \"You will be able to login again into the same account, even if there is no internet access.

\") +\r\n \"Please confirm that you wish to log out.\",\r\n title: \"User Logout\",\r\n buttons: {\r\n cancel: {\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function () {}\r\n },\r\n logout: {\r\n label: \"Logout\",\r\n className: \"btn-warning\",\r\n callback: function () {\r\n UserFactory.clearActiveUser();\r\n if (isSecure) DataCleanerFactory.deleteAllData();\r\n\r\n location.reload(true);\r\n // need to reload, in order for the\r\n // browser to check the cache.manifest\r\n // and discover any changes\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Navigate to Calendar View\r\n * @memberof groundFooter \r\n */\r\n function gotoCalendar() {\r\n // handleIfReport(state, flightId, report);\r\n\r\n SettingsMain.setEditingPage(null);\r\n // go to dashboard\r\n $location.path(\"/\");\r\n }\r\n /**\r\n * Navigate to Bucket Calendar View\r\n * @memberof groundFooter \r\n */\r\n function gotoBucketCalendar() {\r\n SettingsMain.setEditingPage(null);\r\n $location.path('/bucket');\r\n }\r\n /**\r\n * Navigate to FAQs View\r\n * @memberof groundFooter \r\n */\r\n function gotoFAQs() {\r\n SettingsMain.setEditingPage(null);\r\n $location.path('/faqs');\r\n }\r\n\r\n /**\r\n * Navigate to Messages View\r\n * @memberof groundFooter \r\n */\r\n function gotoMessageLibrary() {\r\n $location.path('/messages');\r\n }\r\n\r\n scope.gotoMessageLibrary = gotoMessageLibrary;\r\n scope.gotoFAQs = gotoFAQs;\r\n scope.gotoBucketCalendar = gotoBucketCalendar;\r\n scope.gotoCalendar = gotoCalendar;\r\n scope.logout = logout;\r\n\r\n }\r\n }\r\n\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: true,\r\n templateUrl: \"views/Main/basic-footer.tpl.html\",\r\n scope: false,\r\n link: link\r\n }\r\n\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.directive('chart',chart);\r\n \r\nfunction chart() {\r\n\tvar baseWidth = 600;\r\n\tvar baseHeight = 400;\r\n\r\n\treturn {\r\n\t\trestrict: 'E',\r\n\t\ttemplate: '',\r\n\t\tscope: {\r\n\t\t\tchartObject: \"=value\"\r\n\t\t},\r\n\t\tlink: function(scope, element, attrs) {\r\n\t\t\tvar canvas = element.find('canvas')[0];\r\n\t\t\tvar context = canvas.getContext('2d');\r\n\t\t\tvar chart;\r\n\r\n\t\t\tvar options = {\r\n\t\t\t\ttype: attrs.type || \"Line\",\r\n\t\t\t\twidth: attrs.width || baseWidth,\r\n\t\t\t\theight: attrs.height || baseHeight\r\n\t\t\t};\r\n\t\t\tcanvas.width = options.width;\r\n\t\t\tcanvas.height = options.height;\r\n\t\t\tchart = new Chart(context);\r\n\r\n\t\t\tscope.$watch(function() {\r\n\t\t\t\treturn element.attr('type');\r\n\t\t\t}, function(value) {\r\n\t\t\t\tif (!value) return;\r\n\t\t\t\toptions.type = value;\r\n\t\t\t\tvar chartType = options.type;\r\n if(scope.chartObject){\r\n\t\t\t\t chart[chartType](scope.chartObject.data, scope.chartObject.options);\r\n }\r\n\t\t\t});\r\n\r\n\t\t\t//Update when charts data changes\r\n\t\t\tscope.$watch(function() {\r\n\t\t\t\treturn scope.chartObject;\r\n\t\t\t}, function(value) {\r\n\t\t\t\tif (!value) return;\r\n\t\t\t\tvar chartType = options.type;\r\n\t\t\t\tchart[chartType](scope.chartObject.data, scope.chartObject.options);\r\n\t\t\t\tif (scope.chartInstance) scope.chartInstance.destroy();\r\n\t\t\t\tscope.chartInstance = chart[chartType](scope.chartObject.data, scope.chartObject.options);\r\n\t\t\t}, true);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n \r\n \r\n })(); ","(function () {\r\n 'use strict';\r\n a3_pilot_reports.directive('crewMeals', crewMeals);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name crewMeals\r\n * @restrict E\r\n * @description\r\n * Implementation of crew meals\r\n *\r\n * Display the crew meals\r\n * @attr {String} dutyNo \r\n * @attr {String} dutyDay \r\n * @attr {String} flight-id\r\n * @example\r\n * Usage:\r\n * \r\n * \r\n * @ngInject\r\n */\r\n function crewMeals(CrewRouteFactory, CrewMealFactory, FlightFactory, $sce, $timeout) {\r\n /**\r\n * Initialize crewMeals\r\n * @memberof crewMeals\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attributes attributes of this element\r\n */\r\n function link(scope, element, attributes) {\r\n scope.togglePanel = togglePanel;\r\n scope.route = CrewRouteFactory.getCrewRouteFromStorage(scope.dutyNo, scope.dutyDay);\r\n scope.HasRegChanged = false;\r\n scope.noClicked = noClicked;\r\n scope.yesClicked = yesClicked;\r\n scope.submitRatingClicked = submitRatingClicked;\r\n scope.canceClicked = canceClicked;\r\n scope.clearFormData = clearFormData;\r\n //for flight page\r\n scope.isFlightPanel = scope.flightId !== \"\";\r\n scope.flightCrewMeals = null;\r\n //for route page\r\n scope.isRoutePanel = scope.flightId == null || scope.flightId === \"\";\r\n scope.routeCrewMeals = [];\r\n scope.showCrewMealsPanel = false;\r\n //Rating Form\r\n scope.ratingForm = { CateringMealId: '', FlightId: '', Rating: '', Comments: '', DidNotEatReasonId: '' };\r\n scope.submitRatingMessage = '';\r\n scope.showPanel = \"meals\";\r\n scope.DidNotEatReasons = [];\r\n scope.isOffline = !window.navigator.onLine;\r\n\r\n scope.popoverInfo = {\r\n title: $sce.trustAsHtml(' Attention'),\r\n contentHtml: $sce.trustAsHtml('
' +\r\n 'There is an aircraft change on your route. Please arrange to take your assigned meal with you.' +\r\n '
')\r\n };\r\n\r\n window.addEventListener('offline', function (e) { $timeout(scope.isOffline = !window.navigator.onLine); });\r\n window.addEventListener('online', function (e) { $timeout(scope.isOffline = !window.navigator.onLine); });\r\n\r\n //Get scope values\r\n if (scope.isFlightPanel && scope.route) {\r\n var crewMeals = scope.route.CrewMeals;\r\n for (var i = 0; i < crewMeals.length; i++) {\r\n if (crewMeals[i].FlightId == scope.flightId) {\r\n scope.flightCrewMeals = new FlightCrewMeal(crewMeals[i]);\r\n scope.showCrewMealsPanel = true;\r\n break;\r\n }\r\n }\r\n scope.HasRegChanged = hasRegChanged(scope.flightId);\r\n }\r\n if (scope.isRoutePanel && scope.route && scope.route.CrewMeals.length > 0) {\r\n var crewMeals = scope.route.CrewMeals;\r\n for (var i = 0; i < crewMeals.length; i++) {\r\n scope.routeCrewMeals.push(new FlightCrewMeal(crewMeals[i]));\r\n scope.showCrewMealsPanel = true;\r\n }\r\n scope.HasRegChanged = hasRegChanged(crewMeals[0].FlightId);\r\n }\r\n\r\n if (!scope.isOffline && scope.showCrewMealsPanel) {\r\n CrewMealFactory.getCrewMealsDidNotEatReasons()\r\n .then(res => scope.DidNotEatReasons = res);\r\n }\r\n\r\n //FlightCrewMeal Constructor\r\n function FlightCrewMeal(flight) {\r\n this.FlightDate = moment(flight.FlightDate).format(\"DD/MM\");\r\n this.FlightNo = flight.FlightNo;\r\n this.FlightDeparture = flight.FlightDeparture;\r\n this.CrewMeals = \"\";\r\n this.CrewMealsDescriptions = [];\r\n\r\n for (var i = 0; i < Object.values(flight.CrewMealsCateringIds).length; i++) {\r\n if (i != 0) {\r\n this.CrewMeals += \" & \";\r\n }\r\n var crewMealDetails = CrewMealFactory.getCrewMealFromStorage(Object.values(flight.CrewMealsCateringIds)[i]);\r\n var hasRating = CrewMealFactory.hasRating(Object.keys(flight.CrewMealsCateringIds)[i]);\r\n this.CrewMeals += crewMealDetails.Title;\r\n this.CrewMealsDescriptions.push({ CrewMealId: Object.keys(flight.CrewMealsCateringIds)[i], CateringMealId: crewMealDetails.CateringMealId, Title: crewMealDetails.Title, Description: crewMealDetails.Description, HasRating: hasRating });\r\n\r\n }\r\n }\r\n\r\n //Change Registration check\r\n function hasRegChanged(flightId) {\r\n var retVal = false;\r\n var flights = FlightFactory.getFlightsByFlightId(flightId);\r\n if (flights.length > 0) {\r\n var acTailNo = flights[0].AcTailNo;\r\n for (var i = 0; i < flights.length; i++) {\r\n if (flights[i].AcTailNo != acTailNo) {\r\n retVal = true;\r\n break;\r\n }\r\n }\r\n }\r\n return retVal;\r\n }\r\n\r\n /**\r\n * toggle Panel\r\n * @memberof crewMeals\r\n * @param {number} panelId\r\n */\r\n function togglePanel(panelId) {\r\n $('#' + panelId).toggle();\r\n }\r\n\r\n function noClicked(cateringMealId, crewMealId) {\r\n clearFormData(cateringMealId, crewMealId)\r\n scope.showPanel = \"didNotEatMeal\";\r\n }\r\n\r\n function yesClicked(cateringMealId, crewMealId) {\r\n clearFormData(cateringMealId, crewMealId);\r\n scope.showPanel = \"mealRating\";\r\n }\r\n\r\n //function checkConnection\r\n\r\n function clearFormData(cateringMealId, crewMealId) {\r\n scope.ratingForm.CateringMealId = cateringMealId;\r\n scope.ratingForm.FlightId = scope.flightId;\r\n scope.ratingForm.CrewMealId = crewMealId;\r\n scope.ratingForm.Rating = '';\r\n scope.ratingForm.DidNotEatReasonId = '';\r\n scope.ratingForm.Comments = '';\r\n scope.isOffline = !window.navigator.onLine\r\n }\r\n\r\n function canceClicked() {\r\n scope.showPanel = \"meals\";\r\n }\r\n\r\n function submitRatingClicked() {\r\n scope.showPanel = \"loading\";\r\n CrewMealFactory.sendCrewMealsRatingReport(this.ratingForm)\r\n .then(res => handleSubmitResponse(res));\r\n\r\n }\r\n\r\n function handleSubmitResponse(res) {\r\n if (res.success) {\r\n var index = scope.flightCrewMeals.CrewMealsDescriptions.findIndex((x => x.CateringMealId == scope.ratingForm.CateringMealId));\r\n scope.flightCrewMeals.CrewMealsDescriptions[index].HasRating = true;\r\n manageResponseMessage(\"success\", res.message)\r\n }\r\n else {\r\n manageResponseMessage(\"failure\", res.message)\r\n }\r\n }\r\n\r\n function manageResponseMessage(panelToShow, message) {\r\n scope.submitRatingMessage = message;\r\n scope.showPanel = panelToShow;\r\n $timeout(function () { scope.showPanel = \"meals\"; }, 3000);\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: true,\r\n templateUrl: 'views/directives/crewMeals.tpl.html',\r\n scope: {\r\n dutyNo: '@',\r\n dutyDay: '@',\r\n flightId: '@'\r\n },\r\n link: link\r\n }\r\n }\r\n\r\n})();","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('flightCrew',flightCrew);\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightCrew\r\n * @restrict E\r\n * @description\r\n * Initialize Flight Crew Information\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */ \r\nfunction flightCrew () {\r\n function link(scope, element, attrs){\r\n }\r\n\t\treturn {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: \"views/directives/flightCrew.tpl.html\",\r\n\t\t\tscope : {\r\n flight: '='\r\n },\r\n link: link\r\n\t\t}\r\n\t} \r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n\r\n a3_pilot_reports.directive('flightFooter', flightFooter);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of FlightFooter\r\n *\r\n * Initialize The flights Footer Template and its Navigation, Sync, Footer Functionality\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function flightFooter(FlightFactory, orderByFilter, $location, SettingsMain, PilotReportLocalEditFactory, ReportGuidFactory, UserFactory, apiUrl, $uibModal, MessageFactory, DataCleanerFactory, $route, MemoFactory, $sce, $timeout, $interval) {\r\n /**\r\n * Initialize flightFooter and events\r\n * @memberof flightFooter\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attrs attribute of this element\r\n */\r\n function link(scope, element, attrs) {\r\n if (scope.flight) {\r\n\r\n var flightId = scope.flight.FlightId;\r\n var state = scope.state;\r\n var report = scope.report;\r\n var flights = getPreviousAndNextFlights(flightId);\r\n var messagesCount = 0;\r\n var unreadMessagesCount = 0;\r\n var memosForCurrentFlight = 0;\r\n var user = UserFactory.getUser();\r\n var messages = [];\r\n var memos = [];\r\n var delay = 60000;\r\n\r\n /**\r\n * Get the latest Pax and Gate Informations\r\n * @memberof flightFooter \r\n */\r\n function SynchPaxAndGates() {\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgLightSync.html',\r\n controller: 'SyncPaxCtrl',\r\n size: 'md',\r\n backdrop: 'static',\r\n keyboard: false,\r\n resolve: {\r\n flightId: function () {\r\n return flightId;\r\n },\r\n }\r\n })\r\n\r\n modalInstance.result.then(function () {\r\n scope.lastSync = new Date().getTime();\r\n }, function () { });\r\n }\r\n\r\n /**\r\n * Find previous,next and current flight of the Route of the selected flight\r\n * @memberof flightFooter\r\n * @param {number} flightId input the Id of a Flight \r\n * @returns {Object} previous,next and current flight\r\n */\r\n function getPreviousAndNextFlights(flightId) {\r\n var nextFlight, previousFlight, currentFlight;\r\n // also load the flights created by the user\r\n var flights = FlightFactory.getFlightsByRoute(scope.flight.Route, scope.flight.DutyDate);\r\n flights = orderByFilter(flights, orderByDate, false);\r\n\r\n function orderByDate(item) {\r\n var date = new Date(item.ScheduledDeparture);\r\n return date;\r\n }\r\n\r\n for (var i = 0; i < flights.length; i++) {\r\n if (flights[i].FlightId == flightId) {\r\n if (i >= 1) {\r\n previousFlight = flights[i - 1];\r\n }\r\n if (i + 1 < flights.length) {\r\n nextFlight = flights[i + 1];\r\n }\r\n currentFlight = flights[i];\r\n }\r\n }\r\n //alert(flights.currentFlight.flightId + \" \" + flights.nextFlight.flightId+ \" \" + flights.previousFlight.flightId);\r\n return {\r\n nextFlight: nextFlight,\r\n previousFlight: previousFlight,\r\n currentFlight: currentFlight\r\n };\r\n }\r\n\r\n /**\r\n * It handles the pilot report when u want to navigate to another view\r\n * @memberof flightFooter\r\n * @param {String} state input the current state (view) \r\n * @param {number} flightId input the Id of a Flight \r\n * @param {Object} report input the pilot report \r\n */\r\n function handleIfReport(state, flightId, report) {\r\n if (state == 'report') {\r\n if (report == null) {\r\n report = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\r\n }\r\n var guid = report.ReportGuid;\r\n var status = report.Status;\r\n\r\n // delete the temp report\r\n PilotReportLocalEditFactory.deleteTempReport();\r\n\r\n //reuse guid if this was a new report\r\n if (status == 'pending')\r\n ReportGuidFactory.restoreGuid(report.ReportGuid);\r\n }\r\n }\r\n\r\n /**\r\n * Open the pilot Report for the selected Flight\r\n * @memberof flightFooter \r\n * @param {number} flightId input the Id of a Flight\r\n */\r\n function openReport(flightId) {\r\n var user = UserFactory.getUser();\r\n var token = '';\r\n if (user != null) {\r\n token = user.token;\r\n token = encodeURIComponent(token);\r\n }\r\n\r\n // load the flight\r\n var flight = FlightFactory.getFlightFromStorage(flightId);\r\n if (flight == null) {\r\n // if not found, also check the local flights\r\n var flight = FlightFactory.getLocalFlightFromStorage(flightId);\r\n if (flight == null)\r\n return;\r\n }\r\n\r\n // load the reports\r\n var serverReportForThisUser = flight.getServerPilotReportForUser(user.aimsId);\r\n var serverReportsByAnotherUser = flight.getServerPilotReportsByAnotherUser(user.aimsId);\r\n var localReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\r\n\r\n // no stored local report\r\n if (localReport == null) {\r\n // has server report from this user and from other users\r\n if ((serverReportForThisUser != null) && (serverReportsByAnotherUser.length > 0)) {\r\n // show selection dialog\r\n openReportDialog(flightId);\r\n }\r\n // has server report only from this user\r\n else if ((serverReportForThisUser != null) && (serverReportsByAnotherUser.length == 0)) {\r\n $location.path(\"reportsHistory/\" + serverReportForThisUser.ReportId + \"/\" + flightId+\"/Pilot\");\r\n }\r\n // has server report only from other users\r\n else if ((serverReportForThisUser == null) && (serverReportsByAnotherUser.length > 0)) {\r\n // show selection dialog\r\n openReportDialog(flightId);\r\n }\r\n // no server reports, create a new local report directly\r\n else {\r\n $location.path(\"report/new:\" + -1 + \"/\" + flightId);\r\n }\r\n }\r\n // has stored local report\r\n else {\r\n // special case: has server report from this user, and not from\r\n // other users\r\n if ((serverReportForThisUser != null) && (serverReportsByAnotherUser.length == 0)) {\r\n // open the local report for editing\r\n $location.path(\"report/\" + localReport.ReportGuid);\r\n }\r\n // general case: has server report from this user or from other\r\n // users\r\n else if ((serverReportForThisUser != null) || (serverReportsByAnotherUser.length > 0)) {\r\n // show selection dialog\r\n openReportDialog(flightId);\r\n }\r\n // no server reports, open the local report directly\r\n else {\r\n // open the existing report for editing\r\n $location.path(\"report/\" + localReport.ReportGuid);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Open a modal to choose an action when there is already a pilot report from another user\r\n * @memberof flightFooter \r\n * @param {number} flightId input the Id of a Flight\r\n */\r\n function openReportDialog(flightId) {\r\n var modalInstance = $uibModal.open({\r\n templateUrl: './views/Dialogs/dlgOpenReport.html',\r\n controller: 'OpenReportDialogCtrl',\r\n size: 'md',\r\n resolve: {\r\n flightId: function () {\r\n return flightId;\r\n }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function () { }, function () { });\r\n }\r\n\r\n /**\r\n * Open a modal from which u can Logout from the application\r\n * @memberof flightFooter \r\n */\r\n function logout() {\r\n var isSecure = UserFactory.isSecure()\r\n bootbox.dialog({\r\n message: (isSecure ?\r\n \"Due to the fact that you are working over a public computer, all stored data will be deleted on logout!

\" :\r\n \"You will be able to login again into the same account, even if there is no internet access.

\") +\r\n \"Please confirm that you wish to log out.\",\r\n title: \"User Logout\",\r\n buttons: {\r\n cancel: {\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function () { }\r\n },\r\n logout: {\r\n label: \"Logout\",\r\n className: \"btn-warning\",\r\n callback: function () {\r\n UserFactory.clearActiveUser();\r\n if (isSecure) DataCleanerFactory.deleteAllData();\r\n\r\n location.reload(true);\r\n // need to reload, in order for the\r\n // browser to check the cache.manifest\r\n // and discover any changes\r\n }\r\n }\r\n }\r\n });\r\n }\r\n /**\r\n * Redirects to Reset Device View\r\n * @memberof flightFooter \r\n */\r\n function resetDevice() {\r\n $location.path(\"/reset\");\r\n }\r\n /**\r\n * Open a modal from which you can delete all available reports\r\n * @memberof flightFooter \r\n * @method\r\n */\r\n function deleteAllReports() {\r\n bootbox.dialog({\r\n message: \"Use this process to clear your device from all locally stored Pilot Reports, in order to save up space, when available storage space is not sufficient for the application to function properly.

\" +\r\n \"

ATTENTION

\" +\r\n \"This action will delete all Pilot Reports from your device, including draft and completed ones not sent to the server.\",\r\n title: \"Application Logs Reset\",\r\n buttons: {\r\n cancel: {\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function () { }\r\n },\r\n danger: {\r\n label: \"Delete All Pilot Reports\",\r\n className: \"btn-danger\",\r\n callback: function () {\r\n DataCleanerFactory.deleteAllReports();\r\n $route.reload();\r\n bootbox.alert(\"All Pilot Reports have been successfully deleted.\", function () { });\r\n }\r\n }\r\n }\r\n });\r\n }\r\n /**\r\n * Navigate to Calendar View\r\n * @memberof flightFooter \r\n */\r\n function gotoCalendar() {\r\n handleIfReport(state, flightId, report);\r\n\r\n SettingsMain.setEditingPage(null);\r\n // go to dashboard\r\n $location.path(\"/\");\r\n }\r\n /**\r\n * Navigate to Messages View\r\n * @memberof flightFooter \r\n */\r\n function gotoMessages() {\r\n handleIfReport(state, flightId, report);\r\n $location.path('/messages/' + flightId);\r\n }\r\n\r\n /**\r\n * Navigate to Selected Flight Information View\r\n * @param {number} flightId input the Id of a Flight\r\n * @memberof flightFooter \r\n */\r\n function gotoFlight(flightId) {\r\n handleIfReport(state, flightId, report);\r\n $location.path('/flightinfo/' + flightId);\r\n }\r\n /**\r\n * Navigate to Messages View\r\n * @memberof flightFooter \r\n */\r\n function gotoMessageLibrary() {\r\n handleIfReport(state, flightId, report);\r\n $location.path('/messages');\r\n }\r\n /**\r\n * Navigate to the Current Flight's Information View\r\n * @memberof flightFooter \r\n */\r\n function gotoFlightInfo() {\r\n gotoFlight(flightId);\r\n }\r\n /**\r\n * Open current's Flight Pilot Report\r\n * @memberof flightFooter \r\n */\r\n function openPilotReport() {\r\n openReport(flightId);\r\n }\r\n\r\n /**\r\n * Navigate to Memos Library\r\n * @memberof flightFooter \r\n */\r\n function gotoMemosLibrary() {\r\n handleIfReport(state, flightId, report);\r\n $location.path('/memos');\r\n }\r\n function goToSafetyReport(flightId) {\r\n $location.path('/safetyreport/flightcrewreport/' + flightId);\r\n }\r\n\r\n function goToFatigueReport(flightId) {\r\n $location.path('/safetyreport/fatiguereport/' + flightId);\r\n }\r\n\r\n if (state != \"memos\" && flights && flights.currentFlight) {\r\n MemoFactory.getMemosForFlight(flightId, function (results) {\r\n memos = results;\r\n scope.memosForCurrentFlight = memos.length;\r\n });\r\n }\r\n\r\n if (state != \"messages\" && flights && flights.currentFlight) {\r\n messages = MessageFactory.getMessagesFromIds(flights.currentFlight.messages);\r\n messagesCount = messages.length;\r\n for (var i = 0; i < messages.length; i++) {\r\n if (messages[i].ReadDt == null) {\r\n unreadMessagesCount++\r\n }\r\n }\r\n }\r\n\r\n if (state == 'pax' || state == 'flight' && scope.paxInfo) {\r\n var now = new Date().getTime();\r\n var departure = new Date(scope.flight.ScheduledDeparture).getTime();\r\n\r\n if (departure < now) {\r\n var openSyncPopover = $interval(showSyncPopover, delay);\r\n }\r\n }\r\n\r\n /**\r\n * Show Popover that advices User to sync so he can get the latest Pax and Gate Informations\r\n * @memberof flightFooter \r\n */\r\n function showSyncPopover() {\r\n var firstSyncWarning = departure - 4500000; //75 mintes before takeoff\r\n var secondSyncWarning = departure - 600000; //10 minutes before takeoff\r\n var now = new Date().getTime();\r\n var lastSync = scope.lastSync;\r\n\r\n if ((now > firstSyncWarning && now < secondSyncWarning && (!lastSync || lastSync < firstSyncWarning)) || (now > secondSyncWarning && now < departure && (!lastSync || lastSync < secondSyncWarning))) {\r\n scope.enableSyncPopover = true;\r\n }\r\n }\r\n\r\n function returnTimeDiff() {\r\n //time difference in minutes from: now and pax info list date\r\n scope.paxTimeDiffInMins = Math.round((new Date().getTime() - new Date(scope.paxInfo.LastRun).getTime()) / 60000);\r\n }\r\n\r\n if (state == 'pax' || state == 'flight') {\r\n if (scope.paxInfo && (new Date(scope.flight.ScheduledDeparture).getTime() > new Date().getTime())) {\r\n returnTimeDiff();\r\n var showTimeDiff = $interval(returnTimeDiff, delay);\r\n }\r\n }\r\n\r\n /**\r\n * Navigate to Submit ticket view\r\n * @memberof filghtFooter \r\n */\r\n function gotoTicket() {\r\n // go to Submit ticket view\r\n $location.path(\"/ticket\");\r\n }\r\n\r\n /**\r\n * Navigate to the Current Flight's Pax Information View\r\n * @memberof flightFooter \r\n */\r\n function gotoPaxInfo() {\r\n SettingsMain.setEditingPage(null);\r\n handleIfReport(state, flightId, report);\r\n $location.path('/pax/' + flightId);\r\n }\r\n\r\n\r\n scope.gotoFlight = gotoFlight;\r\n scope.previousFlight = flights.previousFlight;\r\n scope.nextFlight = flights.nextFlight;\r\n scope.gotoCalendar = gotoCalendar;\r\n scope.gotoFlightInfo = gotoFlightInfo;\r\n scope.openPilotReport = openPilotReport;\r\n scope.gotoMessages = gotoMessages;\r\n scope.messagesCount = messagesCount;\r\n scope.unreadMessagesCount = unreadMessagesCount;\r\n scope.logout = logout;\r\n scope.resetDevice = resetDevice;\r\n scope.deleteAllReports = deleteAllReports;\r\n scope.gotoMessageLibrary = gotoMessageLibrary;\r\n scope.gotoMemosLibrary = gotoMemosLibrary;\r\n scope.gotoPaxInfo = gotoPaxInfo;\r\n\r\n scope.showMobileMenu = false;\r\n scope.userPosition = user.position;\r\n scope.SynchPaxAndGates = SynchPaxAndGates;\r\n scope.gotoTicket = gotoTicket;\r\n scope.goToSafetyReport = goToSafetyReport;\r\n scope.goToFatigueReport = goToFatigueReport;\r\n\r\n scope.syncWarning = $sce.trustAsHtml('
You are strongly advised to sync your device.
');\r\n scope.enableSyncPopover = false;\r\n scope.lastSync = null;\r\n\r\n element.on('$destroy', function () {\r\n $interval.cancel(openSyncPopover);\r\n $interval.cancel(showTimeDiff);\r\n });\r\n }\r\n }\r\n return {\r\n restrict: 'E',\r\n terminal: true,\r\n templateUrl: \"views/Flight/footer.tpl.html\",\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.directive('flightHeader',flightHeader);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightHeader\r\n * @restrict E\r\n * @description\r\n * Implementation of flightHeader\r\n * Initialize the template of the header while you are in the Flight Level\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */ \r\nfunction flightHeader() {\r\n\t\treturn {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: \"views/Flight/header.tpl.html\",\r\n\t\t\tscope: false\r\n\t\t}\r\n\t} \r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('groundCrew',groundCrew);\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundCrew\r\n * @restrict E\r\n * @description\r\n * Initialize Trainer and Trainee Info\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */ \r\nfunction groundCrew () {\r\n function link(scope, element, attrs){\r\n scope.groundDuty = scope.duty;\r\n scope.toggleCrewList = toggleCrewList\r\n\r\n scope.groundDuty.Trainees.forEach(function(relatedTrainees){\r\n relatedTrainees.isCollapsed = false;\r\n relatedTrainees.dynamicSize = 10;\r\n });\r\n\r\n /**\r\n * @memberof GroundDutyCtrl\r\n * @name toggleCrewList\r\n * @description \r\n * Οnly show the first 10 trainees - if more then toggle\r\n */\r\n function toggleCrewList(relatedTrainees){\r\n relatedTrainees.isCollapsed = !relatedTrainees.isCollapsed;\r\n\r\n if(relatedTrainees.isCollapsed) relatedTrainees.dynamicSize = relatedTrainees.CrewMembers.length;\r\n else relatedTrainees.dynamicSize = 10;\r\n }\r\n\r\n }\r\n\t\treturn {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: \"views/directives/groundCrew.tpl.html\",\r\n\t\t\tscope : {\r\n duty: '='\r\n },\r\n link: link\r\n\t\t}\r\n\t} \r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('groundHeader', groundHeader);\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundHeader\r\n * @restrict E\r\n * @description\r\n * Implementation of groundHeader (appears in groundDuty-info view)\r\n * Initialize the template of the header while you are in the Ground Duty Level\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */ \r\nfunction groundHeader () {\r\n\t\treturn {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: \"views/GroundDuty/header.tpl.html\",\r\n\t\t\tscope: false\r\n\t\t}\r\n\t} \r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n a3_pilot_reports.directive('groundServices', groundServices);\r\n\r\n/**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundServices\r\n * @restrict E\r\n * @description\r\n * Implementation of ground services \r\n *\r\n * Display the ground services\r\n * @attr {String} arrival The flight arrival station.\r\n * @attr {String} departure The flight departure station.\r\n * @attr {String} flight-id The flight id.\r\n * @example\r\n * Usage:\r\n * \r\n * \r\n * @ngInject\r\n */ \r\n function groundServices(GroundServicesFactory, PilotReportLocalEditFactory, PilotReportLocalEditCreatorFactory, FlightFactory, $sce) {\r\n \r\n /**\r\n * Initialize groundServices\r\n * @memberof groundServices\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attributes attributes of this element\r\n */\r\n function link(scope, element, attributes){\r\n scope.togglePanel = togglePanel;\r\n scope.flight = FlightFactory.getFlightFromTotalFlights(scope.flightId);\r\n scope.isInFinalState = isInFinalState;\r\n scope.saveNewUsedState = saveNewUsedState;\r\n scope.DepartureGroundServices = [];\r\n scope.ArrivalGroundServices = [];\r\n scope.popoverInfo = {\r\n title: $sce.trustAsHtml(' Info'),\r\n contentHtml: $sce.trustAsHtml('
Contracted Services' + \r\n '
Non Contracted Services' +\r\n '
')\r\n };\r\n\r\n var report = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(scope.flightId);\r\n if (report == null){\r\n if (scope.departure){\r\n scope.DepartureGroundServices = GroundServicesFactory.getGroundServicesByStation(scope.departure);\r\n }\r\n if (scope.arrival){\r\n scope.ArrivalGroundServices = GroundServicesFactory.getGroundServicesByStation(scope.arrival);\r\n }\r\n }\r\n else {\r\n report = PilotReportLocalEditFactory.checkForNewGroundServices(report);\r\n if (scope.departure){\r\n scope.DepartureGroundServices = report.DepartureGroundServices;\r\n }\r\n if (scope.arrival){\r\n scope.ArrivalGroundServices = report.ArrivalGroundServices;\r\n }\r\n }\r\n\r\n\r\n /**\r\n * Check if the report is in a final state so that we cant edit any more\r\n * @memberof groundServices\r\n * @returns {boolean} true if final, false otherwise\r\n */\r\n function isInFinalState(){\r\n var isInFinalState = ((scope.flight.LineStatus === 'na') ||\r\n (scope.flight.LineStatus === 'stored') ||\r\n (scope.flight.LineStatus === 'storedotheruser') ||\r\n (scope.flight.LineStatus === 'stored+otheruser') ||\r\n (scope.flight.LineStatus === 'synched') ||\r\n (scope.flight.LineStatus === 'synchedotheruser'));\r\n return isInFinalState;\r\n }\r\n\r\n /**\r\n * When a ground service usage is toggled on or off,\r\n * create the report if it doesnt exist\r\n * or just save the changes\r\n * @memberof groundServices\r\n */\r\n function saveNewUsedState() {\r\n //if report is pending, it doesnt exist yet. create it\r\n if (scope.flight.LineStatus === 'pending' || scope.flight.LineStatus === 'pendingoverdue'){\r\n report = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight(scope.flightId); \r\n if (scope.departure){\r\n report.DepartureGroundServices = scope.DepartureGroundServices;\r\n }else{\r\n report.DepartureGroundServices=[];\r\n }\r\n if (scope.arrival){\r\n report.ArrivalGroundServices = scope.ArrivalGroundServices;\r\n }else{\r\n report.ArrivalGroundServices = [];\r\n }\r\n report.Status = 'draft';\r\n report.saveReport();\r\n FlightFactory.updateFlightFromReport(report);\r\n }\r\n\r\n PilotReportLocalEditFactory.setPilotReportToStorage(report);\r\n }\r\n\r\n //TODO : find a more angular way (EPAP)\r\n /**\r\n * toggle Panel\r\n * @memberof groundServices\r\n * @param {number} panelId\r\n */\r\n function togglePanel(panelId) {\r\n $('#' + panelId).toggle();\r\n }\r\n }\r\n \r\n return {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: 'views/directives/groundServices.tpl.html',\r\n\t\t\tscope: {\r\n arrival: '@',\r\n departure: '@',\r\n flightId: '@'\r\n },\r\n link: link\r\n }\r\n}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\n \r\n a3_pilot_reports.directive('mainFooter',mainFooter);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name mainFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of mainFooter\r\n * Initialize The main Footer Template and its Navigation, Sync, Footer Functionality\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */ \r\nfunction mainFooter($location ,SettingsMain, UserFactory, $uibModal, MessageFactory, DataCleanerFactory, $route, MemoFactory, $sce, $timeout,LeaveRequestFactory){\r\n /**\r\n * Initialize mainFooter and events\r\n * @memberof mainFooter\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attrs attribute of this element\r\n */\r\n\t\tfunction link(scope, element, attrs) {\r\n\r\n\t\t\tvar messagesCount = 0;\r\n\t\t\tvar unreadMessagesCount = 0;\r\n\t\t\tvar memosCount = 0;\r\n var messages = [];\r\n var memos = [];\r\n \r\n /**\r\n * Open a modal from which u can Logout from the application\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction logout() {\r\n\t\t\t\tvar isSecure = UserFactory.isSecure()\r\n\t\t\t\tbootbox.dialog({\r\n\t\t\t\t\tmessage: (isSecure ?\r\n\t\t\t\t\t\t\t\"Due to the fact that you are working over a public computer, all stored data will be deleted on logout!

\" :\r\n\t\t\t\t\t\t\t\"You will be able to login again into the same account, even if there is no internet access.

\") +\r\n\t\t\t\t\t\t\"Please confirm that you wish to log out.\",\r\n\t\t\t\t\ttitle: \"User Logout\",\r\n\t\t\t\t\tbuttons: {\r\n\t\t\t\t\t\tcancel: {\r\n\t\t\t\t\t\t\tlabel: \"Cancel\",\r\n\t\t\t\t\t\t\tclassName: \"btn-default\",\r\n\t\t\t\t\t\t\tcallback: function() {}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tlogout: {\r\n\t\t\t\t\t\t\tlabel: \"Logout\",\r\n\t\t\t\t\t\t\tclassName: \"btn-warning\",\r\n\t\t\t\t\t\t\tcallback: function() {\r\n\t\t\t\t\t\t\t\tUserFactory.clearActiveUser();\r\n\t\t\t\t\t\t\t\tif (isSecure) DataCleanerFactory.deleteAllData();\r\n\r\n\t\t\t\t\t\t\t\tlocation.reload(true);\r\n\t\t\t\t\t\t\t\t// need to reload, in order for the\r\n\t\t\t\t\t\t\t\t// browser to check the cache.manifest\r\n\t\t\t\t\t\t\t\t// and discover any changes\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n \r\n /**\r\n * Redirects to Reset Device View\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction resetDevice() {\r\n\t\t\t\t$location.path(\"/reset\");\r\n\t\t\t}\r\n /**\r\n * Open a modal from which you can delete all available reports\r\n * @memberof mainFooter \r\n * @method\r\n */\r\n\t\t\tfunction deleteAllReports() {\r\n\t\t\t\tbootbox.dialog({\r\n\t\t\t\t\tmessage: \"Use this process to clear your device from all locally stored Pilot Reports, in order to save up space, when available storage space is not sufficient for the application to function properly.

\" +\r\n\t\t\t\t\t\t\"

ATTENTION

\" +\r\n\t\t\t\t\t\t\"This action will delete all Pilot Reports from your device, including draft and completed ones not sent to the server.\",\r\n\t\t\t\t\ttitle: \"Application Logs Reset\",\r\n\t\t\t\t\tbuttons: {\r\n\t\t\t\t\t\tcancel: {\r\n\t\t\t\t\t\t\tlabel: \"Cancel\",\r\n\t\t\t\t\t\t\tclassName: \"btn-default\",\r\n\t\t\t\t\t\t\tcallback: function() {}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tdanger: {\r\n\t\t\t\t\t\t\tlabel: \"Delete All Pilot Reports\",\r\n\t\t\t\t\t\t\tclassName: \"btn-danger\",\r\n\t\t\t\t\t\t\tcallback: function() {\r\n\t\t\t\t\t\t\t\tDataCleanerFactory.deleteAllReports();\r\n\t\t\t\t\t\t\t\t$route.reload();\r\n\t\t\t\t\t\t\t\tbootbox.alert(\"All Pilot Reports have been successfully deleted.\", function() {});\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n \r\n /**\r\n * Navigate to Calendar View\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction gotoCalendar(){\r\n\t\t\t\tSettingsMain.setEditingPage(null);\r\n\t\t\t\t// go to dashboard\r\n\t\t\t\t$location.path(\"/\");\r\n\t\t\t}\r\n\t\t\t/**\r\n\t\t\t * Navigate to Bucket Calendar View\r\n\t\t\t * @memberof flightFooter \r\n\t\t\t */\r\n\t\t\tfunction gotoBucketCalendar() {\r\n\t\t\t\tSettingsMain.setEditingPage(null);\r\n\t\t\t\t$location.path('/bucket');\r\n\t\t\t}\r\n /**\r\n * Navigate to Messages View\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction gotoMessageLibrary(){\r\n\t\t\t\t$location.path('/messages');\r\n\t\t\t}\r\n \r\n /**\r\n * Navigate to Memos Library\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction gotoMemos() {\r\n\t\t\t\t$location.path('/memos');\r\n\t\t\t}\r\n \r\n /**\r\n * Navigate to leave request View\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction gotoLeaveRequests(){\r\n\t\t\t\t$location.path('/leaverequest');\r\n\t\t\t}\r\n\r\n \r\n /**\r\n * Navigate to Submit ticket view\r\n * @memberof mainFooter \r\n */\r\n\t\t\tfunction gotoTicket(){\r\n\t\t\t\t// go to Submit ticket view\r\n\t\t\t\t$location.path(\"/ticket\");\r\n\t\t\t}\r\n \r\n\t\t\tmessages = MessageFactory.getMessagesFromStorage();\r\n\t\t\tmessagesCount = messages.length;\r\n\t\t\tfor (var i = 0; i < messages.length; i++) {\r\n\t\t\t\tif (messages[i].ReadDt == null) {\r\n\t\t\t\t\tunreadMessagesCount++\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tMemoFactory.getMemosFromStorage(function(results){\r\n\t\t\t\tvar memosCount = 0;\r\n \r\n //remove memos that belong to \"Training Surveys\" category\r\n for(var i = 0; i < results.length; i++){\r\n if(results[i].Category != \"Training Surveys\"){\r\n memosCount++;\r\n }\r\n }\r\n scope.memosCount = memosCount;\r\n\r\n\t\t\t});\r\n\r\n\t\t\tscope.messagesCount = messagesCount;\r\n\t\t\tscope.unreadMessagesCount = unreadMessagesCount;\r\n\t\t\tscope.logout = logout;\r\n\t\t\tscope.resetDevice = resetDevice;\r\n\t\t\tscope.deleteAllReports = deleteAllReports;\r\n\t\t\tscope.gotoMessageLibrary = gotoMessageLibrary;\r\n\t\t\tscope.gotoMemos = gotoMemos;\r\n\t\t\tscope.memosCount = memosCount;\r\n\t\t\tscope.gotoCalendar = gotoCalendar;\r\n\t\t\tscope.gotoBucketCalendar = gotoBucketCalendar;\r\n scope.gotoTicket = gotoTicket;\r\n scope.leaveRequestInformation = LeaveRequestFactory.getLeaveRequestInformation();\r\n scope.gotoLeaveRequests = gotoLeaveRequests;\r\n\r\n\t\t}\r\n\t\t\t\r\n\t\treturn {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: \"views/Main/footer.tpl.html\",\r\n\t\t\tscope: false,\r\n\t\t\tlink : link\r\n\t\t}\r\n\t}\r\n \r\n })(); ","(function () {\r\n\r\n a3_pilot_reports.directive('memosByCategory', memosByCategory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name memosByCategory\r\n * @restrict E\r\n * @description\r\n * Implementation of memosByCategory\r\n * Initialize the panels with memos group by category.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function memosByCategory(MemoFactory, MemoImagesFactory, $uibModal, DataCleanerFactory, GroundDutyFactory, FlightFactory) {\r\n function link($scope, attrs) {\r\n $scope.togglePanel = togglePanel;\r\n var Id = $scope.id;\r\n \r\n\r\n /**\r\n * toggle Panel\r\n * @memberof memosByCategory\r\n * @param {number} panelId\r\n */\r\n function togglePanel(panelId) {\r\n $('#' + panelId).toggle();\r\n }\r\n\r\n //Initialize Memos\r\n if($scope.type == \"duty\" || $scope.type == \"d\"){\r\n MemoFactory.getMemosForCrewRoute(Id, $scope.day, function (results) {\r\n $scope.memos = filterMemos(results);\r\n });\r\n }\r\n else if($scope.type == \"ground\" || $scope.type == \"g\"){\r\n MemoFactory.getMemosForGroundDuty(Id, function (results) {\r\n $scope.memos = filterMemos(results);\r\n });\r\n }\r\n //(attrs.type == \"flight\" || attrs.type == \"f\") default Flight type\r\n else{\r\n MemoFactory.getMemosForFlight(Id, function (results) {\r\n $scope.memos = filterMemos(results);\r\n });\r\n }\r\n \r\n /**\r\n * filter memos\r\n * @memberof memosByCategory\r\n * @param {object} data\r\n */\r\n function filterMemos(data){\r\n //normalize memos\r\n var distinctMemos = normalizeMemos(data);\r\n\r\n if (distinctMemos.length != data.length) {\r\n MemoFactory.getMemosFromStorage(function (allMemos) {\r\n var distinctMemosAll = normalizeMemos(allMemos);\r\n MemoImagesFactory.getMemoImagesFromStorage(function (allMemoImages) {\r\n var distinctMemoImagesAll = normalizeMemoImages(allMemoImages);\r\n recreateIndexedDB(distinctMemosAll, allMemoImages);\r\n });\r\n });\r\n }\r\n var memosByCategory = [];\r\n for (var i = 0; i < distinctMemos.length; i++) {\r\n var memo = distinctMemos[i];\r\n if (!memosByCategory.filter(function (e) { return e.Category == memo.Category }).length > 0 && memo.Category != \"None\") {\r\n memosByCategory.push({ Category: memo.Category, memoList: [memo] });\r\n }\r\n else if (memosByCategory.filter(function (e) { return e.Category == memo.Category }).length > 0 && memo.Category != \"None\") {\r\n memosByCategory.filter(function (object) {\r\n\r\n if (object.Category == memo.Category) {\r\n return object;\r\n };\r\n })[0].memoList.push(memo);\r\n }\r\n }\r\n return memosByCategory;\r\n }\r\n function recreateIndexedDB(distinctMemosAll, distinctMemosImagesAll) {\r\n //delete indexdb\r\n var q = DataCleanerFactory.deleteIndexedDB();\r\n q.then(function () {\r\n MemoFactory.setMemosToStorage(distinctMemosAll);\r\n MemoImagesFactory.setMemoImagesToStorage(distinctMemosImagesAll);\r\n\r\n //save normalize data to indexedDB\r\n LogService.debug(\"Recreated IndexedDB\");\r\n });\r\n q.catch(function (ex) {\r\n console.log(ex);\r\n });\r\n\r\n }\r\n function normalizeMemos(data) {\r\n var distinctData = [];\r\n if (data && data.length > 1) {\r\n var sortData = data.dynamicSort(\"Id\");\r\n for (var i = 0; i < sortData.length - 1; i++) {\r\n if (sortData[i + 1].Id == sortData[i].Id) {\r\n //swap rows in list - check lastUpdated property, latest at the end\r\n if (sortData[i].LastUpdated && sortData[i + 1].LastUpdated) {\r\n var memoDateA = new Date(sortData[i].LastUpdated);\r\n var memoDateB = new Date(sortData[i + 1].LastUpdated);\r\n if (memoDateA.getTime() > memoDateB.getTime()) {\r\n var temp = sortData[i + 1];\r\n sortData[i + 1] = sortData[i];\r\n sortData[i] = temp;\r\n }\r\n }\r\n } else {\r\n distinctData.push(sortData[i]);\r\n }\r\n }\r\n distinctData.push(sortData[sortData.length - 1]);\r\n } else {\r\n distinctData = data;\r\n }\r\n\r\n return distinctData\r\n }\r\n function normalizeMemoImages(data) {\r\n var distinctData = [];\r\n if (data && data.length > 1) {\r\n var sortData = data.dynamicSort(\"imageId\");\r\n for (var i = 0; i < sortData.length - 1; i++) {\r\n if (!(sortData[i + 1].imageId == sortData[i].imageId)) {\r\n distinctData.push(sortData[i]);\r\n }\r\n }\r\n distinctData.push(sortData[sortData.length - 1]);\r\n } else {\r\n distinctData = data;\r\n }\r\n\r\n return distinctData\r\n }\r\n\r\n $scope.openMemo = openMemo;\r\n\r\n\r\n /**\r\n * Open modal to see information for the selected Memo\r\n * @memberof memosByCategory\r\n * @param {object} memo A memo object\r\n */\r\n function openMemo(memo) {\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Memos/dlgMemo.html',\r\n controller: 'MemoModalCtrl',\r\n size: 'lg',\r\n keyboard: false,\r\n resolve: {\r\n memo: function () {\r\n return memo;\r\n }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function () {\r\n if (memo.ReadDt == null) {\r\n memo.ReadDt = new Date();\r\n MemoFactory.saveOneMemoToStorage(memo);\r\n\r\n if($scope.type == \"ground\"){\r\n MemoFactory.markGroundDutiesUnread();\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/directives/memosByCategoryPanel.tpl.html\",\r\n scope: {\r\n type: '@',\r\n id: '=',\r\n day: '=' \r\n },\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function () {\r\n\r\n a3_pilot_reports.directive('securitySearch', securitySearch);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name securitySearch\r\n * @restrict E\r\n * @description\r\n * Implementation of securitySearch\r\n * Initialize the panel with previous flight info.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function securitySearch(AircaftPositionsFactory, FlightFactory) {\r\n function link($scope) {\r\n var showSecurityMsg = false;\r\n var securitySearchRequired = null;\r\n var DepartureUK = null;\r\n var DepartureEU = null;\r\n var DepartureCDG = null;\r\n var PreviousEU = null;\r\n\r\n var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId($scope.id);\r\n var flightInfo = FlightFactory.getFlightFromStorage($scope.id);\r\n\r\n if(flightInfo){\r\n DepartureUK = flightInfo.DepartureCountry == \"UNITED KINGDOM\";\r\n DepartureEU = flightInfo.DepartureEU;\r\n DepartureCDG = flightInfo.Departure == \"CDG\";\r\n\r\n // RULE 1: Current Departure Airport is UK\r\n // RULE 2: Current Departure Airport is Non EU\r\n // RULE 3: Current Departure Airport is CDG Airport\r\n if(DepartureUK || !DepartureEU || DepartureCDG){\r\n securitySearchRequired = true;\r\n }\r\n else{\r\n securitySearchRequired = false;\r\n }\r\n\r\n }\r\n \r\n if(aircaftPositions){\r\n // RULE 4: Previous Origin Airport is Non EU\r\n PreviousEU = aircaftPositions.PreviousEU; \r\n if(!PreviousEU){\r\n securitySearchRequired = true;\r\n }\r\n else{\r\n securitySearchRequired = false;\r\n }\r\n }\r\n \r\n if(securitySearchRequired != null){\r\n showSecurityMsg = true;\r\n }\r\n\r\n $scope.showSecurityMsg = showSecurityMsg;\r\n $scope.securitySearchRequired = securitySearchRequired;\r\n $scope.aircaftPositions = aircaftPositions;\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/directives/securitySearch.tpl.html\",\r\n scope: {\r\n id: '='\r\n },\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('showerrormessage', showerrormessage);\r\n\r\n /**\r\n * @ngdoc directive\r\n * @name showerrormessage\r\n * @restrict EA\r\n * @description\r\n * Implementation of show error message\r\n * @attr {String} message: the error message.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */ \r\n function showerrormessage() {\r\n\r\n function link($scope, element, attrs) {\r\n $scope.errorMessage = attrs.message;\r\n $scope.hasMessage = attrs.message != null && attrs.message.length > 0;\r\n\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n template: '
{{errorMessage}}
',\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})(); ","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('updateConfirm',updateConfirm);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name updateConfirm\r\n * @restrict E\r\n * @description\r\n * Implementation of aircraft differences\r\n *\r\n * Display the confirm textto update service workers version\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\nfunction updateConfirm(SWUpdateService) {\r\n function link($scope, element, attributes){\r\n //if serviceWorker registered\r\n if ($scope.SWRegistration != null) {\r\n $scope.needUpdate = null;\r\n $scope.update = update;\r\n \r\n //get waiting service worker if exists\r\n $scope.needUpdate = $scope.SWRegistration.waiting;\r\n\r\n //if waiting service woker exists check how long its been waiting\r\n if ($scope.needUpdate != null){ \r\n SWUpdateService.checkVersionExpiration($scope.SWRegistration);\r\n }\r\n }\r\n\r\n function update() {\r\n SWUpdateService.update($scope.SWRegistration);\r\n }\r\n\r\n }\r\n return {\r\n\t\t\trestrict: 'E',\r\n\t\t\tterminal: true,\r\n\t\t\ttemplateUrl: 'views/directives/updateConfirm.tpl.html',\r\n\t\t\tscope: true,\r\n link: link\r\n\t\t}\r\n}\r\n})();","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.controller('AddFlightCtrl', AddFlightCtrl)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name AddFlightCtrl\r\n * @description \r\n * Add a new flight that is not in schedule\r\n * @ngInject\r\n */ \r\n function AddFlightCtrl($scope, UserFactory, FlightFactory, AircraftTypeFactory, $uibModalInstance, $route) {\r\n\r\n\t\t$scope.isSecure = UserFactory.isSecure();\r\n\r\n\t\t// cancel\r\n\t\t$scope.doCancel = doCancel;\r\n \r\n\r\n\t\t// add flight\r\n\t\t$scope.doAdd = doAdd;\r\n \r\n\r\n\r\n\t\t// setup datetime pickers\r\n\t\tvar now = new Date();\r\n\t\tvar minSelectableDate = new Date();\r\n\t\tvar maxSelectableDate = new Date();\r\n\t\tminSelectableDate.setDate(now.getDate() - 15);\r\n\t\tmaxSelectableDate.setDate(now.getDate() + 2);\r\n\t\t$scope.minSelectableDateStr = minSelectableDate.toString('dd-MM-yyyy');\r\n\t\t$scope.maxSelectableDateStr = maxSelectableDate.toString('dd-MM-yyyy');\r\n\t\t$scope.selectedDate = null;\r\n\t\t$scope.selectedTime = null;\r\n\r\n\t\t$scope.hstep = 1;\r\n\t\t$scope.mstep = 1;\r\n\t\t$scope.ismeridian = false;\r\n\r\n\t\t$scope.dateFormat = 'dd-MM-yyyy';\r\n\t\t$scope.hourFormat = \"HH:mm\"\r\n\r\n\t\t$scope.datepicker = {\r\n\t\t\topened: false\r\n\t\t};\r\n\r\n\r\n\t\t$scope.openDatepicker = openDatepicker;\r\n\r\n\r\n\t\t// get the values from ui and create a flight\r\n\t\t$scope.createFlightFromUIValues = createFlightFromUIValues; \r\n \r\n \r\n\r\n\t\t// setup aircraft types\r\n\t\tvar actypes = AircraftTypeFactory.getAircraftTypesFromStorage();\r\n\t\tif (!(actypes instanceof Array)) actypes = [];\r\n\t\tactypes.push({\r\n\t\t\tCode: 'other'\r\n\t\t});\r\n\t\t$scope.aircraftTypes = actypes;\r\n\r\n\r\n\t\t// function to process the form\r\n\t\t$scope.processForm = processForm;\r\n\t\t\r\n /**\r\n * Add the flight to schedule\r\n * @memberof AddFlightCtrl\r\n */\r\n function doAdd() {\r\n\t\t\t$scope.processForm();\r\n\t\t}\r\n \r\n /**\r\n * Close the modal\r\n * @memberof AddFlightCtrl\r\n */\r\n\t\tfunction doCancel() {\r\n\t\t\t$uibModalInstance.close('cancel');\r\n\t\t} \r\n \r\n /**\r\n * Open Datepicker\r\n * @memberof AddFlightCtrl\r\n */\r\n function openDatepicker() {\r\n\t\t\t$scope.datepicker.opened = true;\r\n\t\t};\r\n \r\n /**\r\n * Get the values from ui and create a flight \r\n * @memberof AddFlightCtrl\r\n */\r\n function createFlightFromUIValues() {\r\n\r\n\t\t\t// get moment dt from controls\r\n\t\t\tvar flightDate = $scope.formData.flightDateStr;\r\n\t\t\tvar flightSTD = $scope.formData.flightTimeStr;\r\n\t\t\t// convert them to dates\r\n\t\t\tflightDate = new Date(flightDate);\r\n\t\t\tflightSTD = new Date(flightSTD);\r\n\t\t\t// combine date and time\r\n\t\t\tflightDate.setHours(flightSTD.getHours(), flightSTD.getMinutes(), 0, 0);\r\n\t\t\t// flightDate = flightDate.fromUTC();\r\n\t\t\t// get other flight details\r\n\t\t\tvar flightNumber = $scope.formData.flightNumber;\r\n\t\t\tvar flightDeparture = $scope.formData.flightDeparture;\r\n\t\t\tvar flightDestination = $scope.formData.flightDestination;\r\n\t\t\tvar flightRegNo = $scope.formData.flightRegNo;\r\n\t\t\tvar flightAcType = null;\r\n\t\t\tif ($scope.formData.flightAcType != null)\r\n\t\t\t\tflightAcType = $scope.formData.flightAcType;\r\n\r\n\t\t\t// try to create a local flight\r\n\t\t\tvar newFlight = FlightFactory.createLocalFlight(flightDate, flightNumber, flightDeparture, flightDestination, flightRegNo, flightAcType);\r\n\r\n\t\t\treturn newFlight;\r\n\t\t}\r\n \r\n /**\r\n * Process and validate the form\r\n * @memberof AddFlightCtrl\r\n */\r\n function processForm() {\r\n // if all valid\r\n if ($scope.formFlight.$valid) {\r\n try {\r\n // try to create a local flight\r\n var newFlight = $scope.createFlightFromUIValues();\r\n\r\n // save the local flight\r\n if (newFlight != null) {\r\n FlightFactory.saveLocalFlight(newFlight);\r\n }\r\n\r\n if (newFlight == null) {\r\n bootbox.alert(\"

Error

Unable to create a flight record.\");\r\n } else {\r\n (function() {\r\n $uibModalInstance.close();\r\n $route.reload();\r\n })();\r\n }\r\n } catch (e) {\r\n bootbox.alert(\"

Error

Unable to create a flight record due to unexpected error:\\n\" + e.message);\r\n }\r\n } else {\r\n bootbox.alert(\"Please fill in all the required fields.\");\r\n }\r\n }\r\n \r\n\t\t// initialize form data\r\n\t\t$scope.formData = {};\r\n\r\n\t}\r\n \r\n })(); ","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.controller('CalendarCtrl', CalendarCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CalendarCtrl\r\n * @description \r\n * View your schedule (flights and ground duties)\r\n * @ngInject\r\n */\r\n\tfunction CalendarCtrl($scope, version, $location, MemoFactory, FlightFactory, UserFactory, PilotReportLocalEditFactory, CrewRouteFactory, \r\n\t\t\t\t\t\t\tMessageFactory, UpdateService, DataCleanerFactory, SyncLogFactory, $timeout, $uibModal, GroundDutyFactory, SettingsMain, \r\n\t\t\t\t\t\t\tdefaultCalendarDate, AutolandFactory, CrewHotelFactory, TrainingSessionFactory, FlightSessionFactory, ScheduleAcknowledgeFactory) {\r\n\t\t\t\t\t\t\t\t\r\n\t\t$scope.pendingOverdueReports = 0;\r\n\t\t$scope.draftReports = 0;\r\n\t\t$scope.completedReports = 0;\r\n\r\n\r\n\t\t$scope.isSecure = UserFactory.isSecure();\r\n\t\t$scope.state = 'calendar';\r\n\r\n\t\tif (version) {\r\n\t\t\t$scope.version = version.replace('appVersion_', '');\r\n\t\t} else {\r\n\t\t\t$scope.version = '';\r\n\t\t}\r\n\r\n\t\t//scope variables\r\n\t\tvar user = UserFactory.getUser();\r\n\t\t$scope.logged_user_info = user.aimsId + ' - ' + user.name;\r\n\t\t$scope.storageUsage = storageUsage;\r\n\r\n\t\t//SetupView\r\n\t\t$scope.setupView = setupView;\r\n\r\n\t\t//Pages\r\n\t\t$scope.addFlight = addFlight;\r\n\r\n\t\t$scope.searchPastGroundDuties = searchPastGroundDuties;\r\n\r\n\t\t//Modals\r\n\t\t$scope.openSynch = openSynch;\r\n\r\n\t\t$scope.hasUnsetTraining = false;\r\n\r\n\t\tvar groundSessions = [];\r\n var flightSessions = [];\r\n TrainingSessionFactory.getAll(function(savedGroundSessions){\r\n FlightSessionFactory.getAll(function(savedFlightSessions){\r\n groundSessions = savedGroundSessions;\r\n flightSessions = savedFlightSessions;\r\n\r\n $scope.setupView(false);\r\n });\r\n\t\t});\r\n\r\n\r\n /**\r\n * Setups Calendar View\r\n * @memberof CalendarCtrl\r\n * @param {boolean} isReload\r\n */\r\n\t\tfunction setupView(isReload) {\r\n\t\t\tif (!UserFactory.isLoggedIn()) {\r\n\t\t\t\t$location.path(\"/login\");\r\n\t\t\t}\r\n\r\n\t\t\t$scope.NeedsToSync = UpdateService.updater();\r\n\t\t\t/*\t\t\t\t\r\n\t\t\tvar reportstobesynched = PilotReportLocalEditFactory.getPilotReportLocalEditThatNeedToBeSynched();\r\n\t\t\r\n\t\t$scope.number_of_reports_to_sync = reportstobesynched.length;\r\n\t\t*/\r\n\t\t\t$scope.number_of_messages = MessageFactory.getMessagesFromStorage().length;\r\n\t\t\t$scope.number_of_messages_not_readen = MessageFactory.getCountOfUnreadMessages();\r\n\r\n\t\t\t//Get count of unread memos but remove the ones that belong in 'Training Surveys' Category\r\n\t\t\tMemoFactory.getUnreadMemos(function (memos) {\r\n\r\n\t\t\t\tvar unreadMemosCount = 0;\r\n\t\t\t\t//remove memos that belong in \"Training Surveys\" category\r\n\t\t\t\tfor (var i = 0; i < memos.length; i++) {\r\n\t\t\t\t\tif (memos[i].Category != \"Training Surveys\") {\r\n\t\t\t\t\t\tunreadMemosCount++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t$scope.unreadMemosCount = unreadMemosCount;\r\n\t\t\t});\r\n\r\n\t\t\t//Get autoland procedures\r\n\t\t\tvar autoland = AutolandFactory.getAutolandFromStorage();\r\n\t\t\t$scope.autolandCount = 0;\r\n\t\t\t$scope.flightsLeft = 0;\r\n\t\t\tif (autoland != null) {\r\n\t\t\t\t$scope.autolandCount = autoland.autolandCount;\r\n\t\t\t\t$scope.flightsLeft = autoland.flightsLeft;\r\n\t\t\t\t$scope.hasAEFlights = autoland.totalAEFlights > 0\r\n\t\t\t}\r\n\t\t\t// read the flights from the local storage and display them\r\n\t\t\tvar flights = FlightFactory.getFlightsFromStorageAndCheckIfTooOld();\r\n\r\n\t\t\t// also load the flights created by the user\r\n\t\t\tflights = FlightFactory.getLocalFlightsAndMergeWithServerFlights(flights);\r\n\r\n\r\n\t\t\t// if no local flights are found then force sync\r\n\t\t\tif (!isReload) {\r\n\t\t\t\tneedsToSync = true;\r\n\t\t\t}\r\n\t\t\tvar crewRoutes = CrewRouteFactory.getCrewRoutesFromStorage();\r\n\t\t\tvar groundDuties = GroundDutyFactory.getGroundDutiesFromStorage();\r\n\r\n\t\t\tvar crewRoutesEvents = formatCrewRoutes(crewRoutes);\r\n\t\t\tvar groundDutiesEvents = formatGroundDuties(groundDuties);\r\n\r\n\t\t\t\r\n\t\t\tvar flightEvents = formatFlights(flights);\r\n\r\n\t\t\tvar events = flightEvents.concat(groundDutiesEvents).concat(crewRoutesEvents);\r\n\r\n\t\t\tvar specialDates = findScheduleChangedDates();\r\n\r\n\t\t\t// //temporary disable for A3\r\n\t\t\t// var showInCalendar = CrewHotelFactory.showHotelsInCalendar(flights)\r\n\t\t\t// if(showInCalendar){\r\n\t\t\t// \tvar crewHotels = CrewHotelFactory.getCrewHotelsFromStorage();\r\n\t\t\t// \tvar crewHotelsEvents = formatHotels(crewHotels);\r\n\t\t\t// \tevents = events.concat(crewHotelsEvents);\r\n\t\t\t// }\r\n\r\n\t\t\t//Enable again!\r\n\t\t\tvar crewHotels = CrewHotelFactory.getCrewHotelsFromStorage();\r\n\t\t\tvar crewHotelsEvents = formatHotels(crewHotels);\r\n\t\t\tevents = events.concat(crewHotelsEvents);\r\n\r\n\t\t\tcalendar(events, specialDates);\r\n\r\n\t\t\tvar needsToSync = false;\r\n\r\n\t\t\t// check the last sync date\r\n\t\t\tvar lastLog = SyncLogFactory.getSyncLog();\r\n\t\t\tvar canShowSync = true;\r\n\t\t\tif (lastLog == null) {\r\n\t\t\t\tneedsToSync = true;\r\n\t\t\t} else {\r\n\t\t\t\tcanShowSync = lastLog.canShowSync(); //used to avoid showing again and again the dialog :: delay X minutes before showing again\r\n\t\t\t\tif (lastLog.date == null)\r\n\t\t\t\t\tneedsToSync = true;\r\n\t\t\t\telse if (lastLog.date != null) {\r\n\t\t\t\t\tif (Date.today().add(-1).days().toUTC().isAfter(new Date(lastLog.date).toUTC()) || lastLog.forceSync) {\r\n\t\t\t\t\t\tif (!isReload)\r\n\t\t\t\t\t\t\tneedsToSync = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tvar isOpenUpdateModal = ($(\".modal-updating\").data('bs.modal') || { isShown: false }).isShown;\r\n\t\t\tif (needsToSync && canShowSync && !isOpenUpdateModal) {\r\n\t\t\t\t$scope.openSynch();\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tMemoFactory.getMandatoryUnreadMemos(function (memos) {\r\n\t\t\t\t\tvar mandatoryUnread = 0;\r\n\t\t\t\t\t//remove memos that belong in \"Training Surveys\" category\r\n\t\t\t\t\tfor (var i = 0; i < memos.length; i++) {\r\n\t\t\t\t\t\tif (memos[i].Category != \"Training Surveys\") {\r\n\t\t\t\t\t\t\tmandatoryUnread++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t$scope.mandatoryUnread = mandatoryUnread;\r\n\r\n\t\t\t\t\tif ($scope.mandatoryUnread > 0) {\r\n\t\t\t\t\t\topenMandatoryModal();\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction openMandatoryModal() {\r\n\t\t\tvar modalInstance = $uibModal.open({\r\n\t\t\t\ttemplateUrl: 'views/Flight/dlgMandatory.html',\r\n\t\t\t\tcontroller: 'MandatoryModalCtrl',\r\n\t\t\t\tsize: 'md',\r\n\t\t\t\tbackdrop: 'static',\r\n\t\t\t\tkeyboard: false,\r\n\t\t\t\tresolve: { mandatoryUnread: $scope.mandatoryUnread }\r\n\t\t\t});\r\n\t\t}\r\n\r\n /**\r\n * Finds the dates with a change on their schedule\r\n * @memberof CalendarCtrl\r\n * @param {array} events Calendar events (Flights and Ground duties) \r\n * @returm {array} scheduleChangedDates\r\n */\r\n\t\tfunction findScheduleChangedDates() {\r\n var scheduleChangedDates = ScheduleAcknowledgeFactory.getScheduleChangesFromStorage();\r\n\r\n return scheduleChangedDates;\r\n }\r\n\r\n\t\t\r\n\r\n /**\r\n * Initialize Calendar\r\n * @memberof CalendarCtrl\r\n * @param {array} events Flights and Ground duties \r\n * @param {array} specialDates The Schedule Changed Dates\r\n */\r\n\t\tfunction calendar(events, specialDates) {\r\n\t\t\t\r\n\t\t\t$(\"#calendar\").fullCalendar({\r\n\r\n\t\t\t\tdefaultView: getDefaultView(),\r\n\t\t\t\tdefaultDate: defaultCalendarDate,\r\n\t\t\t\tfirstDay: 1,\r\n\t\t\t\tlang: 'en',\r\n\t\t\t\teditable: false,\r\n\t\t\t\tdraggable: false,\r\n\t\t\t\tselectable: false,\r\n\t\t\t\tselectHelper: false,\r\n\t\t\t\tunselectAuto: false,\r\n\t\t\t\tdisableResizing: false,\r\n\t\t\t\tdroppable: false,\r\n\t\t\t\tfixedWeekCount: false, nextDayThreshold: \"00:00:00\",\r\n\t\t\t\theader: {\r\n\t\t\t\t\tleft: 'title',\r\n\t\t\t\t\tcenter: '',\r\n\t\t\t\t\tright: 'month,listMonth today prev,next'\r\n\t\t\t\t},\r\n\t\t\t\ttimeFormat: 'HH:mm',\r\n\t\t\t\tdisplayEventEnd: true,\r\n\t\t\t\tevents: events,\r\n\t\t\t\teventRender: function (event, element, icon) {\r\n\t\t\t\t\tif ($('#calendar').fullCalendar('getView').type === 'listMonth') {\r\n\t\t\t\t\t\telement.find('.fc-list-item-title').addClass('listview-icon');\r\n\t\t\t\t\t\t$.each(event.className, function (index, icon) {\r\n\t\t\t\t\t\t\telement.addClass(event.listViewColor);\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\t// $.each(event.icons, function (index, icon) {\r\n\t\t\t\t\t\t// element.find('.listview-icon').prepend(\" \");\r\n\t\t\t\t\t\t// });\r\n\r\n\t\t\t\t\t\tif (!event.description == \"\") {\r\n\t\t\t\t\t\t\telement.find('.fc-list-item-title').append(\"\" + \" \" + event.description + \"\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (!event.icon == \"\") {\r\n\t\t\t\t\t\t\telement.find('.fc-list-item-title').append(\"\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (!event.second_icon == \"\") {\r\n\t\t\t\t\t\t\telement.find('.fc-list-item-title').append(\"\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\r\n\t\t\t\t\t\tif (event.type == \"crewRoute\" || event.type == \"crewHotel\") {\r\n\t\t\t\t\t\t\telement.find('.fc-time').remove();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telement.find('.fc-title').prepend(\"
\");\r\n\t\t\t\t\t\tif (!event.description == \"\") {\r\n\t\t\t\t\t\t\telement.find('.fc-title').append(\"
\" + event.description + \"
\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (!event.icon == \"\") {\r\n\t\t\t\t\t\t\telement.find('.fc-title').append(\"\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (!event.second_icon == \"\") {\r\n\t\t\t\t\t\t\telement.find('.fc-title').append(\"\");\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\r\n\t\t\t\tdayRender: function (date, cell) {\r\n\t\t\t\t\tfor (var i = 0; i < specialDates.length; i++) {\r\n\t\t\t\t\t\tvar objdate = new Date(specialDates[i]);\r\n\t\t\t\t\t\tif ((date._d.getFullYear() == objdate.getFullYear()) &&\r\n\t\t\t\t\t\t\t(date._d.getDate() == objdate.getDate()) &&\r\n\t\t\t\t\t\t\t(date._d.getMonth() == objdate.getMonth())\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\tcell.addClass('bg-yellow');\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tdayClick: function (date, jsEvent, view) {\r\n\t\t\t\t},\r\n\t\t\t\teventClick: function (calEvent, jsEvent, view) {\r\n\t\t\t\t\tif (calEvent.type == \"flight\") {\r\n\t\t\t\t\t\t$timeout(function () {\r\n\t\t\t\t\t\t\tgotoFlightInfo(calEvent._id);\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (calEvent.type == \"groundDuty\") {\r\n\t\t\t\t\t\t$timeout(function () {\r\n\t\t\t\t\t\t\tgotoGroundDutyInfo(calEvent._id);\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if (calEvent.type == \"crewRoute\") {\r\n\t\t\t\t\t\t$timeout(function () {\r\n\t\t\t\t\t\t\tgotoCrewRouteInfo(calEvent.dutyNo, calEvent.dutyDay);\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\t\t\t\theight: 'auto'\r\n\t\t\t});\r\n\r\n\r\n\t\t\tfunction getDefaultView() {\r\n\t\t\t\tvar calendarStyle = SettingsMain.getCalendarViewStyle();\r\n\t\t\t\tif (calendarStyle == null) {\r\n\t\t\t\t\tcalendarStyle = detectMobile() ? \"listMonth\" : \"month\";\r\n\t\t\t\t}\r\n\t\t\t\treturn calendarStyle;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction detectMobile() {\r\n\t\t\t\tvar isMobile = (window.innerWidth <= 800 && window.innerHeight <= 735);\r\n\r\n\t\t\t\treturn isMobile;\r\n\t\t\t}\r\n\r\n\t\t\t$('.fc-listMonth-button').click(function () {\r\n\t\t\t\tSettingsMain.setCalendarViewStyle('listMonth');\r\n\t\t\t})\r\n\r\n\t\t\t$('.fc-month-button').click(function () {\r\n\t\t\t\tSettingsMain.setCalendarViewStyle('month');\r\n\t\t\t})\r\n\r\n\t\t}\r\n /**\r\n * Transform flights in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} flights The Scheduled Flights \r\n * @return {array} events \r\n */\r\n\t\tfunction formatFlights(flights) {\r\n\t\t\tvar flightEvents = [];\r\n\t\t\tfor (var i = 0; i < flights.length; i++) {\r\n\t\t\t\tvar description = flights[i].getRoute();\r\n\t\t\t\tvar title = flights[i].FlightNo;\r\n\t\t\t\tif (flights[i].TrainingIndicatorCode) {\r\n\t\t\t\t\ttitle = title + \" \" + flights[i].TrainingIndicatorCode;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar classname = \"\";\r\n\t\t\t\tvar icon = \"fa-plane\";\r\n\t\t\t\tvar second_icon = \"\";\r\n\t\t\t\tvar id = flights[i].FlightId;\r\n\t\t\t\tvar type = \"flight\";\r\n\t\t\t\tvar listViewColor = \"\";\r\n\r\n\r\n\r\n\t\t\t\tif (flights[i].LineStatus === 'na') {\r\n\t\t\t\t\tclassname = \"fc-aluminum\";\r\n\t\t\t\t\tlistViewColor = \"lv-aluminium\";\r\n\t\t\t\t}\r\n\t\t\t\telse if (flights[i].LineStatus === 'pending') {\r\n\t\t\t\t\tclassname = \"fc-blue\";\r\n\t\t\t\t\tlistViewColor = \"lv-blue\";\r\n\t\t\t\t}\r\n\t\t\t\telse if (flights[i].LineStatus === 'pendingoverdue') {\r\n\t\t\t\t\tclassname = \"fc-seablue\";\r\n\t\t\t\t\tlistViewColor = \"lv-seablue\";\r\n\t\t\t\t\t$scope.pendingOverdueReports++;\r\n\t\t\t\t}\r\n\t\t\t\telse if (\r\n\t\t\t\t\t(flights[i].LineStatus === 'draft') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'draftotheruser')\r\n\t\t\t\t) {\r\n\t\t\t\t\tclassname = \"fc-orange\";\r\n\t\t\t\t\tlistViewColor = \"lv-orange\";\r\n\t\t\t\t\t$scope.draftReports++;\r\n\t\t\t\t} else if (\r\n\t\t\t\t\t(flights[i].LineStatus === 'completed') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'completedotheruser')\r\n\t\t\t\t) {\r\n\t\t\t\t\tclassname = \"fc-purple\";\r\n\t\t\t\t\tlistViewColor = \"lv-purple\";\r\n\t\t\t\t\t$scope.completedReports++;\r\n\t\t\t\t} else if (\r\n\t\t\t\t\t(flights[i].LineStatus === 'stored') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'storedotheruser') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'stored+otheruser') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'synched') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'synchedotheruser')\r\n\t\t\t\t) {\r\n\t\t\t\t\tclassname = \"fc-green\";\r\n\t\t\t\t\tlistViewColor = \"lv-green\";\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (flights[i].IsScheduleChanged && flights[i].LineStatus != 'na') {\r\n\t\t\t\t\tclassname = classname + \" text-yellow-important\";\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (flights[i].LineStatus === 'na')\r\n\t\t\t\t\ticon = \"\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'pending')\r\n\t\t\t\t\ticon = \"fa-plus\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'pendingoverdue')\r\n\t\t\t\t\ticon = \"fa-exclamation-triangle text-lemon\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'draft')\r\n\t\t\t\t\ticon = \"fa-pencil\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'completed')\r\n\t\t\t\t\ticon = \"fa-check-circle\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'synched')\r\n\t\t\t\t\ticon = \"fa-check-square-o\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'draftotheruser')\r\n\t\t\t\t\ticon = \"fa-pencil \";\r\n\t\t\t\telse if (flights[i].LineStatus === 'completedotheruser')\r\n\t\t\t\t\ticon = \"fa-check-circle \";\r\n\t\t\t\telse if (flights[i].LineStatus === 'synchedotheruser')\r\n\t\t\t\t\ticon = \"fa-check-square-o\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'stored')\r\n\t\t\t\t\ticon = \"fa-cloud-download\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'storedotheruser')\r\n\t\t\t\t\ticon = \"fa-cloud-download\";\r\n\t\t\t\telse if (flights[i].LineStatus === 'stored+otheruser')\r\n\t\t\t\t\ticon = \"fa-cloud-download\";\r\n\r\n\r\n\t\t\t\tif (\r\n\t\t\t\t\t(flights[i].LineStatus === 'draftotheruser') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'completedotheruser') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'synchedotheruser') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'storedotheruser') ||\r\n\t\t\t\t\t(flights[i].LineStatus === 'stored+otheruser')\r\n\t\t\t\t)\r\n\t\t\t\t\tsecond_icon = \"fa-user\";\r\n\r\n\r\n\t\t\t\tvar IsScheduleChanged = flights[i].IsScheduleChanged;\r\n\r\n\t\t\t\tvar ScheduledDeparture = flights[i].ScheduledDeparture\r\n\r\n\t\t\t\tif (flights[i].ScheduledArrival == null) {\r\n\t\t\t\t\tvar ScheduledArrival = ScheduledDeparture;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar ScheduledArrival = flights[i].ScheduledArrival\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar event = {\r\n\t\t\t\t\t_id: id,\r\n\t\t\t\t\ttitle: title,\r\n\t\t\t\t\tstart: ScheduledDeparture,\r\n\t\t\t\t\tend: ScheduledArrival,\r\n\t\t\t\t\tdescription: description,\r\n\t\t\t\t\ticon: icon,\r\n\t\t\t\t\tsecond_icon: second_icon,\r\n\t\t\t\t\tclassName: classname,\r\n\t\t\t\t\ttype: type,\r\n\t\t\t\t\tisScheduleChanged: IsScheduleChanged,\r\n\t\t\t\t\tlistViewColor: listViewColor\r\n\t\t\t\t};\r\n\t\t\t\tflightEvents.push(event)\r\n\t\t\t}\r\n\r\n\t\t\treturn flightEvents;\r\n\t\t}\r\n\r\n /**\r\n * Transform Ground Duties in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} duties The Scheduled Ground Duties \r\n * @return {array} events \r\n */\r\n\t\tfunction formatGroundDuties(duties) {\r\n\t\t\tvar groundEvents = [];\r\n\t\t\tvar now=moment.utc();\r\n\r\n\t\t\tfor (var i = 0; i < duties.length; i++) {\r\n\t\t\t\t//var description = duties[i].DutyDescription +\"
\";\r\n\t\t\t\tvar description = duties[i].Code;\r\n\t\t\t\tvar title = (duties[i].Title) ? duties[i].Title : duties[i].Duty;\r\n\r\n\r\n\t\t\t\tvar classname = \"fc-white\";\r\n\t\t\t\tvar icon = \"\";\r\n\t\t\t\tif(duties[i].RelatedGroundDuties && duties[i].RelatedGroundDuties.length > 1){\r\n\t\t\t\t\ticon=\"fa-graduation-cap\" // icon only if training\r\n\t\t\t\t\t\r\n\t\t\t\t\t//Get ground courses\r\n\t\t\t\t\tvar courseStatuses =[]; \r\n\t\t\t\t\tvar coursesFlat = [];\r\n\t\t\t\t\tfor(var j=0; j1){\r\n\t\t\t\t\t\t\tif(courseStatuses.includes(\"Pending\"))\t$scope.hasUnsetTraining = true;\r\n\t\t\t\t\t\t\tclassname = \"fc-seablue-inverted\"\r\n\t\t\t\t\t\t\ticon = \"fa-exclamation-triangle text-yellow\";\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t//Draft\r\n\t\t\t\t\t\tvar courseId = coursesFlat[0].CourseId; // each duty should contain ONLY ONE COURSE\r\n\t\t\t\t\t\tvar duty = duties[i];\r\n\r\n\t\t\t\t\t\tif(groundSessions && groundSessions.length){\r\n\t\t\t\t\t\t\tvar existingSession = groundSessions.find(s => s.courseId == courseId && s.day == duty.DutyDateS && s.dutyId == duty.Id);\r\n\t\t\t\t\t\t\tif(existingSession && !existingSession.HasLimitedInfo && existingSession.trainees && existingSession.trainees.length){\r\n\t\t\t\t\t\t\t\t//a training session with trainees exists\r\n\t\t\t\t\t\t\t\tclassname = \"fc-orange-inverted\";\r\n\t\t\t\t\t\t\t\ticon = \"fa-graduation-cap\";\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}else if(courseStatuses.includes(\"Completed\")){\r\n\t\t\t\t\t\t//Completed\r\n\t\t\t\t\t\tclassname = \"fc-green-inverted \"\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t\r\n\r\n\t\t\t\tvar second_icon = \"\";\r\n\t\t\t\tif (duties[i].Unread) {\r\n\t\t\t\t\tsecond_icon = \"fa-envelope text-orange\";\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar id = duties[i].Id;\r\n\t\t\t\tvar type = \"groundDuty\";\r\n\t\t\t\tvar start = (duties[i].DutyBegin) ? duties[i].DutyBegin : ((duties[i].DutyDateS) ? duties[i].DutyDateS : duties[i].DutyDate);\r\n\t\t\t\tvar end = duties[i].DutyEnd;\r\n\t\t\t\tvar listViewColor = \"lv-white\";\r\n\r\n\r\n\t\t\t\tvar event = {\r\n\t\t\t\t\t_id: id,\r\n\t\t\t\t\ttitle: title,\r\n\t\t\t\t\tstart: start,\r\n\t\t\t\t\tend: end,\r\n\t\t\t\t\tdescription: description,\r\n\t\t\t\t\ticon: icon,\r\n\t\t\t\t\tsecond_icon: second_icon,\r\n\t\t\t\t\tclassName: classname,\r\n\t\t\t\t\ttype: type,\r\n\t\t\t\t\tlistViewColor: listViewColor\r\n\t\t\t\t};\r\n\r\n\t\t\t\tgroundEvents.push(event);\r\n\t\t\t}\r\n\r\n\t\t\treturn groundEvents;\r\n\t\t}\r\n\r\n\t\t/**\r\n * Transform Crew Routes in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} routes The Scheduled Crew Routes \r\n * @return {array} events \r\n */\r\n\t\tfunction formatCrewRoutes(routes) {\r\n\t\t\tvar crewRouteEvents = [];\r\n var now=moment.utc();\r\n\r\n\t\t\tfor (var i = 0; i < routes.length; i++) {\r\n\t\t\t\tvar description = routes[i].Route;\r\n\t\t\t\t// var title = (duties[i].Title)? duties[i].Title : duties[i].Duty;\r\n\r\n\t\t\t\tvar classname = \"fc-white\";\r\n\r\n\t\t\t\tvar icon = \"\";\r\n\t\t\t\tvar second_icon = \"\";\r\n\r\n\t\t\t\t//Get ground courses\r\n\t\t\t\tvar courseStatuses=[]; \r\n\t\t\t\tvar courses = routes[i].Courses;\r\n\r\n\t\t\t\tif(courses){\r\n\t\t\t\t\tcourses.forEach(function(x){\r\n\t\t\t\t\t\tcourseStatuses.push(x.Status)\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\r\n\t\t\t\t/*Statuses\r\n\t\t\t\t\tCompleted : session has been sent\r\n\t\t\t\t\tOutdated :\tsession submission is overdue\r\n\t\t\t\t\tDraft\t : session completion has started but not submitted\r\n\t\t\t\t\tPending : session submission not yet due\r\n\t\t\t\t*/\r\n\r\n\t\t\t\tvar trainingStatus = \"\";\r\n\t\t\t\tif(courseStatuses.includes(\"Pending\")){\r\n\t\t\t\t\t//Pending\r\n\t\t\t\t\ttrainingStatus = \"Pending\";\r\n\r\n\t\t\t\t\t//Outdated\r\n\t\t\t\t\tvar dutyEnd = moment.utc(routes[i].DutyEnd);\r\n\t\t\t\t\tvar duration = moment.duration(now.diff(dutyEnd)).asHours();\r\n\t\t\t\t\tif(duration>1){\r\n\t\t\t\t\t\tif(courseStatuses.includes(\"Pending\"))\t$scope.hasUnsetTraining = true;\r\n\t\t\t\t\t\ttrainingStatus = \"Outdated\";\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//Draft\r\n\t\t\t\t\tvar courseIds = courses.map(x => x.CourseId); \r\n\t\t\t\t\tvar route = routes[i];\r\n\r\n\t\t\t\t\tif(flightSessions && flightSessions.length){\r\n\t\t\t\t\t\t//TODO msis fix\r\n\t\t\t\t\t\tvar dutyBegin = new moment(route.DutyBegin).format(\"YYYY-MM-DD\");\r\n\t\t\t\t\t\tvar dutyEnd = new moment(route.DutyEnd).format(\"YYYY-MM-DD\");\r\n\t\t\t\t\t\tvar existingSessions = flightSessions.filter(s => courseIds.includes(s.courseId) && (new moment(s.day).isSame(dutyBegin) || new moment(s.day).isSame(dutyEnd) || new moment(s.day).isBetween(dutyBegin, dutyEnd)) \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t&& s.dutyDay == route.DutyDay && s.dutyNo == route.DutyNo);\r\n\t\t\t\t\t\tif(existingSessions && existingSessions.some(x => !x.HasLimitedInfo && x.trainees && x.trainees.length)){\r\n\t\t\t\t\t\t\t//a training session with trainees exists\r\n\t\t\t\t\t\t\ttrainingStatus = \"Draft\";\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}else if(courseStatuses.includes(\"Completed\")){\r\n\t\t\t\t\t//Completed\r\n\t\t\t\t\ttrainingStatus = \"Completed\";\r\n\t\t\t\t\tclassname = \"fc-green-inverted \";\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tif(trainingStatus == \"Outdated\"){\r\n\t\t\t\t\tsecond_icon = \"fa-exclamation-triangle text-yellow second-icon-training\";\r\n\t\t\t\t\tclassname = \"fc-seablue-inverted\";\r\n\t\t\t\t}\r\n\t\t\t\telse if(trainingStatus == \"Draft\"){\r\n\t\t\t\t\tclassname = \"fc-orange-inverted\";\r\n\t\t\t\t}\r\n\t\t\t\telse if(trainingStatus == \"Pending\"){\r\n\t\t\t\t\tclassname = \"fc-blue-inverted\";\r\n\t\t\t\t}\r\n\t\t\t\telse if (trainingStatus == \"Completed\"){\r\n\t\t\t\t\tclassname = \"fc-green-inverted\";\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif(courses && courses.length){\r\n icon = \"fa-graduation-cap\";\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t// var id = routes[i].Id;\r\n\t\t\t\tvar type = \"crewRoute\";\r\n\t\t\t\tvar dutyNo = routes[i].DutyNo;\r\n\t\t\t\tvar dutyDay = routes[i].DutyDay;\r\n\t\t\t\tvar start = (routes[i].DutyBegin) ? routes[i].DutyBegin : ((routes[i].DutyDateS) ? routes[i].DutyDateS : routes[i].DutyDate);\r\n\t\t\t\tvar end = routes[i].DutyEnd;\r\n\t\t\t\tvar listViewColor = \"lv-white\";\r\n\r\n\t\t\t\tvar event = {\r\n\t\t\t\t\t// _id:id,\r\n\t\t\t\t\t// title: title,\r\n\t\t\t\t\tdutyNo: dutyNo,\r\n\t\t\t\t\tdutyDay: dutyDay,\r\n\t\t\t\t\tstart: start,\r\n\t\t\t\t\tend: end,\r\n\t\t\t\t\tdescription: description,\r\n\t\t\t\t\ticon: icon,\r\n\t\t\t\t\tsecond_icon: second_icon,\r\n\t\t\t\t\tclassName: classname,\r\n\t\t\t\t\ttype: type,\r\n\t\t\t\t\tlistViewColor: listViewColor\r\n\t\t\t\t};\r\n\r\n\t\t\t\tcrewRouteEvents.push(event);\r\n\t\t\t}\r\n\t\t\treturn crewRouteEvents;\r\n\t\t}\r\n\r\n /**\r\n * Transform Crew Hotels in calendar events\r\n * @memberof CalendarCtrl\r\n * @param {array} crew hotels \r\n * @return {array} events \r\n */\r\n function formatHotels(hotels, flights, groundDuties){\r\n var crewRouteEvents = [];\r\n for(var i=0;i= 0)\r\n\t\t\t\tflights[flightIndex] = flight;\r\n\t\t\telse\r\n\t\t\t\tflights.push(flight);\r\n\r\n\t\t\t//Save\r\n\t\t\tlocalStorageMD5Service.set('flights', flights);\r\n\t\t}\r\n \r\n\t\tfunction updateFlightFromReport(report) {\r\n\t\t\tvar flight = getFlightFromStorage(report.FlightId);\r\n\t\t\tif (flight != null && flight != undefined) {\r\n\t\t\t\tflight.AcTailNo = report.AcTailNo;\r\n\t\t\t\tflight.AcType = report.AcType;\r\n\r\n\t\t\t\tvar allflights = getFlightsFromStorage();\r\n\t\t\t\tfor (var i = 0; i < allflights.length; i++) {\r\n\t\t\t\t\tif (allflights[i].FlightId != null && allflights[i].FlightId == report.FlightId) {\r\n\t\t\t\t\t\tvar reportIndex = i;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tflight.initialize();\r\n\t\t\t\tallflights[reportIndex] = flight;\r\n\t\t\t\tsetFlightsToStorage(allflights);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfunction getServerPilotReportForUser(userAimsId) {\r\n\t\t\t\r\n\t\t\tif (this.pilotReports == null)\r\n\t\t\t\treturn null;\r\n\t\t\r\n\t\t\tvar result = null;\r\n\t\t\r\n\t\t\tfor (var i=0; i 0) {\r\n\t\t\t\t\tvar token = '';\r\n\t\t\t\t\tif (user != null)\t{\r\n\t\t\t\t\t\ttoken = user.token;\r\n\t\t\t\t\t\ttoken = encodeURIComponent(token);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.CabinReportId =this.cabinReports[0].ReportId;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t\tthis.CabinReportId = null;\r\n\t\t\t\t\r\n\t\t\t\t// initialize the pilot report status field\r\n\t\t\t\tthis.initializePilotReportStatus(user);\r\n\t\t\t\t\r\n\t\t\t\t// initialize css classes for display\r\n\t\t\t\tthis.pilotReportStatusDescr = this.getPilotReportStatusDescr();\r\n\t\t\t}\r\n\t\t\tcatch (ex)\r\n\t\t\t{\r\n\t\t\t\t$log.error(\"initialize failed: \" + ex.message);\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n /**\r\n * Initialize Pilot report Status\r\n * @memberof FlightFactory\r\n * @param {object} user \r\n */\t\r\n function initializePilotReportStatus(user){\r\n\r\n\t\t\t// check that the user is a CP\r\n\t\t\tif ((user == null) || (this.IsDHC != 0) || (this.Position != 'CP'))\t{\r\n\t\t\t\tthis.LineStatus = \"na\";\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// initialize to pending\r\n\t\t\tthis.LineStatus = \"pending\";\r\n\r\n\t\t\t// check if there is a local edit report or a server report for this\r\n\t\t\t// flight\r\n\t\t\tvar serverReportForThisUser = this.getServerPilotReportForUser(user.aimsId);\r\n\t\t\tvar serverReportsByAnotherUser = this.getServerPilotReportsByAnotherUser(user.aimsId);\r\n\r\n\t\t\tvar hasServerReportForThisUser = serverReportForThisUser != null;\r\n\t\t\tvar hasServerReportsByAnotherUser = serverReportsByAnotherUser.length > 0;\r\n\t\t\t\r\n\t\t\tvar localReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(this.FlightId);\r\n\t\t\t\r\n\t\t\tthis.LocalReportId = null;\r\n\t\t\tthis.ServerReportLink = null;\r\n\t\t\t\r\n\t\t\t// if there is a local copy of the report\r\n\t\t\tif (localReport != null)\r\n\t\t\t{\r\n\t\t\t\tthis.LocalReportId = localReport.ReportGuid;\r\n\t\t\t\tthis.LocalReportHasNothingToReport = localReport.NothingToReport;\r\n\t\t\t\t\r\n\t\t\t\tif (localReport.Status === 'draft')\r\n\t\t\t\t{\r\n\t\t\t\t\tif (hasServerReportsByAnotherUser)\r\n\t\t\t\t\t\tthis.LineStatus = \"draftotheruser\";\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tthis.LineStatus = \"draft\";\r\n\t\t\t\t}\r\n\t\t\t\telse if (localReport.Status === 'completed')\r\n\t\t\t\t{\r\n\t\t\t\t\tif (hasServerReportsByAnotherUser)\r\n\t\t\t\t\t\tthis.LineStatus = \"completedotheruser\";\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tthis.LineStatus = \"completed\";\r\n\t\t\t\t}\r\n\t\t\t\telse if (localReport.Status === 'synched')\r\n\t\t\t\t{\r\n\t\t\t\t\tif (hasServerReportsByAnotherUser)\r\n\t\t\t\t\t\tthis.LineStatus = \"synchedotheruser\";\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tthis.LineStatus = \"synched\";\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif (hasServerReportsByAnotherUser)\r\n\t\t\t\t\t\tthis.LineStatus = \"draftotheruser\";\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tthis.LineStatus = \"draft\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// if there is a server report by this and by another user\r\n\t\t\t\tif (hasServerReportForThisUser && hasServerReportsByAnotherUser)\r\n\t\t\t\t{\r\n\t\t\t\t\tthis.LineStatus = \"stored+otheruser\";\r\n\t\t\t\t\t// Something if this or any other user has something to\r\n\t\t\t\t\t// report\r\n\t\t\t\t\tthis.ServerReportHasNothingToReport = serverReportForThisUser.ReportedItems == 0;\r\n\t\t\t\t\tif (this.ServerReportHasNothingToReport){\r\n\t\t\t\t\t\t// if nothing to report by this user, check if any other\r\n\t\t\t\t\t\t// user has something to report\r\n\t\t\t\t\t\tfor (var i=0; i 0) {\r\n\t\t\t\t\t\t\t\tthis.ServerReportHasNothingToReport = false;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// if there is a server report for another user\r\n\t\t\t\telse if (hasServerReportsByAnotherUser)\r\n\t\t\t\t{\r\n\t\t\t\t\tthis.LineStatus = \"storedotheruser\";\r\n\t\t\t\t\t\r\n\t\t\t\t\tthis.ServerReportHasNothingToReport = true;\r\n\t\t\t\t\tfor (var i=0; i 0) {\r\n\t\t\t\t\t\t\tthis.ServerReportHasNothingToReport = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// if there is a server report for only this user\r\n\t\t\t\telse if (hasServerReportForThisUser)\r\n\t\t\t\t{\r\n\t\t\t\t\tthis.LineStatus = \"stored\";\r\n\t\t\t\t\tthis.ServerReportHasNothingToReport = serverReportForThisUser.ReportedItems == 0;\r\n\t\t\t\t}\r\n\t\t\t\t// no server report\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tthis.LocalReportId = \"new\";\r\n\t\t\t\t\t\r\n\t\t\t\t\t// no server report found for this user, status is pending\r\n\t\t\t\t\tif (new Date(this.ScheduledDeparture) < new Date())\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tthis.LineStatus = \"pendingoverdue\";\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tthis.LineStatus = \"pending\";\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\r\n /**\r\n * Get Pilot Report Status Descr\r\n * @memberof FlightFactory\r\n * @returns {string} description \r\n */\t\t\r\n function getPilotReportStatusDescr() {\r\n\t\t\tif (this.LineStatus === 'na')\r\n\t\t\t\treturn \"n/a\";\r\n\t\t\telse if (this.LineStatus === 'pending')\r\n\t\t\t\treturn \"Pending\";\r\n\t\t\telse if (this.LineStatus === 'pendingoverdue')\r\n\t\t\t\treturn \"Pending\";\r\n\t\t\telse if (this.LineStatus === 'draft')\r\n\t\t\t\treturn \"Draft\";\r\n\t\t\telse if (this.LineStatus === 'completed')\r\n\t\t\t\treturn \"Completed\";\r\n\t\t\telse if (this.LineStatus === 'synched')\r\n\t\t\t\treturn \"Synched\";\r\n\t\t\telse if (this.LineStatus === 'draftotheruser')\r\n\t\t\t\treturn \"Draft +\";\r\n\t\t\telse if (this.LineStatus === 'completedotheruser')\r\n\t\t\t\treturn \"Completed +\";\r\n\t\t\telse if (this.LineStatus === 'synchedotheruser')\r\n\t\t\t\treturn \"Synched +\";\r\n\t\t\telse if (this.LineStatus === 'stored')\r\n\t\t\t\treturn \"Stored\";\r\n\t\t\telse if (this.LineStatus === 'storedotheruser')\r\n\t\t\t\treturn \"Stored\";\r\n\t\t\telse if (this.LineStatus === 'stored+otheruser')\r\n\t\t\t\treturn \"Stored +\";\r\n\t\t\telse\r\n\t\t\t\treturn this.LineStatus;\r\n\t\t}\r\n \r\n /**\r\n * Get Server PilotReport For the selected User\r\n * @memberof FlightFactory\r\n * @param {number} userAimsId The user aims Id\r\n * @return {object} pilotReport \r\n */\t\t\r\n function getServerPilotReportForUser(userAimsId){\r\n\r\n if (this.pilotReports == null)\r\n return null;\r\n\r\n var result = null;\r\n\r\n for (var i=0; i 0 && ((pilotReportsX && cabinReportsX)|| messagesX )){\r\n\r\n\t\t\t// loop all flights\r\n\t\t\tvar user = UserFactory.getUser();\r\n\t\t\t\t\t\tvar f, pr, cr, me;\r\n\t\t\tfor (var fi=0;fi 0){\r\n\t\t\t\t\t\r\n\t\t\t\t\tfor (var pri=0; pri 0){\r\n\t\t\t\t\tfor (var cri=0; cri 0){\r\n\r\n\t\t\t\t\t\t\t\t\t\tfor (var mi=0; mi= 0)\r\n\t\t\tlocalFlights[flightIndex] = flight;\r\n\t\telse\r\n\t\t\tlocalFlights.push(flight);\r\n\t\t\r\n\t\t// save\r\n\t\tlocalStorageMD5Service.set('localFlights',localFlights);\r\n\t}\r\n \r\n /**\r\n * Save a local flight\r\n * @memberof FlightFactory\r\n * @param {object} flight\r\n */\r\n function getLocalFlightsAndMergeWithServerFlights(serverFlights){\r\n\r\n\t\tif (serverFlights == null)\r\n\t\t\tserverFlights = new Array();\r\n\t\t\r\n\t\t// get the local flights array from storage\r\n\t\tvar localFlights = fromObjectList(localStorageMD5Service.get('localFlights'));\r\n\t\tif (localFlights == null)\r\n\t\t\tlocalFlights = new Array();\r\n\r\n\t\t// add the local flight to the given array\r\n\t\tvar arrayLength = localFlights.length;\r\n\t\tfor (var i = 0; i < arrayLength; i++) {\r\n localFlights[i].initialize();\r\n\t\t\tserverFlights.push(localFlights[i]);\r\n\t\t}\r\n\t\t\r\n\t\treturn serverFlights;\r\n\t}\r\n \r\n /**\r\n * Get Flight from local flights\r\n * @memberof FlightFactory\r\n * @param {number} flightId \r\n * @return {object} flight\r\n */ \r\n\t\tfunction getLocalFlightFromStorage(flightId) {\r\n\t\t\t\t\tvar flight = GenericService.get(flightId,'localFlights',objCallback);\r\n if(flight){\r\n flight.initialize();\r\n }\r\n\t\t\t\t\treturn fromObject(flight);\r\n\t\t\t}\r\n /**\r\n * mark Schedule Changed Flights by comparing flights from new and old data\r\n * @memberof FlightFactory\r\n * @param {object} newFlights \r\n * @param {object} oldFlights\r\n * @return {object} newFlights \r\n */ \r\n\t\tfunction markScheduleChangedFlights(newFlights, oldFlights) {\r\n var lastScheduleDate = SyncLogFactory.getLastScheduleDate();\r\n\t\t\t\r\n //if there are no old flights or no last schedule date\r\n\t\t\tif(oldFlights && lastScheduleDate){\r\n //loop all new flights\r\n var exists;\r\n for(var i=0;i handleSubmitResponse(res))\r\n .catch(res => handleFailedResponse(res));\r\n\t\t}\r\n\t\t\t\r\n\t\tfunction handleSubmitResponse(res) {\r\n $scope.showContent = 'results';\r\n\r\n\t\t\t$scope.availableCources = res.data.trainingCourses;\r\n $scope.pendingDuties = res.data.pendingGroundDuties;\r\n \r\n $scope.availableCources.forEach(function(course) {\r\n course.HasLimitedInfo = true;\r\n CourseFactory.upsertCourse(course, function() { });\r\n });\r\n $scope.pendingDuties.forEach(function(duty) {\r\n duty.isManualEntry = true;\r\n duty.hasPendingCourse = true;\r\n GroundDutyFactory.addGroundDuty(duty);\r\n });\r\n\r\n }\r\n\r\n\t\tfunction handleFailedResponse(res) {\r\n $scope.showContent = 'results';\r\n\t\t\t$scope.hasError = true;\r\n }\t\r\n\t \r\n\t\tfunction closeModal() {\r\n $uibModalInstance.close();\r\n $route.reload();\r\n }\r\n\r\n}\r\n\r\n})();","(function () {\r\n\r\n a3_pilot_reports.directive('aimsCrewMemos', aimsCrewMemos);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name aimsCrewMemos\r\n * @restrict E\r\n * @description\r\n * Implementation of aimsCrewMemos\r\n * Initialize the Aims Crew Memos\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function aimsCrewMemos(AimsCrewMemosFactory) {\r\n function link($scope, element, attrs) {\r\n $scope.aimsCrewMemos = AimsCrewMemosFactory.getAimsCrewMemosByDate(attrs.date);\r\n \r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/directives/aimsCrewMemos.tpl.html\",\r\n scope: true,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('AimsCrewMemosFactory', AimsCrewMemosFactory)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AimsCrewMemosFactory\r\n * @description \r\n * Add, Update, Delete and Get Aims Crew Memos.\r\n * @ngInject\r\n */\r\nfunction AimsCrewMemosFactory(GenericService) {\r\n \r\n /**\r\n * Initialize the AircaftPositions\r\n * @memberof AircaftPositionsFactory\r\n */\r\n\t\tfunction AimsCrewMemos() {\r\n\t\t\tthis.Date = null;\r\n\t\t\tthis.Line = null;\r\n\t\t\tthis.OrderNo = null;\r\n\t\t\t\r\n \r\n this.GetId = GetId;\r\n\t\t}\r\n\t\t\t\t\r\n\t\tvar objType = 'AimsCrewMemos';\r\n\t\tvar objCallback = AimsCrewMemos; \r\n\t\t\r\n\t\tvar service = \r\n\t\t{ \r\n\t\t\tgetAimsCrewMemosFromStorage : getAimsCrewMemosFromStorage,\r\n\t\t\tsetAimsCrewMemosToStorage : setAimsCrewMemosToStorage,\r\n\t\t\tclearAimsCrewMemosFactoryFromStorage : clearAimsCrewMemosFactoryFromStorage,\r\n\t\t\tgetAimsCrewMemosByDate : getAimsCrewMemosByDate\r\n\t\t};\r\n\r\n /**\r\n * Overide default get Id\r\n * @memberof AimsCrewMemosFactory\r\n * @returns {string} Id \r\n */\r\n\t\tfunction GetId() {\r\n\t\t\treturn this.Date;\r\n\t\t}\r\n\t\t\t\t\r\n \r\n \r\n /**\r\n * Get Aims Crew Memos\r\n * @memberof AimsCrewMemosFactory\r\n * @returns {Array} Aims Crew Memos\r\n */\r\n\t\tfunction getAimsCrewMemosFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Save Aims Crew Memos to storage\r\n * @memberof AimsCrewMemosFactory\r\n * @param {Array} A list of Aims Crew Memos\r\n */\r\n\t\tfunction setAimsCrewMemosToStorage(aircaftPositions) {\r\n\t\t\tGenericService.saveAll(aircaftPositions,objType,objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Remove the Aims Crew Memos of the local storage\r\n * @memberof AimsCrewMemosFactory\r\n */\r\n\t\tfunction clearAimsCrewMemosFactoryFromStorage() {\r\n\t\t\tGenericService.removeAll(objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Get AimsCrewMemosFactory of this flight by date\r\n * @memberof AimsCrewMemosFactory\r\n * @returns {Object} AimsCrewMemosFactory\r\n */\r\n\t\tfunction getAimsCrewMemosByDate(date) {\r\n\t\t var crewMemos = getAimsCrewMemosFromStorage();\r\n \r\n var datesMemos = [];\r\n var arrayLength = crewMemos.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (crewMemos[i].GetId() == date) {\r\n\t\t\t\t\tdatesMemos.push(crewMemos[i]);\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn datesMemos;\r\n\t\t}\r\n \r\n \r\n\r\n\r\n\r\n\treturn service;\r\n\t}\r\n\r\n})();","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.factory('AircaftPositionsFactory', AircaftPositionsFactory)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AircaftPositionsFactory\r\n * @description \r\n * Add, Update, Delete and Get AircaftPositions.\r\n * @ngInject\r\n */\r\n\tfunction AircaftPositionsFactory(GenericService) {\r\n\r\n /**\r\n * Initialize the AircaftPositions\r\n * @memberof AircaftPositionsFactory\r\n */\r\n\t\tfunction AircaftPositions() {\r\n\t\t\tthis.FlightId = null;\r\n\t\t\tthis.PreviousFlightNo = null;\r\n\t\t\tthis.PreviousStation = null;\r\n\t\t\tthis.PreviousSTA = null;\r\n\t\t\tthis.PreviousETA = null;\r\n\t\t\tthis.PreviousATA = null;\r\n\t\t\tthis.PreviousGATE = null;\r\n\t\t\tthis.PreviousSTAND = null;\r\n\t\t\tthis.NextFlightNo = null;\r\n\t\t\tthis.NextStation = null;\r\n\t\t\tthis.NextSTD = null;\r\n\t\t\tthis.NextETD = null;\r\n\t\t\tthis.NextATD = null;\r\n\t\t\tthis.NextGATE = null;\r\n\t\t\tthis.NextSTAND = null;\r\n\r\n\t\t\tthis.GetId = GetId;\r\n\t\t}\r\n\r\n\t\tvar objType = 'aircaftpositions';\r\n\t\tvar objCallback = AircaftPositions;\r\n\r\n\t\tvar service =\r\n\t\t{\r\n\t\t\tgetAircaftPositionsFromStorage: getAircaftPositionsFromStorage,\r\n\t\t\tsetAircaftPositionsToStorage: setAircaftPositionsToStorage,\r\n\t\t\tclearAircaftPositionsFromStorage: clearAircaftPositionsFromStorage,\r\n\t\t\tgetAircaftPositionsByFlightId: getAircaftPositionsByFlightId,\r\n\t\t\tupdateAircraftPositionsToStorage: updateAircraftPositionsToStorage\r\n\t\t};\r\n\r\n /**\r\n * Overide default get Id\r\n * @memberof AircaftPositionsFactory\r\n * @returns {number} Id \r\n */\r\n\t\tfunction GetId() {\r\n\t\t\treturn this.FlightId;\r\n\t\t}\r\n\r\n\r\n\r\n /**\r\n * Get messages\r\n * @memberof AircaftPositionsFactory\r\n * @returns {Array} Aircaft Positions \r\n */\r\n\t\tfunction getAircaftPositionsFromStorage() {\r\n\t\t\treturn GenericService.list(objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Save Aircaft Positions to storage\r\n * @memberof AircaftPositionsFactory\r\n * @param {Array} messages A list of Aircaft Positions\r\n */\r\n\t\tfunction setAircaftPositionsToStorage(aircaftPositions) {\r\n\t\t\tGenericService.saveAll(aircaftPositions, objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Remove the Aircaft Positions of the local storage\r\n * @memberof AircaftPositionsFactory\r\n */\r\n\t\tfunction clearAircaftPositionsFromStorage() {\r\n\t\t\tGenericService.removeAll(objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Get Aircaft Positions of this flight\r\n * @memberof AircaftPositionsFactory\r\n * @returns {Object} Aircaft Positions \r\n */\r\n\t\tfunction getAircaftPositionsByFlightId(flightId) {\r\n\t\t\treturn GenericService.get(flightId, objType, objCallback);\r\n\t\t}\r\n\r\n\r\n\t\t/**\r\n\t\t* Update Aircraft Position to storage\r\n\t\t* @memberof AircaftPositionsFactory\r\n\t\t* @param {object} aircraftPositions Aircraft Positions\r\n\t\t*/\r\n\t\tfunction updateAircraftPositionsToStorage(aircraftPositions, flightId) {\r\n\t\t\tif (GenericService.get(flightId, objType, objCallback)){\r\n\t\t\t\tGenericService.save(aircraftPositions, objType, objCallback);\r\n\t\t\t}\r\n\t\t\telse if (aircraftPositions != null)\r\n\t\t\t\tGenericService.add(aircraftPositions, objType, objCallback);\r\n\t\t}\r\n\t\treturn service;\r\n\t}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('eventHistory',eventHistory);\r\n\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name eventHistory\r\n * @restrict E\r\n * @description\r\n * Implementation of eventHistory\r\n * Initialize the Event History of report incidents (mockup view).\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */ \r\nfunction eventHistory() {\r\n\r\n\t\treturn {\r\n\t\t\trestrict: 'E',\r\n templateUrl: 'views/directives/eventHistory.tpl.html',\r\n\t\t}\r\n\t}\r\n\r\n})();\r\n\t","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('flightStatus',flightStatus);\r\n\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name flightStatus\r\n * @restrict EA\r\n * @description\r\n * Implementation of flightStatus\r\n *\r\n * Initialize the flight Status panel needs to have flight in scope\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */ \r\nfunction flightStatus(AircaftPositionsFactory) {\r\n \r\n \r\n function needsSecuritySearch(){\r\n if($scope.aircaftPositions.PreviousEU){\r\n $scope.securitySearch = false;\r\n }\r\n \r\n if($scope.aircaftPositions.PreviousCounty == \"SWITZERLAND\" \r\n ||$scope.aircaftPositions.PreviousCounty == \"NORWAY\"\r\n ||$scope.aircaftPositions.PreviousCounty == \"ICELAND\"\r\n ||$scope.aircaftPositions.PreviousCounty == \"MONTENEGRO\"){\r\n $scope.securitySearch = false;\r\n }\r\n \r\n if($scope.aircaftPositions.PreviousCounty == \"UNITED KINGDOM\" \r\n ||$scope.aircaftPositions.PreviousCounty == \"FRANCE\"){\r\n $scope.securitySearch = true;\r\n }\r\n \r\n if($scope.flight.ArrivalCountry == \"TURKEY\" \r\n ||$scope.flight.ArrivalCountry == \"EGYPT\"\r\n ||$scope.flight.ArrivalCountry == \"ISRAEL\"\r\n ||$scope.flight.ArrivalCountry == \"JORDAN\"\r\n ||$scope.flight.ArrivalCountry == \"SAUDI ARABIA\"){\r\n $scope.securitySearch = true;\r\n }\r\n \r\n }\r\n \r\n \r\n return {\r\n\t\t\trestrict: 'EA',\r\n\t\t\tterminal: true,\r\n templateUrl: 'views/directives/flightStatus.tpl.html',\r\n\t\t\tscope : false,\r\n link: function ($scope, element, attrs) {\r\n $scope.securitySearch = false;\r\n \r\n if($scope.flight && $scope.flight.FlightId){\r\n $scope.aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId($scope.flight.FlightId);\r\n }\r\n\r\n }\r\n }\r\n}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('FlightConfigCtrl',FlightConfigCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightConfigCtrl\r\n * @description \r\n * Set the ETA of the flight\r\n * @ngInject\r\n */ \r\nfunction FlightConfigCtrl($scope,$uibModalInstance,flight,FlightFactory){\r\n\r\n\t\t$scope.cancel = cancel;\r\n\t\t$scope.save = save;\r\n\t\t$scope.flightETA = new Date(flight.ETA? flight.ETA : flight.ScheduledArrival);\r\n \r\n /**\r\n * Save the new ETA\r\n * @memberof FlightConfigCtrl\r\n */\r\n\t\tfunction save() {\r\n\t\t\tif ($scope.flightETA){\r\n\t\t\t\tvar ETAdate = $scope.flightETA;\r\n\t\t\t\tvar STDdate =new Date(flight.ScheduledDeparture);\r\n\r\n var ETAtimestamp = ETAdate.getTime();\r\n\t\t\t\tvar STDtimestamp = STDdate.getTime();\r\n \r\n\t\t\t\tETAdate.setUTCFullYear(STDdate.getUTCFullYear());\r\n\t\t\t\tETAdate.setUTCMonth(STDdate.getUTCMonth());\r\n\t\t\t\tETAdate.setUTCDate(STDdate.getUTCDate());\r\n\r\n\t\t\t\t\r\n\r\n\t\t\t\tif(ETAtimestamp0;\r\n\t\t$scope.items = items.sort(function(a, b){return (new Date(a.STD).getTime())- (new Date(b.STD).getTime())});\r\n\t\t$scope.flightETA = flight.ETA? new Date(flight.ETA).getTime() : flightArrivalTime;\r\n \r\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof FlightGateCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\r\n function isConnectedFlightClose(connection){\r\n\r\n if(!connection) {\r\n return '';\r\n }\r\n\r\n var connFlightDate = new Date(connection).getTime();\r\n\r\n if ( $scope.flightETA > connFlightDate)\r\n return '';\r\n\r\n if ((connFlightDate - $scope.flightETA) < 3600001 ) { \r\n return 'bg-bisque';\r\n }\r\n\r\n if ((connFlightDate - $scope.flightETA) < 6480000) {\r\n return 'bg-cornsilk';\r\n }\r\n\r\n return '';\r\n}\r\n \r\n /**\r\n * Returns the time difference\r\n * @memberof FlightGateCtrl\r\n * @param {string} time Connection STD\r\n * @return {string} timeDifference\r\n */\r\n function TimeDifference(time){\r\n\r\n var timeString = '';\r\n var sign = '';\r\n var dayString = null;\r\n if(time){\r\n var connFlightDate = new Date(time);\r\n var ms = connFlightDate.getTime() - $scope.flightETA ; // this is a time in milliseconds\r\n if(ms<0){\r\n ms = -ms;\r\n sign = \"-\";\r\n }\r\n\r\n var days = Math.floor(ms / (24*60*60*1000));\r\n days = days<0? days+1:days;\r\n var daysms=ms % (24*60*60*1000);\r\n var hours = Math.floor((daysms)/(60*60*1000));\r\n var hoursms=ms % (60*60*1000);\r\n var minutes = Math.floor((hoursms)/(60*1000));\r\n timeString = ''+ sign + (hours > 0 ? (\"0\" + hours).substr(-2) + \":\" : '') + (\"0\" + minutes).substr(-2) + '\\'' + '';\r\n dayString = ' ' +days + 'd';\r\n }\r\n return timeString + ((days && days!=0) ? dayString : '');\r\n}\r\n\r\n /**\r\n * Checks if the data are new\r\n * @memberof FlightGateCtrl\r\n * @param {string} time timestamp\r\n * @return {boolean} IsOld\r\n */\r\n function IsOld(time){\r\n IsOld=false;\r\n if(time){\r\n var now = new Date();\r\n var timeDate = new Date(time);\r\n var diff = now.getTime() - timeDate.getTime();\r\n if(diff>3600000){\r\n IsOld=true;\r\n }\r\n }\r\n return IsOld;\r\n}\r\n \r\n /**\r\n * Apply given filters to show connectings flights\r\n * @memberof FlightGateCtrl\r\n */\r\n function applyFilter(){\r\n var newFlightgates = [];\r\n if(searchFilters.length>0){\r\n for(var i = 0 ; i= 0){\r\n newFlightgates.push(distinct_gates[i]);\r\n break;\r\n } \r\n }\r\n }\r\n }\r\n $scope.gates = newFlightgates.sort(function(a, b){return (new Date(a.STD).getTime())- (new Date(b.STD).getTime())});\r\n }\r\n \r\n /**\r\n * Add a filter\r\n * @memberof FlightGateCtrl\r\n * @param {string} searchText Search text\r\n */\r\n function addFilter (searchText){\r\n if(searchText.trim().length>0){\r\n var exists = false;\r\n for(var i = 0 ; i<$scope.filters.length ; i++){\r\n if($scope.filters[i]==searchText.toString().toUpperCase()){\r\n exists = true;\r\n break;\r\n }\r\n }\r\n if (!exists){\r\n var flight = FlightFactory.getFlightFromStorage(flightId);\r\n searchFilters.push(searchText.toString().toUpperCase());\r\n flight.FlightsFilters = searchFilters;\r\n FlightFactory.updateFlight(flight);\r\n $scope.filters = searchFilters; \r\n }\r\n $scope.searchText = \"\";\r\n applyFilter();\r\n }\r\n}\r\n /**\r\n * Remove a filter\r\n * @memberof FlightGateCtrl\r\n * @param {item} string filter\r\n */\r\n function removeFilter (item){\r\n var flight = FlightFactory.getFlightFromStorage(flightId);\r\n var index = searchFilters.indexOf(item);\r\n searchFilters.splice(index,1);\r\n flight.FlightsFilters = searchFilters;\r\n FlightFactory.updateFlight(flight);\r\n $scope.filters = searchFilters;\r\n applyFilter();\r\n}\r\n \r\n /**\r\n * Close the modal\r\n * @memberof FlightGateCtrl\r\n */\r\n function cancel() {\r\n $uibModalInstance.close($scope.gates);\r\n}\r\n\t}\r\n \r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('FlightGateFactory',FlightGateFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightGateFactory\r\n * @description \r\n * Add, Update, Delete and Get Flight Gates.\r\n * @ngInject\r\n */ \r\nfunction FlightGateFactory(GenericService){\r\n /**\r\n * Initialize the FlightGate\r\n * @memberof FlightGateFactory\r\n */\r\n\t\tfunction FlightGate() {\r\n\t\t\tthis.FlightDate = null;\r\n\t\t\tthis.Codeshares = [];\r\n\t\t\tthis.FlightNo = null;\r\n\t\t\tthis.Codeshares = [];\r\n\t\t\tthis.Departure = null;\r\n\t\t\tthis.Arrival = null;\r\n\t\t\tthis.STD = null;\r\n\t\t\tthis.STA = null;\r\n\t\t\tthis.ETD = null;\r\n\t\t\tthis.ETA = null;\r\n\t\t\tthis.STD_Diff = null;\r\n\t\t\tthis.STA_Diff = null;\r\n\t\t\tthis.STD_lcl = null;\r\n\t\t\tthis.STA_lcl = null;\r\n\t\t\tthis.ETD_lcl = null;\r\n\t\t\tthis.ETA_lcl = null;\r\n\t\t\tthis.DepGate = null;\r\n\t\t\tthis.DepStand = null;\r\n\t\t\tthis.AcType = null;\r\n\t\t\tthis.lastUpdate = null;\r\n\t\t\t//net fields used to hold values before latest update\r\n\t\t\tthis.previousUpdate = null;\r\n\t\t\tthis.previousGate = null;\r\n\t\t\tthis.previousSTD = null;\r\n\t\t\tthis.previousSTD_lcl = null;\r\n\t\t\tthis.previousSTD_Diff = null;\r\n\t\t\tthis.previousSTA = null;\r\n\t\t\tthis.previousSTA_lcl = null;\r\n\t\t\tthis.previousSTA_Diff = null;\r\n\t\t\t \r\n\t\t\t//object functions\r\n\t\t\tthis.getRoute=getRoute;\r\n\t\t\tthis.dtSTD=dtSTD\r\n\t\t\tthis.dtSTA=dtSTA;\r\n\t\t\tthis.dtETD=dtETD;\r\n\t\t\tthis.dtETA=dtETA;\r\n\t\t\tthis.dtSTD_lcl=dtSTD_lcl;\r\n\t\t\tthis.dtSTA_lcl=dtSTA_lcl;\r\n\t\t\tthis.dtETD_lcl=dtETD_lcl;\r\n\t\t\tthis.dtETA_lcl=dtETA_lcl;\r\n\t\t\tthis.dateSTD=dateSTD;\r\n\t\t\tthis.timeSTD=timeSTD;\r\n\t\t\tthis.timeSTA=timeSTA;\r\n\t\t\tthis.timeETD=timeETD;\r\n\t\t\tthis.timeETA=timeETA;\r\n\t\t\tthis.timeSTD_lcl=timeSTD_lcl;\r\n\t\t\tthis.timeSTA_lcl=timeSTA_lcl;\r\n\t\t\tthis.timeETD_lcl=timeETD_lcl;\r\n\t\t\tthis.timeETA_lcl=timeETA_lcl;\r\n\t\t\tthis.hasETD=hasETD;\r\n\t\t\tthis.hasETA=hasETA;\r\n\t\t\tthis.depDelay=depDelay;\r\n\t\t\tthis.arrDelay=arrDelay;\r\n\t\t\tthis.setUpdatedNow=setUpdatedNow;\r\n\t\t\tthis.gateChanged=gateChanged;\r\n\t\t\tthis.stdChanged=stdChanged;\r\n\t\t\tthis.staChanged=staChanged;\r\n\t\t\tthis.stdDiffChanged=stdDiffChanged;\r\n\t\t\tthis.staDiffChanged=staDiffChanged;\r\n\t\t\tthis.toString=toString;\r\n\t\t\tthis.changesToString=changesToString;\r\n\t\t\tthis.getKey=getKey;\r\n\t\t}\r\n\t\t\t \r\n\t\tvar objType = 'FlightGates';\r\n\t\tvar objCallback = FlightGate; \r\n\t\t\t\t\r\n\t\tvar service = {\r\n\t\t\tprocessUpdatedData : processUpdatedData,\r\n\t\t\tgetFromStorage : getFromStorage,\r\n\t\t\tgetAfterSTDFromStorage : getAfterSTDFromStorage,\r\n\t\t\tsetToStorage : setToStorage\r\n }\r\n\t\t\r\n\t\t\t\t//Object functions\r\n\t\tfunction getRoute() {\r\n\t\t\tif (this.Departure == null && this.Arrival == null) return '-null-';\r\n\t\t\telse return (this.Departure || '?') + '-' + (this.Arrival || '?');\r\n\t\t}\r\n \r\n /**\r\n * Transform STD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\t\t\t\t\r\n\t\tfunction dtSTD(){\r\n\t\t\treturn stringIsoToDateTime(this.STD);\r\n\t\t}\r\n \r\n /**\r\n * Transform STA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\r\n\t\tfunction dtSTA(){\r\n\t\t\treturn stringIsoToDateTime(this.STA);\r\n\t\t}\r\n \r\n /**\r\n * Transform ETD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\r\n\t\tfunction dtETD(){\r\n\t\t\treturn stringIsoToDateTime(this.ETD);\r\n\t\t}\r\n \r\n /**\r\n * Transform ETA iso string to date\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\r\n\t\tfunction dtETA(){\r\n\t\t\treturn stringIsoToDateTime(this.ETA);\r\n\t\t}\t\t\t\r\n /**\r\n * Transform local STD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\t\t\r\n\t\tfunction dtSTD_lcl(){\r\n\t\t\treturn stringIsoToDateTime(this.STD_lcl);\r\n\t\t}\r\n /**\r\n * Transform local STA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\t\r\n\t\tfunction dtSTA_lcl(){\r\n\t\t\treturn stringIsoToDateTime(this.STA_lcl);\r\n\t\t}\r\n /**\r\n * Transform local ETD iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\t\t\r\n\t\tfunction dtETD_lcl(){\r\n\t\t\treturn stringIsoToDateTime(this.ETD_lcl);\r\n\t\t}\r\n /**\r\n * Transform local ETA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\r\n\t\tfunction dtETA_lcl(){\r\n\t\t\treturn stringIsoToDateTime(this.ETA_lcl);\r\n\t\t}\t\r\n /**\r\n * Transform local ETA iso string to datetime\r\n * @memberof FlightGateFactory\r\n * @return {object} date\r\n */\r\n function dateSTD(){\r\n\t\t\treturn stringIsoToDateString(this.STD);\r\n\t\t}\r\n /**\r\n * Transform STD iso string to time string \r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeSTD(){\r\n\t\t\treturn stringIsoToTimeString(this.STD);\r\n\t\t}\r\n /**\r\n * Transform STA iso string to time string \r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeSTA(){\r\n\t\t\treturn stringIsoToTimeString(this.STA);\r\n\t\t}\r\n /**\r\n * Transform ETD iso string to time string\r\n * @memberof FlightGateFactory\r\n * @return {object} time\r\n */\r\n\t\tfunction timeETD(){\r\n\t\t\treturn stringIsoToTimeString(this.ETD);\r\n\t\t}\r\n /**\r\n * Transform ETA iso string to time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeETA(){\r\n\t\t\treturn stringIsoToTimeString(this.ETA);\r\n\t\t}\r\n /**\r\n * Transform STD iso string to local time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeSTD_lcl(){\r\n\t\t\treturn stringIsoToTimeString(this.STD_lcl);\r\n\t\t}\r\n /**\r\n * Transform local STA iso string to string time\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeSTA_lcl(){\r\n\t\t\treturn stringIsoToTimeString(this.STA_lcl);\r\n\t\t}\r\n /**\r\n * Transform local ETD iso string to time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeETD_lcl(){\r\n\t\t\treturn stringIsoToTimeString(this.ETD_lcl);\r\n\t\t}\r\n /**\r\n * Transform local ETA iso string to time\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction timeETA_lcl(){\r\n\t\t\treturn stringIsoToTimeString(this.ETA_lcl);\r\n\t\t}\r\n /**\r\n * Transform local ETA iso string to time\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction hasETD(){\r\n\t\t\tif (this.ETD && this.STD != this.ETD && this.dtSTD() < this.dtETD())\r\n\t\t\t\treturn true;\r\n\t\t\telse\r\n\t\t\t\treturn false;\r\n\t\t}\r\n /**\r\n * check if gate has ETA\r\n * @memberof FlightGateFactory\r\n * @return {boolean} hasETA\r\n */\r\n\t\tfunction hasETA(){\r\n\t\t\treturn (this.ETA && this.STA != this.ETA && this.dtSTA() < this.dtETA())\r\n\t\t}\r\n /**\r\n * check if gate has ETA\r\n * @memberof FlightGateFactory\r\n * @return {boolean} hasETA\r\n */\r\n\t\tfunction depDelay(){\r\n\t\t\tif (this.hasETD() && this.STD_Diff && this.STD_Diff > 0)\r\n\t\t\t\treturn this.STD_Diff;\r\n\t\t\telse\r\n\t\t\t\treturn null;\r\n\t\t}\r\n /**\r\n * Return arrival delay\r\n * @memberof FlightGateFactory\r\n * @return {boolean} STA_Diff\r\n */\r\n\t\tfunction arrDelay(){\r\n\t\t\tif (this.hasETA() && this.STA_Diff && this.STA_Diff > 0)\r\n\t\t\t\t\treturn this.STA_Diff;\r\n\t\t\telse\r\n\t\t\t\t\treturn null;\r\n\t\t}\r\n\r\n /**\r\n * record the current time as the lastUpdate of the object\r\n * @memberof FlightGateFactory\r\n */\r\n function setUpdatedNow(){\r\n\t\t\tthis.lastUpdate = new Date();\r\n\t\t\tif (this.DepGate == null)\r\n\t\t\t\t\tthis.DepGate='';\r\n\t\t}\r\n\r\n /**\r\n * Check if the gate has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} gateChanged\r\n */\r\n function gateChanged(){\r\n\t\t\tif (!this.previousGate)\r\n\t\t\t\treturn false;\r\n\t\t\telse\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\r\n /**\r\n * Check if the STD has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} stdChanged\r\n */\r\n function stdChanged(){\r\n\t\t\tif (!this.previousSTD)\r\n\t\t\t\treturn false;\r\n\t\t\telse\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\r\n /**\r\n * Check if the STA has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} staChanged\r\n */\r\n function staChanged(){\r\n\t\t\tif (!this.previousSTA)\r\n\t\t\t\treturn false;\r\n\t\t\telse\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\r\n /**\r\n * Check if the STD diff has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} stdDiffChanged\r\n */\r\n function stdDiffChanged(){\r\n\t\t\tif (!this.previousSTD_Diff)\r\n\t\t\t\treturn false;\r\n\t\t\telse\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\r\n /**\r\n * Check if the STA diff has changed since the last update\r\n * @memberof FlightGateFactory\r\n * @return {boolean} staDiffChanged\r\n */\r\n function staDiffChanged(){\r\n\t\t\tif (!this.previousSTA_Diff)\r\n\t\t\t\treturn false;\r\n\t\t\telse\r\n\t\t\t\treturn true;\r\n\t\t}\r\n \r\n /**\r\n * Print the flight gate info\r\n * @memberof FlightGateFactory\r\n * @return {string} toSting\r\n */ \r\n\t\tfunction toString(){\r\n\t\t\tvar s=this.dateSTD() + ' ' + this.FlightNo;\r\n\t\t\ts+=' ' + this.Departure + '-' + this.Arrival;\r\n\t\t\ts+=' ' + (this.hasETD() ? 'ETD'+this.timeETD_lcl()+(this.depDelay() ? '[+'+this.depDelay()+'\\']' : '') : 'STD'+this.timeSTD_lcl());\r\n\t\t\ts+='->' + (this.hasETA() ? 'ETA'+this.timeETA_lcl() + '[' + (this.STA_Diff>0 ? '+' : '-')+this.STA_Diff + '\\']' : 'STA'+this.timeSTA_lcl());\r\n\t\t\ts+=(this.DepGate ? ' Gate: ' + this.DepGate : '');\r\n\t\t\treturn s;\r\n\t\t}\r\n \r\n /**\r\n * Show all the changes of the flight gates\r\n * @memberof FlightGateFactory\r\n * @return {string} toSting\r\n */ \r\n\t\tfunction changesToString(){\r\n\t\t\tvar s='';\r\n\t\t\tif (this.stdChanged())\r\n\t\t\t\t\ts+='STD: ' + stringIsoToTimeString(this.previousSTD) + ' -> ' + this.timeSTD();\r\n\t\t\tif (self.stdDiffChanged())\r\n\t\t\t\t\ts+=(s=='' ? '' : ', ')+'departure delay: '+this.previousSTD_Diff + ' -> ' + this.STD_Diff;\r\n\t\t\tif (self.staChanged())\r\n\t\t\t\t\ts+=(s=='' ? '' : ', ')+'STA: ' + stringIsoToTimeString(this.previousSTA) + ' -> ' + this.timeSTA();\r\n\t\t\tif (self.staDiffChanged())\r\n\t\t\t\t\ts+=(s=='' ? '' : ', ')+'arrival delay: '+this.previousSTA_Diff + ' -> ' + this.STA_Diff;\r\n\t\t\tif (self.gateChanged())\r\n\t\t\t\t\ts+=(s=='' ? '' : ', ')+' gate: '+this.previousGate + ' -> ' + this.DepGate;\r\n\t\t\treturn s;\r\n\t\t}\r\n\r\n /**\r\n * returns a string with all the fields uniquely defining a flight, concatenated\r\n * @memberof FlightGateFactory\r\n * @return {string} key\r\n */ \r\n function getKey(){\r\n\t\t\tvar s = this.FlightDate + '|' + this.FlightNo + '|' + this.Departure + '-' + this.Arrival;\r\n\t\t\treturn s;\r\n\t\t}\r\n\t\t\r\n /**\r\n * Transform iso datetime string to date time Object\r\n * @memberof FlightGateFactory\r\n * @return {Object} DateTime\r\n */\r\n function stringIsoToDateTime(str){\r\n\t\t\tvar dt=null;\r\n\t\t\ttry{\r\n\t\t\t\tif (str){\r\n\t\t\t\t\t//replace T in order to avoid browser converting datetime to browser's timezone\r\n\t\t\t\t\t//eg 2016-05-17T23:04:00 would be converted to Wed May 18 2016 02:04:00 GMT+0300 (GTB Daylight Time) when we want it to be Tue May 17 2016 23:04:00 GMT+0300 (GTB Daylight Time)\r\n\t\t\t\t\tstr = str.replace('T', ' ');\r\n\t\t\t\t\tdt=new Date(str);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcatch(e){}\r\n\t\t\treturn dt;\r\n\t\t}\r\n \r\n /**\r\n * Transform iso datetime string to date string\r\n * @memberof FlightGateFactory\r\n * @return {string} date\r\n */\r\n\t\tfunction stringIsoToDateString(str){\r\n\t\t\tvar dt= stringIsoToDateTime(str);\r\n\t\t\tvar s=null;\r\n\t\t\tif (dt){\r\n\t\t\t\tvar year=dt.getFullYear();\r\n\t\t\t\tvar month=dt.getMonth()+1;\r\n\t\t\t\tvar day=dt.getDate();\r\n\t\t\t\ts=(day < 10 ? '0' : '')+day+'.'+(month < 10 ? '0' : '')+month+'.'+year;\r\n\t\t\t}\r\n\t\t\treturn s;\r\n\t\t}\r\n \r\n /**\r\n * Transform iso datetime string to time string\r\n * @memberof FlightGateFactory\r\n * @return {string} time\r\n */\r\n\t\tfunction stringIsoToTimeString(str){\r\n\t\t\tvar dt=stringIsoToDateTime(str);\r\n\t\t\tvar s=null;\r\n\t\t\tif (dt){\r\n\t\t\t\tvar hour=dt.getHours();\r\n\t\t\t\tvar min=dt.getMinutes();\r\n\t\t\t\ts=(hour < 10 ? '0' : '')+hour+':'+(min<10 ? '0' : '')+min+'';\r\n\t\t\t}\r\n\t\t\treturn s;\r\n\t\t}\r\n\t\t\r\n /**\r\n * Process updated list of fligths 'gates' and store them.Before storing them, we need to identify changes in Gates and in ETD/ETA to notify customers when required. \r\n * @memberof FlightGateFactory\r\n */\r\n\t\tfunction processUpdatedData(data){\r\n\t\t\t//Update List\r\n\t\t\tvar list= fromObjectList(data);\r\n\t\t\t\r\n\t\t\t//Original List\r\n\t\t\tvar listPrevious=getFromStorage();\r\n\t\t\t\r\n\t\t\t//Search each \"new\" flight in the new list, and check if it has been modified since last update\r\n\t\t\tif (list && list.length > 0)\r\n\t\t\t{\r\n\t\t\t\tvar flight,flightPrevious, hasChanged;\r\n\t\t\t\tvar previousLength=listPrevious.length;\r\n\t\t\t\tfor(var i=0;i0){\r\n\t\t\t\t\t\tfor(var p=0;p=date || (dateETD !=null && dateETD.getTime()>=date )) && dep==flightgates[i].Departure && \r\n\t\t\t\t\t//check only for 2 days later\r\n\t\t\t\t\t(dateSTD.getTime()<=(date+172800000))) {\r\n\t\t\t\t\tnewFlightgates.push(flightgates[i]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn newFlightgates;\r\n\t\t}\r\n \r\n /**\r\n * Set flightgates from storage\r\n * @memberof FlightGateFactory\r\n * @param {array} data\r\n */\t\t\t\r\n\t\tfunction setToStorage(data){\r\n\t\t\tGenericService.saveAll(data,objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Set flightgates from storage\r\n * @memberof FlightGateFactory\r\n * @param {array} data\r\n */\t\r\n\t\tfunction fromObjectList( objList ) {\r\n\t\t\tif (objList==null)\r\n\t\t\t\treturn [];\r\n\r\n\t\t\tvar arrayLength = objList.length;\r\n\t\t\tvar result = [];\r\n\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tvar item = new FlightGate();\r\n\t\t\t\tangular.extend(item, objList[i]);\r\n\r\n\t\t\t\tresult.push(item);\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\t\t}\r\n\r\n\treturn service;\t\t\t\t\t\t\t\t\t\t\t \r\n\t}\r\n\r\n })(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('FlightInfoCtrl', FlightInfoCtrl)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightInfoCtrl\r\n * @description \r\n * Shows the flight informations\r\n * @ngInject\r\n */\r\n function FlightInfoCtrl($scope, $location, $routeParams, $uibModal,barOptions\r\n , FlightFactory, PaxInfoFactory, MessageFactory, $anchorScroll, CrewCallFactory, PreviousDutyFactory, UserFactory,\r\n AircaftPositionsFactory,AimsCrewMemosFactory,showCatIIApprachAcTypes,showGroundInfoAcTypes, FlightCheckInsFactory) {\r\n\r\n\r\n var flightId = $routeParams.flightId;\r\n var flight = FlightFactory.getFlightFromTotalFlights(flightId);\r\n\r\n \r\n\r\n $scope.user = UserFactory.getUser();\r\n $scope.flightId = flightId;\r\n $scope.shownSideMenu = false;\r\n $scope.sideMenuItems = [];\r\n $scope.showSidePanel = showSidePanel;\r\n $scope.hideSidePanel = hideSidePanel;\r\n $scope.goToPanel = goToPanel;\r\n\r\n function hideSidePanel() {\r\n $scope.shownSideMenu = false;\r\n }\r\n\r\n\r\n function goToPanel(id) {\r\n $location.hash(id);\r\n $anchorScroll();\r\n hideSidePanel();\r\n };\r\n\r\n function showSidePanel() {\r\n $scope.sideMenuItems = [];\r\n $('.panel-heading .title').each(function () {\r\n var menuItem = {};\r\n menuItem.id = $(this).attr(\"id\");\r\n menuItem.title = $(this).html();\r\n menuItem.icon = $(this).data('icon');\r\n $scope.sideMenuItems.push(menuItem);\r\n })\r\n $scope.shownSideMenu = true;\r\n }\r\n \r\n if (!flight) {\r\n // go to dashboard\r\n $location.path(\"/\");\r\n } else {\r\n // (1312896)flightId\r\n\r\n applyPhoneNumber();\r\n applyPreviousDuty();\r\n applyCrewCheckInStatus();\r\n\r\n $scope.flightCrewPreviousDuty = flight.crew.filter(x => x.PreviousDuty && x.PreviousDuty.isDifferent && (x.position == \"CP\" || x.position == \"FO\") && !x.isDHC).length;\r\n $scope.cabinCrewPreviousDuty = flight.crew.filter(x => x.PreviousDuty && x.PreviousDuty.isDifferent && (x.position == \"SA\" || x.position == \"FA\") && !x.isDHC).length;\r\n $scope.dhcCrewPreviousDuty = flight.crew.filter(x => x.PreviousDuty && x.PreviousDuty.isDifferent && x.isDHC).length;\r\n $scope.hasPreviousDuties = $scope.flightCrewPreviousDuty + $scope.cabinCrewPreviousDuty + $scope.dhcCrewPreviousDuty;\r\n\r\n var paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flightId);\r\n var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId(flight.FlightId);\r\n\r\n $scope.dayOfFlight = new Date(flight.FlightDate).getDate();\r\n $scope.showCatIIApprachSection = showCatIIApprachAcTypes.includes(flight.AcType);\r\n $scope.showGroundInfoSection = showGroundInfoAcTypes.includes(flight.AcType);\r\n\r\n $scope.aimsCrewMemos = AimsCrewMemosFactory.getAimsCrewMemosByDate(flight.FlightDate);\r\n\r\n\r\n //Initialized scope variables\r\n $scope.state = 'flight'\r\n $scope.isEnabled = false;\r\n $scope.flight = flight;\r\n $scope.aircaftPositions = aircaftPositions;\r\n $scope.isPanelOpen = true;\r\n $scope.IsProvisional = true;\r\n $scope.paxInfo = paxInfo;\r\n $scope.showConnFlights = true;\r\n $scope.flightZones = RenderFlightZones(flight.Zones);\r\n\r\n //Initialize Zones\r\n function onlyUnique(value, index, self) {\r\n return self.indexOf(value) === index;\r\n }\r\n function RenderFlightZones(zones) {\r\n var flightZones = [];\r\n\r\n if (zones != null) {\r\n\r\n var zoneTitles = zones.map(function (item) {\r\n return item.Title;\r\n });\r\n var uniqueZones = zoneTitles.filter(onlyUnique);\r\n // //or\r\n // var uniqueZones2 = Array.from(new Set(zoneTitles));\r\n\r\n uniqueZones.forEach(function (element) {\r\n\r\n var getZoneCounter = zoneTitles.filter(function (item) {\r\n return item == element;\r\n });\r\n if (getZoneCounter.length > 1) {\r\n flightZones.push({ Title: element.Title, Class: null })\r\n } else {\r\n var zone = zones.filter(function (item) {\r\n return item.Title == element;\r\n });\r\n flightZones.push(zone[0]);\r\n }\r\n });\r\n }\r\n\r\n return flightZones;\r\n }\r\n\r\n\r\n\r\n var flightArrivalTime = new Date(flight.ScheduledArrival).getTime();\r\n\r\n //Initialize Messages\r\n $scope.messages = MessageFactory.getMessagesFromIds(flight.messages);\r\n var messages = $scope.messages;\r\n $scope.openMessage = openMessage;\r\n\r\n //Initialize CSS classes\r\n $scope.getTextClass = getTextClass();\r\n $scope.getTopClass = getTopClass();\r\n $scope.getBottomClass = getBottomClass();\r\n $scope.hasIcon = hasIcon();\r\n\r\n //Charts\r\n $scope.crewChart = generateCrewChart(flight);\r\n if (paxInfo) {\r\n $scope.cStat = (paxInfo.PaxTotalC / paxInfo.ConfigurationC) * 100;\r\n $scope.yStat = (paxInfo.PaxTotalY / paxInfo.ConfigurationY) * 100;\r\n\r\n var listSentTimestamp = new Date(paxInfo.LastRun).getTime();\r\n var DepartureTimestamp = new Date(flight.ScheduledDeparture).getTime();\r\n //20 minutes before takeoff\r\n if (DepartureTimestamp - listSentTimestamp <= 1200000) {\r\n $scope.IsProvisional = false;\r\n }\r\n\r\n }\r\n\r\n $scope.isConnectedFlightClose = isConnectedFlightClose;\r\n $scope.flightETA = $scope.flight.ETA ? \r\n moment( flight.ETA ).valueOf(): flightArrivalTime;\r\n\r\n $scope.TimeDifference = TimeDifference;\r\n $scope.openFlightConfig = openFlightConfig;\r\n $scope.togglePanel = togglePanel;\r\n $scope.toggleViewMode = toggleViewMode;\r\n $scope.IsOld = IsOld;\r\n $scope.openGates = openGates;\r\n\r\n\r\n\r\n\r\n /**\r\n * Open modal to see information for the selected message\r\n * @memberof FlightInfoCtrl\r\n * @param {object} message A message object\r\n */\r\n function openMessage(message) {\r\n\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgMessage.html',\r\n controller: 'MessageModalCtrl',\r\n size: 'lg',\r\n keyboard: false,\r\n backdrop: \"static\",\r\n resolve: {\r\n message: function () {\r\n return message;\r\n }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function () {\r\n if (message.ReadDt == null) {\r\n MessageFactory.markReaden(message.Id);\r\n message.ReadDt = new Date();\r\n }\r\n })\r\n }\r\n /**\r\n * Return the text ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\r\n function getTextClass() {\r\n var classname = \"\";\r\n if (flight.LineStatus === 'na')\r\n classname = \"text-gray\";\r\n else if (flight.LineStatus === 'pending')\r\n classname = \"text-blue\";\r\n else if (flight.LineStatus === 'pendingoverdue')\r\n classname = \"text-blue\";\r\n else if (\r\n (flight.LineStatus === 'draft') ||\r\n (flight.LineStatus === 'draftotheruser')\r\n ) {\r\n classname = \"text-orange\";\r\n } else if (\r\n (flight.LineStatus === 'completed') ||\r\n (flight.LineStatus === 'completedotheruser')\r\n ) {\r\n classname = \"text-purple\";\r\n } else if (\r\n (flight.LineStatus === 'stored') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synched') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n classname = \"text-green\";\r\n }\r\n return classname;\r\n }\r\n /**\r\n * Return the panel border ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\r\n function getTopClass() {\r\n var classname = \"\";\r\n if (flight.LineStatus === 'na')\r\n classname = \"border-top-gray\";\r\n else if (flight.LineStatus === 'pending')\r\n classname = \"border-top-blue\";\r\n else if (flight.LineStatus === 'pendingoverdue')\r\n classname = \"border-top-blue\";\r\n else if (\r\n (flight.LineStatus === 'draft') ||\r\n (flight.LineStatus === 'draftotheruser')\r\n ) {\r\n classname = \"border-top-orange\";\r\n } else if (\r\n (flight.LineStatus === 'completed') ||\r\n (flight.LineStatus === 'completedotheruser')\r\n ) {\r\n classname = \"border-top-purple\";\r\n } else if (\r\n (flight.LineStatus === 'stored') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synched') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n classname = \"border-top-green\";\r\n }\r\n return classname;\r\n }\r\n /**\r\n * Return the panel border ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\r\n function getBottomClass() {\r\n var classname = \"\";\r\n if (flight.LineStatus === 'na')\r\n classname = \"border-bottom-gray\";\r\n else if (flight.LineStatus === 'pending')\r\n classname = \"border-bottom-blue\";\r\n else if (flight.LineStatus === 'pendingoverdue')\r\n classname = \"border-bottom-blue\";\r\n else if (\r\n (flight.LineStatus === 'draft') ||\r\n (flight.LineStatus === 'draftotheruser')\r\n ) {\r\n classname = \"border-bottom-orange\";\r\n } else if (\r\n (flight.LineStatus === 'completed') ||\r\n (flight.LineStatus === 'completedotheruser')\r\n ) {\r\n classname = \"border-bottom-purple\";\r\n } else if (\r\n (flight.LineStatus === 'stored') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synched') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n classname = \"border-bottom-green\";\r\n }\r\n return classname;\r\n }\r\n /**\r\n * If report from another user exists, show icon\r\n * @memberof FlightInfoCtrl\r\n * @returns {boolean} hasIcon\r\n */\r\n function hasIcon() {\r\n var hasIcon = false;\r\n if (\r\n (flight.LineStatus === 'draftotheruser') ||\r\n (flight.LineStatus === 'completedotheruser') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n hasIcon = true;\r\n }\r\n return hasIcon;\r\n }\r\n /**\r\n * Returns the crew Chart\r\n * @memberof FlightInfoCtrl\r\n * @param {object} flight The flight object\r\n * @return {object} crewChart\r\n */\r\n function generateCrewChart(flight) {\r\n\r\n var cp = 0;\r\n var fo = 0;\r\n var sa = 0;\r\n var fa = 0;\r\n\r\n var dhcCp = 0;\r\n var dhcFo = 0;\r\n var dhcSa = 0;\r\n var dhcFa = 0;\r\n\r\n if (flight.crew) {\r\n for (var i = 0; i < flight.crew.length; i++) {\r\n if (flight.crew[i].isDHC) {\r\n switch (flight.crew[i].position) {\r\n case \"CP\":\r\n dhcCp++;\r\n break;\r\n case \"FO\":\r\n dhcFo++;\r\n break;\r\n case \"SA\":\r\n dhcSa++;\r\n break;\r\n case \"FA\":\r\n dhcFa++;\r\n break;\r\n }\r\n } else {\r\n switch (flight.crew[i].position) {\r\n case \"CP\":\r\n cp++;\r\n break;\r\n case \"FO\":\r\n fo++;\r\n break;\r\n case \"SA\":\r\n sa++;\r\n break;\r\n case \"FA\":\r\n fa++;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n var crewData = {\r\n labels: [\"CP\", \"FO\", \"SA\", \"FA\"],\r\n datasets: [{\r\n label: \"Crew\",\r\n fillColor: \"rgba(33,150,243,0.5)\",\r\n strokeColor: \"rgba(33,150,243,0.8)\",\r\n highlightFill: \"rgba(33,150,243,0.75)\",\r\n highlightStroke: \"rgba(33,150,243,1)\",\r\n data: [cp, fo, sa, fa]\r\n }, {\r\n label: \"DHC\",\r\n fillColor: \"rgba(99,181,246,0.5)\",\r\n strokeColor: \"rgba(99,181,246,0.8)\",\r\n highlightFill: \"rgba(99,181,246,0.75)\",\r\n highlightStroke: \"rgba(99,181,246,1)\",\r\n data: [dhcCp, dhcFo, dhcSa, dhcFa]\r\n }]\r\n };\r\n\r\n var crewChart = {\r\n \"data\": crewData,\r\n \"options\": barOptions\r\n };\r\n\r\n return crewChart;\r\n }\r\n /**\r\n * toggle Panel\r\n * @memberof FlightInfoCtrl\r\n * @param {number} panelId\r\n */\r\n function togglePanel(panelId) {\r\n $('#' + panelId).toggle();\r\n if (panelId == \"info-panel\")\r\n $scope.isPanelOpen = !$scope.isPanelOpen;\r\n }\r\n /**\r\n * toggle View Mode\r\n * @memberof FlightInfoCtrl\r\n * @param {string} elem\r\n * @param {string} className \r\n */\r\n function toggleViewMode(elem, className) {\r\n $('body').find('div#' + elem + ' > div').not('.tip').hide(\"slow\");\r\n $('body').find('div#' + elem + ' div.' + className).not('.tip').show(\"slow\");\r\n }\r\n /**\r\n * Checks if the data are new\r\n * @memberof FlightInfoCtrl\r\n * @param {string} time timestamp\r\n * @return {boolean} IsOld\r\n */\r\n function IsOld(time) {\r\n IsOld = false;\r\n if (time) {\r\n var now = new Date();\r\n var timeDate = new Date(time);\r\n var diff = now.getTime() - timeDate.getTime();\r\n if (diff > 3600000) {\r\n IsOld = true;\r\n }\r\n }\r\n return IsOld;\r\n }\r\n /**\r\n * Open modal to see information for gates and connections\r\n * @memberof FlightInfoCtrl\r\n */\r\n function openGates() {\r\n\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgFlightGates.html',\r\n controller: 'FlightGateCtrl',\r\n size: 'lg',\r\n resolve: {\r\n flight: function () {\r\n return $scope.flight;\r\n }\r\n }\r\n });\r\n modalInstance.result.then(function (selectedItem) {\r\n $scope.gates = selectedItem;\r\n });\r\n }\r\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof FlightInfoCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\r\n function isConnectedFlightClose(connection) {\r\n\r\n if (!connection) {\r\n return '';\r\n }\r\n\r\n var connFlightDate = new Date(connection.STD).getTime();\r\n\r\n if ($scope.flightETA > connFlightDate)\r\n return '';\r\n\r\n\r\n\r\n if ((connFlightDate - $scope.flightETA) <= (connection.MCT * 60000)) {\r\n return 'bg-bisque';\r\n }\r\n\r\n if ((connFlightDate - $scope.flightETA) <= ((connection.MCT * 1.2) * 60000)) {\r\n return 'bg-cornsilk';\r\n }\r\n return '';\r\n }\r\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof FlightInfoCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\r\n function TimeDifference(time) {\r\n\r\n var timeString = '';\r\n var sign = '';\r\n var dayString = null;\r\n if (time) {\r\n var connFlightDate = new Date(time);\r\n var ms = connFlightDate.getTime() - $scope.flightETA; // this is a time in milliseconds\r\n if (ms < 0) {\r\n ms = -ms;\r\n sign = \"-\";\r\n }\r\n\r\n var days = Math.floor(ms / (24 * 60 * 60 * 1000));\r\n days = days < 0 ? days + 1 : days;\r\n var daysms = ms % (24 * 60 * 60 * 1000);\r\n var hours = Math.floor((daysms) / (60 * 60 * 1000));\r\n var hoursms = ms % (60 * 60 * 1000);\r\n var minutes = Math.floor((hoursms) / (60 * 1000));\r\n timeString = '' + sign + (hours > 0 ? (\"0\" + hours).substr(-2) + \":\" : '') + (\"0\" + minutes).substr(-2) + '\\'' + '';\r\n dayString = ' ' + days + 'd';\r\n }\r\n return timeString + ((days && days != 0) ? dayString : '');\r\n }\r\n /**\r\n * Open Flight config modal\r\n * @memberof FlightInfoCtrl\r\n */\r\n function openFlightConfig() {\r\n\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgFlightConfig.html',\r\n controller: 'FlightConfigCtrl',\r\n size: 'md',\r\n resolve: {\r\n flight: function () {\r\n return $scope.flight;\r\n }\r\n }\r\n });\r\n modalInstance.result.then(function (selectedItem) {\r\n $scope.flightETA = new Date(selectedItem.ETA).getTime();\r\n\r\n $scope.flight = selectedItem;\r\n });\r\n }\r\n /**\r\n * Open Flight config modal\r\n * @memberof FlightInfoCtrl\r\n */\r\n function generateDistinctGates(gates, FlightsFilters) {\r\n var distinct_gates = [];\r\n\r\n for (var i = 0; i < gates.length; i++) {\r\n for (var j = 0; j < FlightsFilters.length; j++) {\r\n var row = gates[i].FlightNo + \",\" + gates[i].Codeshares.toString();\r\n if (row.indexOf(FlightsFilters[j].toString()) >= 0) {\r\n var distinct_gate = {\r\n FlightNo: gates[i].FlightNo,\r\n Gate: gates[i].DepGate,\r\n Arr: gates[i].Arrival,\r\n STD_lcl: gates[i].STD_lcl,\r\n STD: gates[i].STD,\r\n pax: null,\r\n Codeshares: gates[i].Codeshares\r\n }\r\n distinct_gates.push(distinct_gate);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return distinct_gates;\r\n }\r\n\r\n \r\n function applyPhoneNumber(){\r\n var crewPhoneNumbers = CrewCallFactory.getFlightCrewCallsFromStorage(flightId);\r\n flight.crew.forEach(function(user){\r\n var phoneNumberInfo = crewPhoneNumbers.find(x => x.CrewId == user.id);\r\n if(phoneNumberInfo){\r\n user.PhoneNumber = phoneNumberInfo.PhoneNumber;\r\n }\r\n else{\r\n user.PhoneNumber = null;\r\n }\r\n });\r\n }\r\n \r\n function applyPreviousDuty(){\r\n var previousDuties = PreviousDutyFactory.getFlightPreviousDutiesFromStorage(flightId);\r\n var dutyDate = moment(flight.ScheduledDeparture).startOf('day');\r\n flight.crew.forEach(function(user){\r\n\r\n var previousDutyInfo = previousDuties.find(x => x.CrewId == user.id);\r\n if(previousDutyInfo){\r\n user.PreviousDuty = previousDutyInfo.PreviousDuty;\r\n }\r\n else{\r\n user.PreviousDuty = null;\r\n }\r\n\r\n if(user.PreviousDuty && user.PreviousDuty.isFlight){\r\n var arrivalDate = user.PreviousDuty.ATA;\r\n if(!arrivalDate) arrivalDate = user.PreviousDuty.ETA;\r\n if(!arrivalDate) arrivalDate = user.PreviousDuty.STA;\r\n\r\n user.PreviousDuty.showArrivalDate = !moment(arrivalDate).startOf('day').isSame(dutyDate);\r\n\r\n var departureDate = user.PreviousDuty.ATA;\r\n if(!departureDate) departureDate = user.PreviousDuty.ETA;\r\n if(!departureDate) departureDate = user.PreviousDuty.STA;\r\n\r\n user.PreviousDuty.showDepartureDate = !moment(departureDate).startOf('day').isSame(dutyDate);\r\n }\r\n if(user.PreviousDuty && !user.PreviousDuty.isFlight){\r\n user.PreviousDuty.showDate = !moment(user.PreviousDuty.GroundDutyDate).startOf('day').isSame(dutyDate);\r\n }\r\n });\r\n }\r\n\r\n function applyCrewCheckInStatus(){\r\n var crewCheckInStatuses = FlightCheckInsFactory.getFlightCrewCheckInFromStorage(flightId);\r\n\r\n flight.crew.forEach(function(user){\r\n var statuses = crewCheckInStatuses.find(x => x.CrewId == user.id);\r\n if(statuses){\r\n user.CheckIn = statuses.CheckIn;\r\n user.WillBeThereAt = statuses.WillBeThereAt;\r\n }\r\n else{\r\n user.CheckIn = null;\r\n user.WillBeThereAt = null;\r\n }\r\n });\r\n }\r\n\r\n }\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('groundInfo',groundInfo);\r\n\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name groundInfo\r\n * @restrict EA\r\n * @description\r\n * Implementation of groundInfo\r\n *\r\n * Initialize the ground information (Contacts,Hotels)\r\n * @attr {String} station The name of the station to get the ground information.\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */ \r\nfunction groundInfo(AirportContactFactory,AirportHotelFactory) {\r\n\r\n /**\r\n * Calculates distinct HotelTypes (used for filtering results)\r\n * @memberof AirportHotelCtrl\r\n * @param {array} All the airport Hotels (object which containts Hotels property)\r\n * @return {array} The distinct HotelTypes as an array of strings\r\n */\r\n function findDistinctHotelTypes(items){\r\n var unique = {};\r\n var distinct = [];\r\n for( var i in items ){\r\n if( items[i].Name && typeof(unique[items[i].Name]) == \"undefined\"){\r\n distinct.push(items[i].Name);\r\n }\r\n unique[items[i].Name] = 0;\r\n }\r\n return distinct;\r\n }\r\n\r\n /**\r\n * Used to properly display some Hotel Types, eg nulls\r\n * @memberof AirportHotelCtrl\r\n * @param {string} The Hotel type to examine and \"fix\"\r\n * @return {string} The \"fixed\" string for the given Hotel type (maybe the same as the input value if no fix is needed)\r\n */\r\n function printHotelType(HotelType){\r\n if (!HotelType || HotelType == ''){\r\n console.log(HotelType);\r\n HotelType = '-no Hotel type-';\r\n }\r\n \r\n return HotelType;\r\n }\r\n \r\n /**\r\n * Calculates distinct ContactTypes (used for filtering results)\r\n * @memberof AirportContactCtrl\r\n * @param {array} All the airport contacts (object which containts Contacts property)\r\n * @return {array} The distinct ContactTypes as an array of strings\r\n */\r\n function findDistinctContactTypes(items){\r\n var unique = {};\r\n var distinct = [];\r\n for( var i in items ){\r\n if(items[i].ContactType && typeof(unique[items[i].ContactType]) == \"undefined\"){\r\n distinct.push(items[i].ContactType);\r\n }\r\n unique[items[i].ContactType] = 0;\r\n }\r\n return distinct;\r\n }\r\n \r\n /**\r\n * Used to properly display some Contact Types, eg nulls\r\n * @memberof AirportContactCtrl\r\n * @param {string} The contact type to examine and \"fix\"\r\n * @return {string} The \"fixed\" string for the given contact type (maybe the same as the input value if no fix is needed)\r\n */\r\n function printContactType(contactType){\r\n if (!contactType || contactType == '')\r\n return '-no contact type-';\r\n return contactType;\r\n }\r\n \r\n\t\r\n\t\treturn {\r\n\t\t\trestrict: 'EA',\r\n\t\t\tterminal: true,\r\n templateUrl: 'views/directives/groundInfo.tpl.html',\r\n\t\t\tscope : true,\r\n link: function ($scope, element, attrs) {\r\n var stations = attrs.stations? attrs.stations.split(\",\") : [];\r\n $scope.stationsInfo = []\r\n $scope.filterHotelType = '';\r\n $scope.filterContactType = '';\r\n \r\n //scope methods\r\n $scope.printHotelType = printHotelType;\r\n $scope.printContactType = printContactType;\r\n $scope.showInfo = showInfo;\r\n \r\n angular.forEach(stations,function(station){\r\n var stationInfo = {};\r\n \r\n var flightDate = $scope.flight && $scope.flight.FlightDate ? $scope.flight.FlightDate : null;\r\n var contactInfo = AirportContactFactory.getAirportContacts(station);\r\n stationInfo.Contacts = contactInfo ? contactInfo.Contacts : [];\r\n stationInfo.ContactTypes = findDistinctContactTypes(stationInfo.Contacts)\r\n \r\n var hotelInfo = AirportHotelFactory.getAirportHotels(station, flightDate);\r\n stationInfo.Hotels = hotelInfo ? hotelInfo.Hotels : [];\r\n stationInfo.HotelTypes = findDistinctHotelTypes(stationInfo.Hotels);\r\n \r\n stationInfo.ActiveHotels = false;\r\n stationInfo.ActiveContacts = false;\r\n stationInfo.ActiveGeneralInfo= false;\r\n \r\n stationInfo.Name = station;\r\n if(stationInfo.Hotels.length>0 || stationInfo.Contacts.length>0){\r\n $scope.stationsInfo.push(stationInfo);\r\n }\r\n \r\n });\r\n \r\n var oldViewStation = '';\r\n var oldViewType = '';\r\n \r\n function showInfo(station,type){\r\n \r\n angular.forEach($scope.stationsInfo,function(stationInfo){\r\n if(stationInfo.Name == station.Name){\r\n if(type=='Hotels'){\r\n stationInfo.ActiveHotels = !stationInfo.ActiveHotels;\r\n stationInfo.ActiveContacts = false;\r\n stationInfo.ActiveGeneralInfo=false;\r\n }else if(type=='Contacts'){\r\n stationInfo.ActiveContacts = !stationInfo.ActiveContacts;\r\n stationInfo.ActiveHotels = false;\r\n stationInfo.ActiveGeneralInfo=false;\r\n }else if(type=='General'){\r\n stationInfo.ActiveGeneralInfo=!stationInfo.ActiveGeneralInfo;\r\n stationInfo.ActiveHotels = false;\r\n stationInfo.ActiveContacts = false;\r\n }\r\n }else{\r\n stationInfo.ActiveHotels = false;\r\n stationInfo.ActiveContacts = false;\r\n stationInfo.ActiveGeneralInfo=false;\r\n }\r\n })\r\n \r\n }\r\n\t\t}\r\n\t}\r\n}\r\n})();\r\n\t","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('GroundServicesFactory', GroundServicesFactory);\r\n /**\r\n * @memberOf PilotReports\r\n * @ngdoc factory\r\n * @name GroundServicesFactory\r\n * @description\r\n * Get Ground Services\r\n * @gnInject\r\n */\r\n\r\n function GroundServicesFactory(GenericService) {\r\n /**\r\n * Initialize the GroundServices\r\n * @memberof GroundServicesFactory\r\n */\r\n function GroundService() {\r\n this.Station = null;\r\n }\r\n\r\n var objType = 'groundServices';\r\n var objCallBack = GroundService;\r\n\r\n var service = {\r\n fromObjectList: fromObjectList,\r\n getGroundServicesFromStorage: getGroundServicesFromStorage,\r\n setGroundServicesToStorage: setGroundServicesToStorage,\r\n clearGroundServicesFromStorage: clearGroundServicesFromStorage,\r\n getGroundServicesByStation: getGroundServicesByStation\r\n };\r\n\r\n /**\r\n * Extend an array of Objects from the default GroundService Object\r\n * @memberof GroundServicesFactory\r\n * @param {Array} objList an Array Of ground Services\r\n * @returns {Array} groundServices\r\n */\r\n function fromObjectList(objList) {\r\n return GenericService.fromObjectList(objList, objCallBack);\r\n }\r\n\r\n /**\r\n * Get ground services from local storage\r\n * @memberof GroundServicesFactory\r\n * @returns {Array} groundServices \r\n */\r\n function getGroundServicesFromStorage() {\r\n return GenericService.list(objType, objCallBack);\r\n }\r\n\r\n /**\r\n * Save ground services to storage\r\n * @memberof GroundServicesFactory\r\n * @param {Array} List of ground services\r\n */\r\n function setGroundServicesToStorage(groundServices) {\r\n if(groundServices){\r\n for (var i = 0; i < groundServices.length; i++) {\r\n for (var j = 0; j < groundServices[i].Services.length; j++){\r\n // isDefault could be null\r\n if (groundServices[i].Services[j].IsDefault)\r\n groundServices[i].Services[j].Used = 1;\r\n else\r\n groundServices[i].Services[j].Used = 0;\r\n }\r\n }\r\n GenericService.saveAll(groundServices, objType, objCallBack);\r\n }\r\n }\r\n\r\n /**\r\n * Remove the ground services from the local storage\r\n * @memberof GroundServicesFactory\r\n */\r\n function clearGroundServicesFromStorage() {\r\n GenericService.removeAll(objType, objCallBack);\r\n }\r\n\r\n\r\n /**\r\n * Get Ground Services of a current station from the local storage\r\n * @memberof GroundServicesFactory\r\n * @param {number} station \r\n * @return {object} GroundServices \r\n */\r\n function getGroundServicesByStation(station) {\r\n \r\n var objects = getGroundServicesFromStorage();\r\n if (objects == null)\r\n return [];\r\n\r\n var results = [];\r\n\r\n var arrayLength = objects.length;\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (objects[i].Station == station) {\r\n results = objects[i].Services;\r\n }\r\n }\r\n return results;\r\n }\r\n \r\n return service;\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.filter('paxNames', paxNames);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name paxNames\r\n * @description \r\n * List pax names in list and return $sce html \r\n * @ngInject\r\n */ \r\nfunction paxNames($sce) {\r\n return function(input) {\r\n var html = '\"
C
Y
';\r\n \r\n html = html + \"
Passengers \"\r\n html = html + '
' + input.PassengerSummaryC.Passengers + \"
\";\r\n html = html + '
' + input.PassengerSummaryY.Passengers + '
';\r\n\r\n html = html + \"
PRM \"\r\n html = html + '
' + input.PassengerSummaryC.PRM + \"
\";\r\n html = html + '
' + input.PassengerSummaryY.PRM + '
';\r\n\r\n html = html + \"
UMNR \"\r\n html = html + '
' + input.PassengerSummaryC.UMNR + \"
\";\r\n html = html + '
' + input.PassengerSummaryY.UMNR + '
';\r\n\r\n html = html + \"
DEP \"\r\n html = html + '
' + input.PassengerSummaryC.DEP + \"
\";\r\n html = html + '
' + input.PassengerSummaryY.DEP + '
\\\"';\r\n \r\n \r\n return $sce.trustAsHtml(html);\r\n }\r\n};\r\n\r\n})();","\r\n(function () {\r\n\r\n a3_pilot_reports.directive('reportsPanel', reportsPanel);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name reportsPanel\r\n * @restrict E\r\n * @description\r\n * Implementation of reportsPanel\r\n * Initialize the panels with reports.\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function reportsPanel($location, defaultCalendarDate) {\r\n function link($scope, element, attrs) {\r\n $scope.togglePanel = togglePanel;\r\n\r\n var flight = $scope.flight;\r\n $scope.showSafetyReport = showSafetyReport();\r\n //Initialize CSS classes\r\n $scope.getTextClass = getTextClass();\r\n $scope.getTopClass = getTopClass();\r\n $scope.getBottomClass = getBottomClass();\r\n $scope.hasIcon = hasIcon();\r\n $scope.openCabinReport = openCabinReport;\r\n\r\n /**\r\n * toggle Panel\r\n * @memberof FlightInfoCtrl\r\n * @param {number} panelId\r\n */\r\n function togglePanel(panelId) {\r\n $('#' + panelId).toggle();\r\n }\r\n\r\n function showSafetyReport(){\r\n var today = new Date().toUTC();\r\n if(defaultCalendarDate){\r\n today = new Date(defaultCalendarDate).toUTC();\r\n }\r\n var flightDate = new Date(flight.FlightDate);\r\n var trimmedToday = new Date(today);\r\n var trimmedFlightDate = new Date(flightDate);\r\n var diffDays = Date.DifferenceInDays(trimmedToday.trimTime(), trimmedFlightDate.trimTime());\r\n\r\n return diffDays <= 0;\r\n }\r\n \r\n /**\r\n * Return the text ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\r\n function getTextClass() {\r\n var classname = \"\";\r\n if (flight.LineStatus === 'na')\r\n classname = \"text-gray\";\r\n else if (flight.LineStatus === 'pending')\r\n classname = \"text-blue\";\r\n else if (flight.LineStatus === 'pendingoverdue')\r\n classname = \"text-blue\";\r\n else if (\r\n (flight.LineStatus === 'draft') ||\r\n (flight.LineStatus === 'draftotheruser')\r\n ) {\r\n classname = \"text-orange\";\r\n } else if (\r\n (flight.LineStatus === 'completed') ||\r\n (flight.LineStatus === 'completedotheruser')\r\n ) {\r\n classname = \"text-purple\";\r\n } else if (\r\n (flight.LineStatus === 'stored') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synched') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n classname = \"text-green\";\r\n }\r\n return classname;\r\n }\r\n\r\n /**\r\n * Return the panel upper ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\r\n function getTopClass() {\r\n var classname = \"\";\r\n if (flight.LineStatus === 'na')\r\n classname = \"border-top-gray\";\r\n else if (flight.LineStatus === 'pending')\r\n classname = \"border-top-blue\";\r\n else if (flight.LineStatus === 'pendingoverdue')\r\n classname = \"border-top-blue\";\r\n else if (\r\n (flight.LineStatus === 'draft') ||\r\n (flight.LineStatus === 'draftotheruser')\r\n ) {\r\n classname = \"border-top-orange\";\r\n } else if (\r\n (flight.LineStatus === 'completed') ||\r\n (flight.LineStatus === 'completedotheruser')\r\n ) {\r\n classname = \"border-top-purple\";\r\n } else if (\r\n (flight.LineStatus === 'stored') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synched') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n classname = \"border-top-green\";\r\n }\r\n return classname;\r\n }\r\n\r\n /**\r\n * Return the panel border ccs class accoriding to report status\r\n * @memberof FlightInfoCtrl\r\n * @returns {string} cssClass\r\n */\r\n function getBottomClass() {\r\n var classname = \"\";\r\n if (flight.LineStatus === 'na')\r\n classname = \"border-bottom-gray\";\r\n else if (flight.LineStatus === 'pending')\r\n classname = \"border-bottom-blue\";\r\n else if (flight.LineStatus === 'pendingoverdue')\r\n classname = \"border-bottom-blue\";\r\n else if (\r\n (flight.LineStatus === 'draft') ||\r\n (flight.LineStatus === 'draftotheruser')\r\n ) {\r\n classname = \"border-bottom-orange\";\r\n } else if (\r\n (flight.LineStatus === 'completed') ||\r\n (flight.LineStatus === 'completedotheruser')\r\n ) {\r\n classname = \"border-bottom-purple\";\r\n } else if (\r\n (flight.LineStatus === 'stored') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synched') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n classname = \"border-bottom-green\";\r\n }\r\n return classname;\r\n }\r\n\r\n /**\r\n * If report from another user exists, show icon\r\n * @memberof FlightInfoCtrl\r\n * @returns {boolean} hasIcon\r\n */\r\n function hasIcon() {\r\n var hasIcon = false;\r\n if (\r\n (flight.LineStatus === 'draftotheruser') ||\r\n (flight.LineStatus === 'completedotheruser') ||\r\n (flight.LineStatus === 'storedotheruser') ||\r\n (flight.LineStatus === 'stored+otheruser') ||\r\n (flight.LineStatus === 'synchedotheruser')\r\n ) {\r\n hasIcon = true;\r\n }\r\n return hasIcon;\r\n }\r\n\r\n /**\r\n * Redirects to cabin report page\r\n * @memberof FlightInfoCtrl\r\n * @returns {boolean} hasIcon\r\n */\r\n function openCabinReport() {\r\n $location.path(\"reportsHistory/\" + flight.CabinReportId + \"/\" + flight.FlightId+\"/Cabin\");\r\n }\r\n\r\n }\r\n\r\n\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/directives/reportsPanel.tpl.html\",\r\n scope: false,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('ssr',ssr);\r\n\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name ssr\r\n * @restrict EA\r\n * @description\r\n * Implementation of issues\r\n *\r\n * Initialize the special service template\r\n * @attr {String} format The name of the format to initialize the ssr.\r\n * @example\r\n * Usage:\r\n *
\r\n * @ngInject\r\n */ \r\nfunction ssr($sce,ssrCodes, showRecomendedWaterAcTypes) {\r\n\r\n\t\r\n\t\treturn {\r\n\t\t\trestrict: 'EA',\r\n\t\t\tterminal: true,\r\n templateUrl: 'views/directives/ssr.tpl.html',\r\n scope: {\r\n paxInfo: '=',\r\n flight: '='\r\n },\r\n link: function ($scope, element, attrs) {\r\n $scope.format = attrs.format;\r\n \r\n $scope.FQTVGold = detailedInfo('FQTVGold');\r\n $scope.FQTVSilver = detailedInfo('FQTVSilver');\r\n $scope.UMNR = detailedInfo('UMNR');\r\n $scope.PRM = detailedInfo('WCBD,WCBW,WCHC,WCHR,WCHS,WCLB,WCMP,WCOB')\r\n $scope.DEAF = detailedInfo('DEAF')\r\n $scope.BLND = detailedInfo('BLND')\r\n $scope.DPNA = detailedInfo('DPNA')\r\n $scope.DEP = detailedInfo('DEPA,DEPU,ESCD')\r\n $scope.INAD = detailedInfo('INAD')\r\n $scope.MEDA = detailedInfo('AOXY,MEDA,MEQT,POXY')\r\n $scope.CBBG = detailedInfo('CBBG')\r\n $scope.OTH = detailedInfo('AVIH,BIKE,EMIG,ESAN,EXST,FAMS,GPST,HAJJ,PETC,SVAN,WEAP,XBGS')\r\n \r\n $scope.showFQTVGold = false;\r\n $scope.showFQTVSilver = false;\r\n $scope.showUMNR = false;\r\n $scope.showPRM = false;\r\n $scope.showDEAF = false;\r\n $scope.showBLND = false;\r\n $scope.showDPNA = false;\r\n $scope.showDEP = false;\r\n $scope.showINAD = false;\r\n $scope.showMEDA = false;\r\n $scope.showCBBG = false;\r\n $scope.showOTH = false;\r\n \r\n \r\n \r\n $scope.waterQuantity = getWaterQuantity();\r\n $scope.showRecomendedWater = showRecomendedWater(); \r\n \r\n function showRecomendedWater(){\r\n return showRecomendedWaterAcTypes.includes($scope.flight.AcType);\r\n }\r\n \r\n function getWaterQuantity(){\r\n var totalPax = $scope.flight.BookedC + $scope.flight.BookedY;\r\n var startDate = moment($scope.flight.ScheduledDeparture);\r\n var endDate = moment($scope.flight.ScheduledArrival);\r\n var duration = moment.duration(endDate.diff(startDate)).asHours();\r\n var waterQuantity = (0,18 * totalPax * duration)/200;\r\n var formattedwaterQuantity = waterQuantity.toString().substring(0,4);\r\n return formattedwaterQuantity;\r\n }\r\n \r\n \r\n function detailedInfo(properties){\r\n var propertiesArray = properties.split(',');\r\n var htmlPopover = ''\r\n if($scope.paxInfo && $scope.paxInfo.PassengerSummaryC && $scope.paxInfo.PassengerSummaryY){\r\n if(propertiesArray.length>1){\r\n htmlPopover = '
C
Y
Total
';\r\n\r\n angular.forEach(propertiesArray,function(property){\r\n \r\n var Total = $scope.paxInfo.PassengerSummaryC[('Total'+property)] + $scope.paxInfo.PassengerSummaryY[('Total'+property)];\r\n if(Total>0){\r\n var code = '';\r\n for (var i = 0; i < ssrCodes.length ; i++){\r\n if(ssrCodes[i].code == property){\r\n code = ssrCodes[i].description;\r\n }\r\n }\r\n htmlPopover = htmlPopover + '
' + property + \"\";\r\n htmlPopover = htmlPopover + '' + code + \"\";\r\n htmlPopover = htmlPopover + '
' + $scope.paxInfo.PassengerSummaryC[property] + \"
\";\r\n htmlPopover = htmlPopover + '
' + $scope.paxInfo.PassengerSummaryY[property] + \"
\";\r\n \r\n htmlPopover = htmlPopover + '
' \r\n + Total\r\n + \"
\";\r\n }\r\n })\r\n }else{\r\n angular.forEach(propertiesArray,function(property){\r\n var Total = $scope.paxInfo.PassengerSummaryC[('Total'+property)] + $scope.paxInfo.PassengerSummaryY[('Total'+property)];\r\n htmlPopover = '
C ' + $scope.paxInfo.PassengerSummaryC[property] + '';\r\n htmlPopover = htmlPopover + ' Y ' + $scope.paxInfo.PassengerSummaryY[property] + '';\r\n if(Total){\r\n htmlPopover = htmlPopover + ' Total ' + Total + '';\r\n }\r\n htmlPopover = htmlPopover + '
';\r\n })\r\n }\r\n }\r\n \r\n return $sce.trustAsHtml(htmlPopover);\r\n }\r\n }\r\n\t\t}\r\n\t}\r\n\r\n \r\n\r\n\r\n})();\r\n\t","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.controller('SyncPaxCtrl',SyncPaxCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SyncPaxCtrl\r\n * @description \r\n * Get the latest PAX and gate Information\r\n * @ngInject\r\n */\r\n\tfunction SyncPaxCtrl($scope, InfoAPIService, $uibModalInstance, $route, $timeout, flightId, LogService, FlightFactory, FlightSessionFactory, CourseFactory, CrewCallFactory, PreviousDutyFactory){\r\n\t\t\r\n\t\tvar flight = FlightFactory.getFlightFromTotalFlights(flightId);\r\n\t\r\n\t\t$scope.hideElements = true;\r\n\t\t$scope.showOnSuccess = false;\r\n\t\t$scope.showOnEmptyData = false;\r\n\t\t$scope.showOnSuccessNoFlightData = false;\r\n\t\t$scope.showOnOutOfDateRange = false;\r\n\t\t$scope.cancel = cancel;\r\n\t\t$scope.flightId = flightId;\r\n\r\n\t\tvar isThisFlightSynced = false;\r\n\r\n\t\t$scope.isFetchingFlightData = false;\r\n\t\t$scope.flightDataStatus = [\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Flight Status\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Aircraft Movement\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Crew Info\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Crew Contacts\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t// {\r\n\t\t\t// \tdatatype: \"Aims Crew Memos\",\r\n\t\t\t// \tstatus: \"PENDING\",\r\n\t\t\t// \ttext: \"Pending...\"\r\n\t\t\t// },\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Pax Info\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Meals\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tdatatype: \"Connections\",\r\n\t\t\t\tstatus: \"PENDING\",\r\n\t\t\t\ttext: \"Pending...\"\r\n\t\t\t},\r\n\t\t\t{\r\n datatype: \"Training Info\",\r\n status: \"PENDING\",\r\n text: \"Pending...\"\r\n }\r\n\t\t];\r\n\r\n \r\n /**\r\n * Close the modal\r\n * @memberof SyncPaxCtrl\r\n */\r\n\t\tfunction cancel() {\r\n\t\t\t$uibModalInstance.close('close');\r\n\t\t\t$route.reload();\r\n\t\t};\r\n\r\n\t\tvar q = InfoAPIService.getPax(flightId);\r\n\t\t$scope.isFetchingFlightData = true;\r\n\t\t\r\n\t\tq.then(function(responseData){\r\n\r\n\t\t\tupdateStatusGenerator(responseData);\r\n\t\t\t$scope.isFetchingFlightData = !($scope.isFetchingFlightData);\r\n\r\n\t\t\tif (responseData == undefined || responseData.data == undefined || responseData.data.data == undefined) {\r\n\t\t\t\tvar err = new Error();\r\n\t\t\t\terr.status = -1;\r\n\t\t\t\tvar msg = \"ResponseData error in sync :\" + JSON.stringify(responseData);\r\n\t\t\t\tLogService.debug(msg, err)\r\n\t\t\t\tq.reject(err);\r\n\t\t\t}\r\n\r\n\t\t\t//Save training\r\n\t\t\tvar trainingCourses = responseData.data.data.TrainingCourses;\r\n\t\t\tif(trainingCourses && trainingCourses.length){\r\n\t\t\t\ttrainingCourses.forEach(function(trainingCourse){\r\n\t\t\t\t\tCourseFactory.upsertCourse(trainingCourse, function(course) {\r\n\t\t\t\t\t\tFlightSessionFactory.applyTraineeInfoToSession(course, course.Id, new moment(flight.DutyDate).format(\"YYYY-MM-DD\"), flight.DutyNo, flight.DutyDay, function(session) {\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t});\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\t//1. First remove all additional info (phone numbers & previous duties) for this flight\r\n\t\t\tCrewCallFactory.cleanFlightCrewNumbers(flightId);\r\n\t\t\tPreviousDutyFactory.cleanFlightPreviousDuties(flightId);\r\n\r\n\t\t\t//2. Then save any fetched info\r\n\t\t\tif( responseData.data.data.FlightInfo){\r\n\t\t\t\tvar crew = responseData.data.data.FlightInfo.crew;\r\n\r\n\t\t\t\tCrewCallFactory.saveFlightPhoneNumbers(flightId, crew, flight.ScheduledArrival, flight.ScheduledDeparture);\r\n\t\t\t\tPreviousDutyFactory.saveFlightPreviousDuties(flightId, crew);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//Save pax\r\n\t\t\tif(responseData.data.data.CabinServiceManagementLists){\r\n\t\t\t\tfor(var i=0; i
\r\n * @ngInject\r\n */ \r\nfunction turnAroundTimes(AircaftPositionsFactory, turnAroundTimesSupportingAcTypes) {\r\n \r\n /**\r\n * Initialize turnAroundTimes\r\n * @memberof turnAroundTimes\r\n * @param {service} scope the scope of this element\r\n * @param {service} element element that this direcive is assigned to\r\n * @param {service} attributes attributes of this element\r\n */\r\n function link ($scope, element, attrs) {\r\n $scope.showTaTpanel = false;\r\n\r\n var supportsTurnAround = $scope.flight && turnAroundTimesSupportingAcTypes.includes($scope.flight.AcType);\r\n\r\n if($scope.flight && $scope.flight.FlightId && supportsTurnAround ){\r\n var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId($scope.flight.FlightId);\r\n if(aircaftPositions != null && aircaftPositions.PreviousSTA){\r\n\r\n var std = moment.utc($scope.flight.ScheduledDeparture);\r\n \r\n var TaTMinutes = $scope.flight.AcType == '321' ? -50 : -45;\r\n var startofTAT = moment.utc($scope.flight.ScheduledDeparture).add(TaTMinutes, 'm');\r\n var prevATA = aircaftPositions.PreviousATA ? moment.utc(aircaftPositions.PreviousATA) : null;\r\n var prevSTA = moment.utc(aircaftPositions.PreviousSTA);\r\n var lateArrival = 0;\r\n var inadequateGroundTime = 0;\r\n if(startofTAT.diff(prevSTA, 'm')>=0 && aircaftPositions.PreviousATA){\r\n \r\n var comparedValue = startofTAT;\r\n if(lateArrival > 0){\r\n var comparedValue = prevATA;\r\n }\r\n lateArrival = prevATA.diff(comparedValue, 'm');\r\n $scope.ShowlateArrival = true;\r\n }else{\r\n\r\n lateArrival = aircaftPositions.PreviousATA ? prevATA.diff(prevSTA, 'm') : 0;\r\n inadequateGroundTime = prevSTA.diff(startofTAT, 'm');\r\n if(lateArrival<0){\r\n inadequateGroundTime = inadequateGroundTime + lateArrival;\r\n }\r\n }\r\n \r\n $scope.lateArrival = lateArrival< 0 ? 0 : lateArrival;\r\n $scope.inadequateGroundTime = inadequateGroundTime < 0 ? 0 : inadequateGroundTime;\r\n $scope.showTaTpanel = true;\r\n }\r\n }\r\n\r\n }\r\n return {\r\n\t\t\trestrict: 'EA',\r\n\t\t\tterminal: true,\r\n templateUrl: 'views/directives/turnAroundTimes.tpl.html',\r\n\t\t\tscope : false,\r\n link: link \r\n }\r\n}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('GroundDutyFactory', GroundDutyFactory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name GroundDutyFactory\r\n * @description \r\n * Add, Update and Get Ground Duties.\r\n * @ngInject\r\n */ \r\nfunction GroundDutyFactory(GenericService, $http, apiUrl) {\r\n\r\n /**\r\n * Initialize the GroundDuty\r\n * @memberof GroundDutyFactory\r\n */\r\n\t\tfunction GroundDuty() {\r\n\t\t\tthis.Id = null;\r\n\t\t\tthis.Duty = null;\r\n\t\t\tthis.DutyDescription= null;\r\n\t\t\tthis.DutyBegin = null;\r\n this.DutyEnd = null;\r\n this.GetId = GetId;\r\n this.isTraining = false;\r\n this.icon = null;\r\n this.Instructors = new Array();\r\n this.Trainees = new Array();\r\n this.isManualEntry = false;\r\n this.hasPendingCourse = false;\r\n\t\t}\r\n\r\n\t\tvar objType ='groundDuty';\r\n\t\tvar objCallback = GroundDuty;\r\n\r\n\t\tvar service = {\r\n\t\t\tgetGroundDutiesFromStorage : getGroundDutiesFromStorage,\r\n setGroundDutiesToStorage : setGroundDutiesToStorage,\r\n getGroundDutyFromStorage: getGroundDutyFromStorage,\r\n getGroundDutiesByDutyNo: getGroundDutiesByDutyNo,\r\n mergeGroundDutyInfo : mergeGroundDutyInfo,\r\n updateGroundDuty : updateGroundDuty,\r\n getGroundDutyActiveCourses : getGroundDutyActiveCourses,\r\n setCourseCompleted : setCourseCompleted,\r\n setCoursePending : setCoursePending,\r\n mergeGroundDutiesToStorage : mergeGroundDutiesToStorage,\r\n refresh : refresh,\r\n addGroundDuty : addGroundDuty,\r\n removeGroundDuty : removeGroundDuty,\r\n getManualGroundDutiesFromStorage : getManualGroundDutiesFromStorage\r\n\t\t};\r\n\r\n //object functions\r\n /**\r\n * Overide default get Id\r\n * @memberof GroundDutyFactory\r\n * @returns {number} Id \r\n */\r\n\t\tfunction GetId(){\r\n\t\t\treturn this.Id;\r\n\t\t}\r\n /**\r\n * Get Ground Duties.\r\n * @memberof GroundDutyFactory\r\n * @returns {Array} GroundDuties \r\n */\r\n\t\tfunction getGroundDutiesFromStorage() {\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n /**\r\n * Get GroundDuty from storage groundDuties\r\n * @memberof GroundDutyFactory\r\n * @param {number} groundDutyId \r\n * @return {object} groundDuty\r\n */\r\n\t\tfunction getGroundDutyFromStorage(groundDutyId) {\r\n var groundDuty = GenericService.get(groundDutyId, objType, objCallback);\r\n\r\n var instructors = [];\r\n var trainees = [];\r\n\r\n if (groundDuty != null && groundDuty != undefined) {\r\n //only training\r\n if(groundDuty.RelatedGroundDuties && groundDuty.RelatedGroundDuties.length > 1){\r\n groundDuty.isTraining = true; \r\n \r\n groundDuty.RelatedGroundDuties.forEach(function(element) {\r\n if(element.IsInstructor){\r\n instructors.push(element);\r\n }\r\n else{\r\n trainees.push(element);\r\n }\r\n });\r\n\r\n groundDuty.Trainees = trainees;\r\n groundDuty.Instructors = instructors;\r\n }\r\n }\r\n return groundDuty;\r\n }\r\n \r\n /**\r\n * Save Ground Duties to storage\r\n * @memberof GroundDutyFactory\r\n * @param {Array} GroundDuties A list of Ground Duties\r\n */\r\n\t\tfunction setGroundDutiesToStorage(objList) {\r\n\t\t\tGenericService.saveAll(objList,objType);\r\n\t\t}\r\n\r\n /**\r\n * Get GroundDuties of a Crew Route\r\n * @memberof GroundDutyFactory\r\n * @param {number} dutyNo \r\n * @param {string} dutyDay\r\n\t\t * @return {array} groundDuties\r\n */\r\n function getGroundDutiesByDutyNo(dutyNo, dutyDay){\r\n\t\t\tvar groundDuties = getGroundDutiesFromStorage();\r\n\t\t\tif (groundDuties == null)\r\n\t\t\t\treturn [];\r\n var result = [];\r\n \r\n var instructors = [];\r\n var trainees = [];\r\n\r\n\t\t\tvar arrayLength = groundDuties.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (groundDuties[i].DutyNo == dutyNo && groundDuties[i].DutyDay == dutyDay) {\r\n //only training\r\n if(groundDuties[i].RelatedGroundDuties && groundDuties[i].RelatedGroundDuties.length > 1){\r\n groundDuties[i].isTraining = true; \r\n \r\n instructors = [];\r\n trainees = [];\r\n\r\n groundDuties[i].RelatedGroundDuties.forEach(function(element) {\r\n if(element.IsInstructor){\r\n instructors.push(element);\r\n }\r\n else{\r\n trainees.push(element);\r\n }\r\n });\r\n\r\n groundDuties[i].Trainees = trainees;\r\n groundDuties[i].Instructors = instructors;\r\n }\r\n\r\n\t\t\t\t\tresult.push(groundDuties[i]);\r\n\t\t\t\t}\r\n }\r\n\t\t\treturn result;\r\n }\r\n\r\n /**\r\n * Merge new info to current Ground Duty\r\n * @memberof GroundDutyFactory\r\n * @param {object} duty \r\n */\r\n function mergeGroundDutyInfo(duty){\r\n var currentGroundDutyInfo = GenericService.get(duty.Id, objType, objCallback);\r\n \r\n currentGroundDutyInfo.Code = duty.Code;\r\n currentGroundDutyInfo.Description = duty.Description;\r\n currentGroundDutyInfo.DutyDate = duty.DutyDate;\r\n currentGroundDutyInfo.GroundDutyNo = duty.GroundDutyNo;\r\n currentGroundDutyInfo.DutyDateS = duty.DutyDateS;\r\n currentGroundDutyInfo.DutyBegin = duty.DutyBegin;\r\n currentGroundDutyInfo.DutyEnd = duty.DutyEnd;\r\n currentGroundDutyInfo.DutyDay = duty.DutyDay;\r\n currentGroundDutyInfo.DutyNo = duty.DutyNo;\r\n currentGroundDutyInfo.Route = duty.Route;\r\n\r\n if(currentGroundDutyInfo.RelatedGroundDuties && currentGroundDutyInfo.RelatedGroundDuties.length){\r\n currentGroundDutyInfo.RelatedGroundDuties = duty.RelatedGroundDuties;\r\n }\r\n GenericService.save(currentGroundDutyInfo,objType,objCallback);\r\n }\r\n\r\n \r\n function updateGroundDuty(groundDuty){\r\n GenericService.save(groundDuty,objType, objCallback);\r\n }\r\n\r\n function addGroundDuty(groundDuty) { \r\n var storedGroundDuty = GenericService.get(groundDuty.Id, objType, objCallback);\r\n if(!storedGroundDuty){\r\n GenericService.add(groundDuty, objType, objCallback);\r\n }\r\n else {\r\n updateGroundDuty(groundDuty);\r\n }\r\n }\r\n\r\n function removeGroundDuty(groundDuty) {\r\n GenericService.remove(groundDuty, objType, objCallback);\r\n }\r\n\r\n function setCourseCompleted(dutyId,courseId){\r\n var groundDuty = GenericService.get(dutyId, objType, objCallback);\r\n groundDuty.RelatedGroundDuties.filter(x=>x.Courses).forEach(function(item){\r\n var groundDutyCourse = item.Courses.find(x=>x.CourseId == courseId);\r\n if(groundDutyCourse) groundDutyCourse.Status = \"Completed\";\r\n });\r\n\r\n var allCoursesAreCompleted = false;\r\n\r\n if(groundDuty.RelatedGroundDuties && groundDuty.RelatedGroundDuties.length > 0) {\r\n allCoursesAreCompleted = groundDuty.RelatedGroundDuties.filter(x=>x.Courses && x.Courses.length > 0).every(function (relatedDuty){\r\n return relatedDuty.Courses.every(function(course){\r\n return course.Status == \"Completed\";\r\n });\r\n });\r\n }\r\n \r\n if(groundDuty.isManualEntry && allCoursesAreCompleted){\r\n groundDuty.hasPendingCourse = false;\r\n }\r\n\r\n updateGroundDuty(groundDuty);\r\n }\r\n\r\n function setCoursePending(dutyId,courseId){\r\n var groundDuty = GenericService.get(dutyId, objType, objCallback);\r\n groundDuty.RelatedGroundDuties.filter(x=>x.Courses).forEach(function(item){\r\n var groundDutyCourse = item.Courses.find(x=>x.CourseId == courseId);\r\n if(groundDutyCourse) groundDutyCourse.Status = \"Pending\";\r\n });\r\n updateGroundDuty(groundDuty);\r\n }\r\n\r\n function getGroundDutyActiveCourses(groundDutyId){\r\n var groundDuty = GenericService.get(groundDutyId, objType, objCallback);\r\n var courses = [];\r\n if (groundDuty != null && groundDuty != undefined) {\r\n if(groundDuty.RelatedGroundDuties && groundDuty.RelatedGroundDuties.length > 1){\r\n groundDuty.RelatedGroundDuties.filter(x=> !x.IsInstructor && x.Courses).forEach(function(item){\r\n courses.push(...item.Courses);\r\n });\r\n }\r\n }\r\n return courses; \r\n } \r\n \r\n /**Save Ground Duties to storage but keep local storage values\r\n * Necessary to maintain Absent values in training duties\r\n */\r\n function mergeGroundDutiesToStorage(objList){\r\n var groundDuties = getGroundDutiesFromStorage();\r\n\r\n groundDuties.filter(x => x.isManualEntry).forEach(function(duty) {\r\n objList.push(duty);\r\n });\r\n \r\n if(groundDuties){\r\n objList.forEach(function(incomingDuty){\r\n\r\n if(incomingDuty.RelatedGroundDuties){\r\n var incomingTraineesFlat = [];\r\n incomingDuty.RelatedGroundDuties.filter(x => !x.IsInstructor).forEach(function(related) {\r\n related.CrewMembers.forEach(function(trainee) {\r\n incomingTraineesFlat.push(trainee);\r\n });\r\n });\r\n\r\n //Initialize all as present\r\n incomingTraineesFlat.forEach(function(incomingTrainee){\r\n incomingTrainee.Absent = false;\r\n });\r\n\r\n //Copy Absent value from existing local storage duties\r\n var existingDuty = groundDuties.find(x => x.Id == incomingDuty.Id);\r\n if(existingDuty && existingDuty.RelatedGroundDuties){\r\n var existingTraineesFlat = [];\r\n existingDuty.RelatedGroundDuties.filter(x => !x.IsInstructor).forEach(function(related) {\r\n related.CrewMembers.forEach(function(trainee) {\r\n existingTraineesFlat.push(trainee);\r\n });\r\n });\r\n \r\n incomingTraineesFlat.forEach(function(incomingTrainee){\r\n var existingTrainee = existingTraineesFlat.find(x => x.Id == incomingTrainee.Id);\r\n if(existingTrainee){\r\n incomingTrainee.Absent = existingTrainee.Absent;\r\n }\r\n });\r\n }\r\n\r\n }\r\n\r\n });\r\n }\r\n GenericService.saveAll(objList,objType);\r\n }\r\n\r\n function refresh(refreshGroundDuty, callback){\r\n return $http.post(apiUrl + '/GroundDuty/Refresh', refreshGroundDuty, { 'Content-Type': 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**Get manual Ground Duties from storage*/\r\n function getManualGroundDutiesFromStorage(){\r\n var groundDuties = getGroundDutiesFromStorage();\r\n return groundDuties.filter(x => x.isManualEntry);\r\n }\r\n \r\n\t\treturn service;\r\n\t}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('PastGroundDutyFactory', PastGroundDutyFactory);\r\n /**\r\n * @memberof CabinReports\r\n * @ngdoc factory\r\n * @name PastGroundDutyFactory\r\n * @description \r\n * Get Past Ground Duties.\r\n * @ngInject\r\n */ \r\nfunction PastGroundDutyFactory($http, apiUrl) {\r\n\r\n var service = {\r\n getPastGroundDuties: getPastGroundDuties,\r\n };\r\n\r\n function getPastGroundDuties(callback) {\r\n return $http.get(apiUrl + '/Training/GetPastGroundDuties', { 'Content-Type': 'application/json' })\r\n .catch(callback); \r\n } \r\n \r\n return service;\r\n}\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('encryptionInterceptor', encryptionInterceptor);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpHeaderInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\r\n function encryptionInterceptor($location, apiUrl) {\r\n return {\r\n request: function (config) {\r\n if (config.url.includes(\"api\")) {\r\n if (config.method === \"POST\" || config.method === \"PUT\") {\r\n var encryptedData = encrypt(config.data);\r\n console.log(encryptedData);\r\n }\r\n else if (config.method === \"GET\") {\r\n var absolutePath = config.url;\r\n var stringToHash = absolutePath.substring(absolutePath.lastIndexOf(\"/\") + 1, absolutePath.length);\r\n var hash = (stringToHash + user.aimsId).getHash();\r\n }\r\n }\r\n return config;\r\n }\r\n };\r\n }\r\n\r\n function encrypt(data){\r\n debugger;\r\n \r\n\r\n }\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.config(exceptionConfig);\r\n\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc config\r\n * @name exceptionConfig\r\n * @description \r\n * By default, AngularJS will catch errors and log them to\r\n * the Console. We want to keep that behavior; however, we\r\n * want to intercept it so that we can also log the errors\r\n * to the server for later analysis.\r\n * @ngInject\r\n */\r\nfunction exceptionConfig($provide) {\r\n $provide.decorator('$exceptionHandler', extendExceptionHandler);\r\n}\r\n\r\n /**\r\n * @memberof exceptionConfig\r\n * @description \r\n * Override default exception handling and log errors \r\n * @ngInject\r\n */\t\r\nfunction extendExceptionHandler($delegate, LogService) {\r\n return function(exception, cause) {\r\n $delegate(exception, cause);\r\n /**\r\n * Could add the error to a service's collection,\r\n * add errors to $rootScope, log errors to remote web server,\r\n * or log locally. Or throw hard. It is entirely up to you.\r\n * throw exception;\r\n */\r\n LogService.error(exception, cause);\r\n };\r\n}\r\n \r\n})();","(function() {\r\n 'use strict';\r\n \r\n //***************************************************************************//\r\n //************ Redirect HTTP401 to login page, examine json format on success\r\n //***************************************************************************//\r\n // register the interceptor as a service\r\n a3_pilot_reports.factory('http401interceptor', http401interceptor)\r\n\r\n /* @ngInject */ \r\n function http401interceptor($q,$location, $log){\r\n return {\r\n\r\n 'response': function(response) {\r\n // do something on success\r\n //expecting specific object as a response: success:true/false,errorMessage:string,data:any not null object\r\n //var contentType=response.headers(\"content-type\");\r\n var header = \"\";\r\n if(response && response.headers() && response.headers(\"content-type\")) header = response.headers(\"content-type\").substring(0,16);\r\n if (header===\"application/json\")\r\n {\r\n var errorMessage=\"\";\r\n var isError=false;\r\n if (response==null || response.data==null || response.data.success==null || response.data.errorMessage==null || response.data.data==='undefined')\r\n {\r\n isError=true;\r\n errorMessage=\"Server response not found\";\r\n }\r\n else if (response.data.success==false)\r\n {\r\n isError=true;\r\n errorMessage=response.data.errorMessage;\r\n }\r\n if (isError) $q.reject(response,errorMessage);\r\n }\r\n return response || $q.when(response);\r\n },\r\n\r\n // optional method\r\n 'responseError': function(rejection) {\r\n if(rejection.status === 401){\r\n $log.error('Authorization failed. Need to login again');\r\n if ($location.path()!='/login'){\r\n $location.path('/login');\r\n //force refresh so that the browser will download any updates from the cache.manifest\r\n //without refresh, user may stick to an older version for ever\r\n setTimeout(function(){window.location.reload(true);},1000);\r\n }\r\n return $q.reject(rejection);\r\n }\r\n else{\r\n return $q.reject(rejection); \r\n }\r\n }\r\n };\r\n };\r\n\r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n\r\na3_pilot_reports.factory('httpCrewTokenInterceptor', httpCrewTokenInterceptor);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpCrewTokenInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */ \r\nfunction httpCrewTokenInterceptor($location,$log,localStorageMD5Service,UserTokenFactory){\r\n return {\r\n request: function (config) {\r\n\t\tif ($location.$$url!=\"/login\"){\r\n\t\t\t\r\n\t \t// get the user token\r\n\t \tvar user = localStorageMD5Service.get('user');\r\n\t \tvar token = '';\r\n\t \tif (user != null)\r\n\t \t\ttoken = user.token;\r\n\r\n\t\t\tconfig.headers['X-CrewToken'] = token;\r\n\t\t}\r\n\t\treturn config;\r\n },\r\n response: function (response) {\r\n if(response.headers()['content-type'] === \"application/json; charset=utf-8\"){\r\n \r\n var expiresAt = response.headers()['x-expires-token']\r\n var crewToken = response.headers()['x-rolling-token']\r\n\r\n if(expiresAt && crewToken ){\r\n var user = localStorageMD5Service.get('user');\r\n if (user != null){\r\n user.token = crewToken;\r\n user.expires = expiresAt;\r\n localStorageMD5Service.set('user',user);\r\n }\r\n UserTokenFactory.setToken(crewToken);\r\n }\r\n }\r\n return response;\r\n }\r\n }\r\n}\r\n \r\n})(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('httpHeaderInterceptor', httpHeaderInterceptor);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpHeaderInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\r\n function httpHeaderInterceptor($location, localStorageMD5Service, apiUrl) {\r\n return {\r\n request: function (config) {\r\n if ($location.$$url != \"/login\") {\r\n if (config.url.includes(\"api\")) {\r\n var user = localStorageMD5Service.get('user');\r\n var aimsIdToString = user.aimsId.toString();\r\n if (config.method === \"POST\" || config.method === \"PUT\") {\r\n var dataToHash = typeof config.data === \"object\" ? angular.toJson(config.data) + aimsIdToString : config.data + aimsIdToString;\r\n var hash = (dataToHash).getHash();\r\n config.headers['X-VCode'] = hash;\r\n }\r\n else if (config.method === \"GET\") {\r\n var absolutePath = config.url;\r\n var stringToHash = absolutePath.substring(absolutePath.lastIndexOf(\"/\") + 1, absolutePath.length);\r\n var hash = (stringToHash + aimsIdToString).getHash();\r\n config.headers['X-VCode'] = hash;\r\n }\r\n }\r\n\r\n }\r\n return config;\r\n }\r\n };\r\n }\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.config(httpProviderConfig)\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name httpCrewTokenInterceptor\r\n * @description \r\n * Add CrewToken on non login requests\r\n * @ngInject\r\n */\r\nfunction httpProviderConfig($httpProvider) {\r\n\t$httpProvider.defaults.useXDomain = true;\r\n\t\tdelete $httpProvider.defaults.headers.common['X-Requested-With'];\r\n\r\n\t$httpProvider.interceptors.push('http401interceptor');\r\n $httpProvider.interceptors.push('httpCrewTokenInterceptor');\r\n $httpProvider.interceptors.push('httpHeaderInterceptor');\r\n //$httpProvider.interceptors.push('encryptionInterceptor');\r\n\r\n}\r\n \r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.config(localStorageMD5Config);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc config\r\n * @name localStorageMD5Config\r\n * @description \r\n * Config localStorageMD5ServiceProvider directly by using localStorageMD5ServiceProvider\r\n * @ngInject\r\n */\r\nfunction localStorageMD5Config(localStorageMD5ServiceProvider,localStorageServiceProvider){\r\n\t//localStorageMD5ServiceProvider.help();\r\n\tvar regx = /[?&]secure[&#]?/;\r\n\tif (regx.exec(window.location.href)){\r\n\t\tconsole.log('*** SECURE MODE ***');\r\n\t\tlocalStorageServiceProvider.setStorageType('sessionStorage');\r\n\t}\r\n\tlocalStorageServiceProvider.setPrefix('a3.pilot.reports');\r\n\tlocalStorageServiceProvider.setStorageCookie(10,'/');\r\n\tlocalStorageMD5ServiceProvider.enableCompression();\r\n};\r\n \r\n})(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory(\"LogService\",LogService);\r\n\r\n/**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name LogService\r\n * @description \r\n * The error log service is our wrapper around the core error\r\n * handling ability of AngularJS. Notice that we pass off to\r\n * the native \"$log\" method and then handle our additional\r\n * server-side logging.\r\n * @ngInject\r\n */\r\nfunction LogService( $log,$injector ,$window, apiUrl, UserTokenFactory ,version) {\r\n\tvar lastError=null;\r\n var acceptedTimeDiff = 5; \r\n \r\n function post(errorMessage,stackTrace,cause){\r\n\t\t\t\r\n\t\t\ttry {\r\n\t\t\t\tvar $http = $injector.get(\"$http\");\r\n\t\t \t/*// get the user token\r\n\t\t \tvar user = UserFactory.getUser();\r\n\t\t \tvar token = '';\r\n\t\t \tif (user != null)\r\n\t\t \t\ttoken = user.token;*/\r\n\t\t\t\tvar token = UserTokenFactory.getToken();\r\n\t\t\t\t// Log the JavaScript error to the server.\r\n\t\t\t\t// --\r\n\t\t\t\t// NOTE: In this demo, the POST URL doesn't\r\n\t\t\t\t// exists and will simply return a 404.\r\n\t\t\t\t$http({\r\n\t\t\t\t\tmethod: \"POST\",\r\n\t\t\t\t\turl: apiUrl +\"/log\",\r\n\t\t\t\t\tcontentType: \"application/json\",\r\n\t\t\t\t\tdata:{\r\n\t\t\t\t\t\terrorUrl: $window.location.href,\r\n\t\t\t\t\t\terrorMessage: version + \" \" +errorMessage ,\r\n\t\t\t\t\t\tstackTrace: stackTrace,\r\n\t\t\t\t\t\tcause: ( cause || \"\" )\r\n\t\t\t\t\t},\r\n\t\t\t\t\tbeforeSend: function (request)\r\n\t\t {\r\n\t\t request.setRequestHeader('X-CrewToken', token);\r\n\t\t }\r\n\t\t\t\t});\r\n\t\t\t\t\r\n\r\n\t\t\t} catch ( loggingError ) {\r\n\r\n\t\t\t\t// For Developers - log the log-failure.\r\n\t\t\t\t$log.warn( \"Error logging failed\" );\r\n\t\t\t\t$log.log( loggingError );\r\n\r\n\t\t\t}\r\n\t\t};\r\n\r\n function postFilter(errorMessage,stackTrace,cause){\r\n\t\t\t\tif(lastError!=null && lastError.errorDescr==errorMessage){\r\n\t\t\t\tvar timestampDiff=Date.now()-lastError.timestamp;\r\n\t\t\t\tvar timeDiffInSec = timestampDiff / 1000;\r\n\t\t\t\t\tif (timeDiffInSec > acceptedTimeDiff){\r\n lastError={'errorDescr': errorMessage,\r\n\t\t\t\t\t\t'timestamp': Date.now()};\r\n\t\t\t\t\tpost(errorMessage,stackTrace,cause);\r\n\t\t\t\t\t}\r\n\t\t\t\t}else{\r\n lastError={'errorDescr': errorMessage,\r\n\t\t\t\t\t\t'timestamp': Date.now()};\r\n\t\t\t\t\tpost(errorMessage,stackTrace,cause);\r\n\t\t\t\t}\r\n\t\t};\r\n\t\t\r\n\treturn {\r\n\tdebug : function ( errorMessage, error ){\r\n\t\t\tif (error==null){\r\n\t\t\t\terror=new Error();\r\n\t\t\t}\r\n\t\t\tif(errorMessage!=null){\r\n\t\t\t\terror.description=errorMessage;\r\n\t\t\t}\r\n\r\n\t\t\tpost(error.description,error.stack,\"\");\r\n\t\t\r\n\t},\r\n\terror : function(exception,cause) {\r\n\r\n\t\t\t// Pass off the error to the default error handler\r\n\t\t\t// on the AngualrJS logger. This will output the\r\n\t\t\t// error to the console (and let the application\r\n\t\t\t// keep running normally for the user).\r\n\t\t\t$log.error.apply( $log, arguments );\r\n\r\n\t\t\t// Now, we need to try and log the error the server.\r\n\t\t\t// --\r\n\t\t\t// NOTE: In production, I have some debouncing\r\n\t\t\t// logic here to prevent the same client from\r\n\t\t\t// logging the same error over and over again! All\r\n\t\t\t// that would do is add noise to the log.\r\n\t\t\tvar errorMessage = exception.toString();\r\n\t\t\t//var stackTrace = stacktraceService.print({ e: exception });\r\n\t\t\t//var stackTrace = $log.info({ e: exception });\r\n\t\t\tvar stackTrace = exception.stack;\r\n\r\n\t\t\tpostFilter(errorMessage,stackTrace,cause);\r\n\r\n\t\t\t}\r\n\t\t};\r\n\t\t\r\n}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('UserTokenFactory', UserTokenFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name UserTokenFactory\r\n * @description \r\n * Used to maintain the user token, outside the localStorage, in order to be accessible from the service which logs js errors\r\n * /(this service may not use localstorage provider)\r\n * @ngInject\r\n */\r\n function UserTokenFactory(){\r\n return {\r\n token: '',\r\n\r\n setToken: function(value){\r\n this.token = value;\r\n },\r\n\r\n getToken: function(){\r\n return this.token;\r\n }\r\n };\r\n}\r\n \r\n })(); ","// create guid\r\nvar guid = (function() {\r\n\t function s4() {\r\n\t return Math.floor((1 + Math.random()) * 0x10000)\r\n\t .toString(16)\r\n\t .substring(1);\r\n\t }\r\n\t return function() {\r\n\t return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\r\n\t s4() + '-' + s4() + s4() + s4();\r\n\t };\r\n\t})();\r\n\r\n// generic sort function\r\nvar sort_by = function(field, reverse, primer){\r\n\t var key = function (x) {return primer ? primer(x[field]) : x[field]};\r\n\r\n\t return function (a,b) {\r\n\t\t var A = key(a), B = key(b);\r\n\t\t return ( (A < B) ? -1 : ((A > B) ? 1 : 0) ) * [-1,1][+!!reverse]; \r\n\t }\r\n\t};","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('competences', competences);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name certificates\r\n * @restrict E\r\n * @description\r\n * Implementation of competences\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function competences($uibModal, $timeout) {\r\n function link(scope, element, attrs) {\r\n scope.manageCompetenceGrading = manageCompetenceGrading;\r\n scope.selectSubCompetence = selectSubCompetence;\r\n scope.openGradingModal = openGradingModal;\r\n\r\n scope.trainee.Competences.forEach(function(competence){\r\n competence.isCollapsed = competence.hasMandatory || competence.hasOptional;\r\n competence.showComments = competence.hasMandatory || competence.hasOptional || (competence.Comments && competence.Comments != \"\")\r\n });\r\n\r\n validateTraineeCompetences(scope.trainee);\r\n\r\n function validateTraineeCompetences(trainee){\r\n var missingGrading = trainee.Competences.some(c => c.Grading == null);\r\n var missingPerformanceIndicators = trainee.Competences.filter(c => c.hasMandatory).some(c => !c.SubCompetences.some(sub => sub.Selected));\r\n trainee.isCompetenceValid = !missingGrading && !missingPerformanceIndicators;\r\n } \r\n\r\n function manageCompetenceGrading(competence){\r\n var grading = competence.Grading ? Number(competence.Grading) : null;\r\n var hadMandatory = competence.hasMandatory;\r\n var hadOptional = competence.hasOptional;\r\n competence.hasMandatory = competence.MandatorySub.includes(grading);\r\n competence.hasOptional = competence.OptionalSub.includes(grading);\r\n competence.isCollapsed = competence.hasMandatory || competence.hasOptional;\r\n if(competence.isCollapsed) competence.showComments = true;\r\n \r\n //From Mandatory to None remove selected Sub Competences\r\n if( ((hadMandatory || hadOptional) && (!competence.hasMandatory && !competence.hasOptional))){\r\n competence.SubCompetences.forEach(function(sub){\r\n sub.Selected = false;\r\n });\r\n }\r\n\r\n validateTraineeCompetences(scope.trainee);\r\n\r\n switch (competence.Grading) {\r\n case 5:\r\n competence.GradingMessage = competence.GradeA;\r\n break;\r\n case 4:\r\n competence.GradingMessage = competence.GradeB;\r\n break;\r\n case 3:\r\n competence.GradingMessage = competence.GradeC;\r\n break;\r\n case 2:\r\n competence.GradingMessage = competence.GradeD;\r\n break;\r\n case 1:\r\n competence.GradingMessage = competence.GradeE;\r\n break;\r\n default:\r\n competence.GradingMessage = \"\";\r\n }\r\n\r\n scope.gradingSelection();\r\n }\r\n \r\n function selectSubCompetence(sub){\r\n sub.Selected = !sub.Selected;\r\n if(sub.Selected) scope.gradingSelection();\r\n validateTraineeCompetences(scope.trainee);\r\n }\r\n\r\n function openGradingModal(competence){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgCompetenceGrading.html',\r\n controller: 'CompetenceModalCtrl',\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n competence: function () { return competence;},\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (grading) {\r\n if(grading){\r\n manageCompetenceGrading(competence, grading);\r\n }\r\n });\r\n }\r\n }\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/competences.tpl.html',\r\n scope: {trainee : \"=\", gradingSelection: \"&onGradingSelection\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('FlightCourseCtrl', FlightCourseCtrl);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name FlightCourseCtrl\r\n * @description \r\n *\r\n * @ngInject\r\n */\r\n function FlightCourseCtrl($route, $filter, $timeout, FlightSessionFactory, CrewRouteFactory, FlightFactory, GroundDutyFactory, CourseFactory, $scope, $location, $routeParams) {\r\n $scope.gotoCourse = gotoCourse;\r\n $scope.gotoCrewRoute = gotoCrewRoute;\r\n $scope.gotoFlight = gotoFlight;\r\n $scope.stickySelectedTrainee = stickySelectedTrainee;\r\n $scope.toggleView = toggleView;\r\n\r\n\r\n $scope.refreshCourse = refresh;\r\n $scope.courseTrainees = [];\r\n\r\n var courseId = Number($routeParams.courseId);\r\n var dutyNo = Number($routeParams.dutyNo);\r\n var dutyDay = Number($routeParams.dutyDay);\r\n $scope.viewFromFlight = Number($routeParams.flightId);\r\n\r\n var crewRouteDuty = CrewRouteFactory.getCrewRouteFromStorage(dutyNo, dutyDay);\r\n \r\n var date = $routeParams.date;\r\n crewRouteDuty.date = date;\r\n \r\n var crewRouteCourse = crewRouteDuty.Courses.find(x => x.CourseId == courseId && new moment(x.Date).isSame(date));\r\n\r\n $scope.isEdit = false;\r\n $scope.loading = false;\r\n $scope.refreshSuccess = true; //show refresh icon\r\n\r\n\r\n if (!crewRouteDuty) {\r\n // go to dashboard if no groundDuty\r\n $location.path(\"/\");\r\n } \r\n else \r\n {\r\n $scope.flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay);\r\n\r\n //Get Crew Route's course\r\n CourseFactory.getCourseFromStorage(courseId, function (savedCourse) {\r\n var dutyCourse = savedCourse;\r\n $scope.dutyCourse = dutyCourse;\r\n initCourse(false);\r\n });\r\n $scope.crewRouteDuty = crewRouteDuty;\r\n }\r\n\r\n function gotoFlight(){\r\n var flightId = Number($routeParams.flightId)\r\n $location.path('/flightinfo/' + flightId);\r\n }\r\n\r\n function initCourse(afterRefresh) {\r\n var courseId = $scope.dutyCourse.Id;\r\n FlightSessionFactory.getSession(courseId, date, dutyNo, dutyDay, crewRouteCourse.TrainingFlightIds, afterRefresh, function (course) {\r\n if (course && !course.HasLimitedInfo) {\r\n $scope.availableCourse = true;\r\n \r\n $scope.selectedPhase = course.selectedPhase;\r\n $scope.trainees = course.CourseTrainees;\r\n course.SequenceWarning = false;\r\n }\r\n\r\n $scope.course = course;\r\n manageCourseStatus($scope.dutyCourse, course, afterRefresh);\r\n toggleView('History'); //default\r\n\r\n\r\n if ($scope.trainees) {\r\n stickySelectedTrainee();\r\n //Check for status change (new trainees found on a submitted session (reset) || failed certificate trainees want to retake the test)\r\n if (afterRefresh && $scope.isCourseComplete && $scope.trainees.length) {\r\n CrewRouteFactory.setCoursePending(dutyNo, dutyDay, courseId, date);\r\n $scope.isCourseComplete = false;\r\n $route.reload();\r\n }\r\n }\r\n\r\n $scope.reload = false;\r\n $timeout(function () {\r\n $scope.reload = true;\r\n }, 100);\r\n\r\n });\r\n }\r\n \r\n function gotoCourse(course) {\r\n $location.path('/course/' + course.Id + '/' + groundDuty.DutyDateS + \"/\" + groundDuty.Id);\r\n }\r\n\r\n function gotoCrewRoute(){\r\n $location.path('/crewRoute/'+ dutyNo + '/' + dutyDay);\r\n }\r\n\r\n \r\n function refresh() {\r\n $scope.loading = true;\r\n\r\n if($scope.isOffline){\r\n $timeout(function () {\r\n $scope.loading = false;\r\n }, 100);\r\n $scope.refreshSuccess = false;\r\n $scope.availableCourseInfo = false;\r\n $scope.refreshErrorMsg = \"Online mode is required in order to get course. Please connect to the internet and try again.\";\r\n }\r\n else{\r\n CourseFactory.updateFlightCourseInfo(crewRouteCourse, date, dutyNo, dutyDay, function () {\r\n $scope.loading = false;\r\n $scope.refreshSuccess = true;\r\n $scope.availableCourseInfo = true;\r\n \r\n initCourse(true);\r\n $scope.reload = false;\r\n $timeout(function () {\r\n $scope.reload = true;\r\n }, 100);\r\n \r\n },\r\n function () {\r\n $scope.loading = false;\r\n $scope.refreshSuccess = false;\r\n $scope.availableCourseInfo = false;\r\n $scope.refreshErrorMsg = \"Something went wrong! Please Try again.\";\r\n },\r\n function (error) {\r\n console.log(error);\r\n $scope.loading = false;\r\n $scope.refreshSuccess = false;\r\n $scope.availableCourseInfo = false;\r\n\r\n $scope.refreshErrorMsg = \"Oops! Something went wrong!\";\r\n\r\n if(error.data.errorMessage){\r\n $scope.refreshErrorMsg = error.data.errorMessage;\r\n }\r\n }\r\n )\r\n }\r\n }\r\n\r\n function manageCourseStatus(dutyCourse, course, afterRefresh) {\r\n // COMPLETED : has been submitted\r\n var isCourseComplete = crewRouteCourse.Status == \"Completed\";\r\n\r\n // NEEDS SUBMIT : 1 hour has passed since the end of the course\r\n var now = moment.utc();\r\n if (!dutyCourse.IsCompleted) {\r\n var needsSubmit = false;\r\n var fetched = moment.utc(crewRouteDuty.DutyEnd);\r\n var duration = moment.duration(now.diff(fetched)).asHours();\r\n if (duration > 1) {\r\n needsSubmit = true;\r\n }\r\n }\r\n \r\n // LIMITED : no info available\r\n var isCourseLimited = !course || course.HasLimitedInfo || (course.HasLimitedSession && !afterRefresh);\r\n\r\n\r\n // OUTDATED : NeedsRefresh || 18 hours since last refresh\r\n var isCourseOutdated = false;\r\n if (course && course.FetchedTime) {\r\n var now = moment.utc();\r\n var fetched = moment.utc(course.FetchedTime);\r\n var duration = moment.duration(now.diff(fetched)).asHours();\r\n\r\n if (duration > 18 || course.NeedsRefresh) {\r\n isCourseOutdated = true;\r\n }\r\n }\r\n\r\n $scope.headerMsg = \"Refresh Course\";\r\n if(isCourseLimited) $scope.headerMsg = \"Fetch Course\";\r\n\r\n\r\n $scope.hasPendingTraining = !isCourseComplete;\r\n $scope.hasUnsetTraining = needsSubmit;\r\n $scope.isCourseLimited = isCourseLimited;\r\n $scope.isCourseComplete = isCourseComplete;\r\n $scope.isCourseOutdated = isCourseOutdated;\r\n $scope.hasNotifications = isCourseLimited || isCourseOutdated || isCourseComplete;\r\n }\r\n\r\n function stickySelectedTrainee(){\r\n if($scope.trainees && $scope.trainees.filter(x => !x.Session.Absent).length){\r\n if($scope.trainees.filter(x => !x.Session.Absent).find(x => x.Session.selected)){\r\n $scope.selectedTrainee = $scope.trainees.filter(x => !x.Session.Absent).find(x => x.Session.selected);\r\n }\r\n else{\r\n $scope.selectedTrainee = $scope.trainees.filter(x => !x.Session.Absent)[0];\r\n }\r\n }\r\n else{\r\n $scope.selectedTrainee = null;\r\n }\r\n if($scope.selectedTrainee) $scope.selectedTraineeBadge = {CrewId:$scope.selectedTrainee.CrewId};\r\n }\r\n\r\n\r\n function toggleView(mode){\r\n $scope.viewMode = mode;\r\n }\r\n }\r\n})();\r\n","(function () {\r\n\r\n a3_pilot_reports.directive('instructions', instructions);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name notifications\r\n * @restrict E\r\n * @description\r\n * Show selected module's trainee & instructor instructions\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function instructions($filter, $routeParams, $location) {\r\n function link(scope, attrs) {\r\n scope.warningMessageText = \"\";\r\n scope.viewModuleHistory = viewModuleHistory;\r\n\r\n if(!scope.course.isParallel){\r\n var currentActiveOrderNo = scope.selectedPhase.OrderNo;\r\n \r\n scope.course.CrewCoursePhases.forEach(function(phase){\r\n if(phase.OrderNo < currentActiveOrderNo && phase.Status != \"Completed\"){\r\n phase.SequentialWarning = true;\r\n }\r\n\r\n //check if phase has any history\r\n var oldSessions = [];\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function(trainee){\r\n var historyPhase = trainee.Phases.find(x => x.PhaseId == phase.PhaseId);\r\n if(historyPhase && historyPhase.Sessions) oldSessions = oldSessions.concat(historyPhase.Sessions);\r\n });\r\n\r\n phase.hasHistory = oldSessions.length>0;\r\n });\r\n }\r\n\r\n scope.course.CrewCoursePhases.forEach(function(phase){\r\n phase.StatusClass = '';\r\n \r\n if(phase.SequentialWarning){\r\n phase.StatusClass=\"panel-danger border-left-red\";\r\n phase.BtnClass=\"bg-red text-white\";\r\n }\r\n else if(phase.Status=='InProgress'){\r\n phase.StatusClass=\"border-left-blue\";\r\n phase.TextClass=\"text-blue\";\r\n phase.BtnClass=\"bg-blue text-white\";\r\n }\r\n else if(phase.Status=='Pending'){\r\n phase.StatusClass=\"border-left-gray \";\r\n phase.TextClass=\"text-gray\";\r\n phase.BtnClass=\"bg-gray text-white\";\r\n }\r\n else if(phase.Status=='Completed'){\r\n phase.StatusClass=\"border-left-green\";\r\n phase.TextClass=\"text-green\";\r\n phase.BtnClass=\"bg-green text-white\";\r\n }\r\n\r\n if(phase.PhaseId==scope.selectedPhase.PhaseId){\r\n phase.StatusClass= phase.StatusClass + \" panel-info\";\r\n }\r\n });\r\n\r\n var furtherAheadPhases = [];\r\n furtherAheadPhases = scope.course.CrewCoursePhases.filter(x => x.SequentialWarning);\r\n furtherAheadPhases = $filter('orderBy')(furtherAheadPhases, 'OrderNo');\r\n\r\n if(furtherAheadPhases.length>0){\r\n scope.course.SequenceWarning = true;\r\n scope.warningMessageText = \"\" + furtherAheadPhases[furtherAheadPhases.length-1].Title + \" is not completed. Confirm that you want to continue to \" + scope.selectedPhase.Title +\".\"\r\n }\r\n\r\n scope.traineeInstructions = scope.selectedPhase.TraineeInstructions;\r\n scope.examinerInstructions = scope.selectedPhase.ExaminerInstructions;\r\n scope.continueSubmission = continueSubmission;\r\n scope.cancelSubmission = cancelSubmission;\r\n\r\n function continueSubmission(){\r\n scope.course.SequenceWarning = false;\r\n }\r\n\r\n function cancelSubmission(){\r\n if(scope.isGround){\r\n gotoGroundDuty();\r\n }\r\n else{\r\n gotoCrewRoute();\r\n }\r\n\r\n }\r\n\r\n function gotoGroundDuty() {\r\n $location.path('/groundDuty/' + Number($routeParams.dutyId));\r\n }\r\n\r\n function gotoCrewRoute() {\r\n var dutyNo = scope.crewRouteDuty.DutyNo;\r\n var dutyDay = scope.crewRouteDuty.DutyDay;\r\n $location.path('/crewRoute/' + dutyNo + '/' + dutyDay);\r\n }\r\n\r\n function viewModuleHistory(phaseId){\r\n var courseId = Number($routeParams.courseId);\r\n var dutyId = Number($routeParams.dutyId);\r\n var date = $routeParams.date; \r\n \r\n\r\n if(dutyId) {\r\n $location.path('/groundHistory/' + courseId + '/' + dutyId + '/' + date + '/' + phaseId);\r\n }\r\n else {\r\n var dutyNo = scope.crewRouteDuty.DutyNo;\r\n var dutyDay = scope.crewRouteDuty.DutyDay; \r\n $location.path('/flightHistory/' + courseId + '/' + dutyNo + '/' + dutyDay + '/' + date + '/' + phaseId);\r\n } \r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/Training/instructions.tpl.html\",\r\n scope : false,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function() {\r\n\r\n a3_pilot_reports.directive('trainingMenu', trainingMenu);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name ground Course List\r\n * @restrict E\r\n * @description\r\n * Initialize navigation menu panel with with status indicators\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function trainingMenu(CourseFactory, GroundDutyFactory, FlightFactory, CrewRouteFactory, $location, TrainingSessionFactory, FlightSessionFactory, $filter, $routeParams) {\r\n function link($scope, attrs) {\r\n $scope.gotoCourse = gotoCourse;\r\n $scope.hasPendingTraining = false;\r\n $scope.hasUnsetTraining = false;\r\n\r\n var groundSessions = [];\r\n var flightSessions = [];\r\n TrainingSessionFactory.getAll(function(savedGroundSessions) {\r\n FlightSessionFactory.getAll(function(savedFlightSessions) {\r\n groundSessions = savedGroundSessions;\r\n flightSessions = savedFlightSessions;\r\n\r\n $scope.courses = [];\r\n var duty = null;\r\n var dutyCourses = [];\r\n\r\n if ($scope.type == 'ground') {\r\n duty = GroundDutyFactory.getGroundDutyFromStorage($scope.id);\r\n $scope.duty = duty;\r\n\r\n if (duty && duty.RelatedGroundDuties) {\r\n dutyCourses = GroundDutyFactory.getGroundDutyActiveCourses($scope.id);\r\n if (dutyCourses) {\r\n CourseFactory.getCoursesFromStorageByIds(dutyCourses.map(function(course) { return course.CourseId }), function(savedCourses) {\r\n manageGroundCourseStatuses(duty, dutyCourses, savedCourses);\r\n\r\n //Overall panel color\r\n if(savedCourses.some(x => x.Status == \"Draft\")){\r\n $scope.PanelClass=\"border-bottom-orange\";\r\n }\r\n else if(savedCourses.some(x => x.Status == \"Pending\" || x.Status == \"Outdated\")){\r\n $scope.PanelClass=\"border-bottom-blue\";\r\n }\r\n else{\r\n $scope.PanelClass=\"border-bottom-green\";\r\n }\r\n\r\n $scope.courses = savedCourses;\r\n });\r\n }\r\n }\r\n }\r\n else if($scope.type == 'crewroute' || $scope.type == 'flight'){\r\n if($scope.type == 'crewroute'){\r\n duty = CrewRouteFactory.getCrewRouteFromStorage($scope.dutyNo, $scope.dutyDay);\r\n }\r\n else{\r\n duty = FlightFactory.getFlightFromTotalFlights($scope.id);\r\n }\r\n if (duty && duty.Courses) {\r\n dutyCourses = duty.Courses;\r\n CourseFactory.getCoursesFromStorageByIds(dutyCourses.map(function(course) { return course.CourseId }), function(savedCourses) {\r\n dutyCourses.forEach(function(dutyCourse){\r\n var savedCourse = savedCourses.find(x => x.Id == dutyCourse.CourseId);\r\n \r\n var course = {\r\n Id: savedCourse.Id,\r\n Title : savedCourse.Title,\r\n Day: new moment(dutyCourse.Date)\r\n };\r\n\r\n manageFlightCourseStatus(course, dutyCourse);\r\n $scope.courses.push(course);\r\n });\r\n\r\n $scope.courses.forEach(function(course){\r\n course.FullDate = course.Day.format(\"YYYY-MM-DD\");\r\n course.Day = course.Day.format(\"DD/MM\");\r\n \r\n if($scope.courses.filter(x => x.Id == course.Id).length>1){\r\n course.IsMultiday = true;\r\n }\r\n \r\n });\r\n\r\n //Overall panel color\r\n if($scope.courses.some(x => x.Status == \"Draft\")){\r\n $scope.PanelClass=\"border-bottom-orange\";\r\n }\r\n else if($scope.courses.some(x => x.Status == \"Pending\" || x.Status == \"Outdated\")){\r\n $scope.PanelClass=\"border-bottom-blue\";\r\n }\r\n else{\r\n $scope.PanelClass=\"border-bottom-green\";\r\n }\r\n });\r\n }\r\n }\r\n \r\n });\r\n });\r\n\r\n function manageFlightCourseStatus(course, crewRouteCourse){\r\n var now=moment.utc();\r\n var flights = FlightFactory.getFlightsFromStorage().filter(x => crewRouteCourse.TrainingFlightIds.includes(x.FlightId));\r\n flights = $filter('orderBy')(flights, 'ScheduledArrival');\r\n var dutyEnd = flights[flights.length-1].ScheduledArrival;\r\n\r\n var dutyDate = new moment(crewRouteCourse.Date).format(\"YYYY-MM-DD\");\r\n\r\n var status=\"\";\r\n if(crewRouteCourse.Status == \"Pending\"){\r\n\r\n //Pending\r\n course.Status = \"Pending\";\r\n course.StatusClass = \"text-blue\";\r\n course.StatusDesc = \"pending\";\r\n \r\n //Outdated\r\n dutyEnd = moment.utc(dutyEnd);\r\n var duration = moment.duration(now.diff(dutyEnd)).asHours();\r\n if(duration>1){\r\n course.Status = \"Outdated\";\r\n }\r\n\r\n //Draft\r\n\t\t\t\t\tif(flightSessions && flightSessions.length){\r\n\t\t\t\t\t\tvar existingSession = flightSessions.find(s => s.courseId == crewRouteCourse.CourseId && s.day == dutyDate && s.dutyDay == $scope.dutyDay && s.dutyNo == $scope.dutyNo);\r\n\t\t\t\t\t\tif(existingSession && !existingSession.HasLimitedInfo && existingSession.trainees && existingSession.trainees.length){\r\n\t\t\t\t\t\t\t//a training session with trainees exists\r\n course.Status = \"Draft\"\r\n course.StatusClass = \"text-orange\";\r\n course.StatusDesc = \"draft\";\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n }else if(crewRouteCourse.Status == \"Completed\"){\r\n //Completed\r\n course.Status = \"Completed\";\r\n course.StatusClass = \"text-green\";\r\n course.StatusDesc = \"synced\";\r\n }\r\n\r\n return status;\r\n }\r\n\r\n function manageGroundCourseStatuses(duty, dutyCourses, courses) {\r\n var now = moment.utc();\r\n\r\n courses.forEach(function(course) {\r\n var dutyCourse = dutyCourses.find(x => x.CourseId == course.Id);\r\n course.Status = dutyCourse.Status;\r\n\r\n /*Statuses\r\n \tCompleted : session has been sent\r\n \tOutdated :\tsession submission is overdue\r\n \tDraft\t : session completion has started but not submitted\r\n \tPending : session submission not yet due\r\n */\r\n\r\n if (course.Status == \"Pending\") {\r\n course.StatusClass = \"text-blue\";\r\n course.StatusDesc = \"pending\";\r\n\r\n //Outdated\r\n var dutyEnd = moment.utc(duty.DutyEnd);\r\n var duration = moment.duration(now.diff(dutyEnd)).asHours();\r\n if (duration > 1) {\r\n course.Status = \"Outdated\"\r\n }\r\n\r\n //Draft\r\n if (groundSessions && groundSessions.length) {\r\n var existingSession = groundSessions.find(s => s.courseId == course.Id && s.day == duty.DutyDateS && s.dutyId == duty.Id);\r\n if (existingSession && !existingSession.HasLimitedInfo && existingSession.trainees && existingSession.trainees.length) {\r\n //a training session with trainees exists\r\n course.Status = \"Draft\"\r\n course.StatusClass = \"text-orange\";\r\n course.StatusDesc = \"draft\";\r\n }\r\n }\r\n \r\n } else if (course.Status == \"Completed\") {\r\n //Completed\r\n course.Status = \"Completed\";\r\n course.StatusClass = \"text-green\";\r\n course.StatusDesc = \"synced\";\r\n }\r\n });\r\n\r\n \r\n }\r\n\r\n /**\r\n * Redirect to Course Session\r\n */\r\n function gotoCourse(course) {\r\n if($scope.type==\"ground\"){\r\n $location.path('/groundcourse/' + course.Id + '/' + $scope.duty.Id + \"/\" + $scope.duty.DutyDateS);\r\n }\r\n else if($scope.type==\"crewroute\"){\r\n $location.path('/flightcourse/' + course.Id + '/' + $scope.dutyNo + '/' + $scope.dutyDay + '/' + course.FullDate);\r\n }\r\n else if($scope.type==\"flight\"){\r\n $location.path('/flightcourse/' + course.Id + '/' + $scope.dutyNo + '/' + $scope.dutyDay + '/' + course.FullDate + '/' + Number($routeParams.flightId));\r\n }\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/Training/training-menu.tpl.html\",\r\n scope: {\r\n type: '@',\r\n id: '=',\r\n dutyNo: '=',\r\n dutyDay: '='\r\n },\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('flexCombination',FlexCombination);\r\n\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name FlexCombination\r\n * @restrict E\r\n * @description\r\n * Implementation of Flex Combinations\r\n *\r\n * Initialize the Flex Combination of a season\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */ \r\nfunction FlexCombination($timeout) {\r\n \r\n function link(scope, element, attrs){\r\n \r\n \r\n angular.forEach(scope.seasonRequest.LeaveRequestPriorityPeriods, function (value, key) {\r\n var temp = value.MockLeaveRequestPrioritySlots;\r\n var temp2 = value.LeaveRequestPrioritySlots;\r\n\r\n $timeout(function(){\r\n value.MockLeaveRequestPrioritySlots = angular.fromJson(temp);\r\n value.LeaveRequestPrioritySlots= angular.fromJson(temp2);\r\n }) \r\n \r\n });\r\n \r\n scope.sortableOptions = {\r\n handle: '>.row .myHandle',\r\n update: function(e, ui) {\r\n },\r\n stop: function(e, ui) {\r\n for(var i=0; i< scope.seasonRequest.LeaveRequestPriorityPeriods.length;i++){ \r\n sortSetupOrderNo(scope.seasonRequest.LeaveRequestPriorityPeriods[i])\r\n }\r\n }\r\n }; \r\n \r\n \r\n \r\n scope.setupOrderNo = setupOrderNo;\r\n \r\n function sortSetupOrderNo(period){\r\n if(Array.isArray(period.LeaveRequestPrioritySlots)){\r\n for (var i=0; i0;\r\n \r\n for(var i=0;iSuccess
\",\r\n message :\"You have successfully submitted your leave request. You can modify your leave request untill the \" + closeDateStr + \".\",\r\n callback: function(){ $route.reload(); }\r\n });\r\n }\r\n \r\n function ShowErrorMessage(){\r\n bootbox.alert({title : \"
Error
\",\r\n message :\"Failed to send your leave request. Please try again later\",\r\n callback: function(){ $route.reload(); }\r\n });\r\n }\r\n \r\n function progressBarBox( isOpen ){\r\n if(isOpen){\r\n bootbox.dialog({\r\n closeButton: false,\r\n message: '
Please wait...
',\r\n //title: \"Please wait...\"\r\n });\r\n }else {\r\n bootbox.hideAll();\r\n }\r\n\r\n }\r\n \r\n/* function setupView() {\r\n if (!UserFactory.isLoggedIn()) {\r\n $location.path(\"/login\");\r\n }*/\r\n \r\n //$scope.sortableOptions['ui-floating'] = true;\r\n \r\n function updateLeaveRequestSeason(season){\r\n season.ConfigurationId = season.Configuration.Id\r\n for(var i=0;i $scope.LeaveRequestInformation.LeaveDays){\r\n $scope.invalidSelectedLeaveDays = true;\r\n bootbox.alert((\"

Warning!

You are entilted to \" + $scope.LeaveRequestInformation.LeaveDays + \" leave days but you have selected a combination of \" + totalDays + \" days. Please proceed with the necessary changes.\") \r\n\t\t\t\t);\r\n \r\n } else if (!$scope.QualificationGroup.RequestLessDays && (totalDays < $scope.LeaveRequestInformation.LeaveDays)){\r\n $scope.invalidSelectedLeaveDays = true; \r\n if(hasConfig){\r\n bootbox.alert((\"

Warning!

You are entilted to \" + $scope.LeaveRequestInformation.LeaveDays + \" leave days but you have selected a combination of \" + totalDays + \" days. Please proceed with the necessary changes.\") \r\n\t\t\t\t );\r\n }\r\n }\r\n else{\r\n $scope.invalidSelectedLeaveDays = false;\r\n }\r\n \r\n }\r\n \r\n function getRandomBorderColor(season){\r\n var cssClass = \"border-left-green\"\r\n \r\n if(!season.Configuration){\r\n cssClass = \"border-left-orange\";\r\n }\r\n \r\n return cssClass;\r\n }\r\n \r\n function getRandomTextColor(season){\r\n var cssClass = \"text-green\"\r\n \r\n if(!season.Configuration){\r\n cssClass = \"text-orange\";\r\n }\r\n \r\n return cssClass;\r\n }\r\n }\r\n \r\n \r\n\r\n\r\n\r\n})();","(function () {\r\n 'use strict';\r\n a3_pilot_reports.factory('LeaveRequestFactory', LeaveRequestFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name LeaveRequestFactory\r\n * @description \r\n * Get Leave Request Configuration Data and submit new Leave Request\r\n * @ngInject\r\n */\r\n function LeaveRequestFactory(GenericService, $http, $q, apiUrl) {\r\n\r\n \r\n var service = {\r\n getConfigurationDetails : getConfigurationDetails,\r\n saveLeaveRequestInformation : saveLeaveRequestInformation,\r\n getLeaveRequestInformation : getLeaveRequestInformation,\r\n saveLeaveRequest : saveLeaveRequest\r\n };\r\n \r\n /**\r\n * Initialize the LeaveRequestInformation\r\n * @memberof LeaveRequestFactory\r\n */\r\n function LeaveRequestInformation(){\r\n \r\n }\r\n \r\n var objType = 'LeaveRequestInformation';\r\n\t\tvar objCallback = LeaveRequestInformation; \r\n \r\n var leaveRequestApiURL = apiUrl + '/LeaveRequest';\r\n \r\n \r\n /**\r\n * Get the LeaveRequestInformation and the qualification Group\r\n * @memberof LeaveRequestFactory\r\n * @param {function} callback an on success callback function\r\n * @param {function} errorCallback an on error callback function\r\n */\r\n function getConfigurationDetails(callback,errorCallback) {\r\n return $http.get(leaveRequestApiURL, { 'Content-Type': 'application/json' })\r\n .then(function(responseData){\r\n if(responseData && responseData.data && responseData.data.data && responseData.data.data.LeaveRequestInformation){\r\n saveLeaveRequestInformation(responseData.data.data.LeaveRequestInformation);\r\n }\r\n callback(responseData);\r\n })\r\n .catch(errorCallback);\r\n }\r\n \r\n function saveLeaveRequest(request,callback,errorCallback){\r\n var cleanRequest = angular.toJson(request);\r\n return $http.post(leaveRequestApiURL,cleanRequest ,{ 'Content-Type': 'application/json' })\r\n .then(function(responseData){\r\n if(responseData && responseData.data && responseData.data.data && responseData.data.data.LeaveRequestInformation){\r\n saveLeaveRequestInformation(responseData.data.data.LeaveRequestInformation);\r\n }\r\n console.log(request);\r\n callback(responseData);\r\n })\r\n .catch(errorCallback);\r\n }\r\n /**\r\n * Save the leave Request Information Object in local storage\r\n * @memberof LeaveRequestFactory\r\n * @param {object} leaveRequestInformation a leaveRequestInformation\r\n */\r\n function saveLeaveRequestInformation(leaveRequestInformation){\r\n GenericService.saveOne(leaveRequestInformation,objType,objCallback);\r\n }\r\n \t\r\n /**\r\n * Save the leave Request Information Object in local storage\r\n * @memberof LeaveRequestFactory \r\n * @returns {object} leaveRequestInformation \r\n */\r\n function getLeaveRequestInformation(){\r\n return GenericService.getOne(objType,objCallback);\r\n }\r\n\r\n /* function postProposal(proposal){\r\n return $http.post(apiUrl + '/bucket/PostProposal/', proposal, { 'Content-Type' : 'application/json' });\r\n }\r\n */\r\n\r\n return service;\r\n }\r\n\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.controller('LeaveRequestInstructionsCtrl',LeaveRequestInstructionsCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name LeaveRequestInstructionsCtrl\r\n * @description \r\n * Get the Leave Request Instructions\r\n * @ngInject\r\n */\r\nfunction LeaveRequestInstructionsCtrl($scope, $uibModalInstance){\r\n\t\t$scope.page = 1;\r\n\t\t$scope.cancel = cancel;\r\n $scope.nextPage = nextPage;\r\n $scope.previousPage = previousPage;\r\n \r\n $scope.instructionPages = 6;\r\n \r\n /**\r\n * Goes to the next page of leave instructions\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\r\n function nextPage(){\r\n $scope.page = $scope.page + 1;\r\n normalizePage();\r\n }\r\n \r\n /**\r\n * Goes to the previous page of leave instructions\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\r\n function previousPage(){\r\n $scope.page = $scope.page - 1;\r\n normalizePage();\r\n }\r\n \r\n /**\r\n * Normalize the page number if it is out of range\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\r\n function normalizePage(){\r\n if($scope.page > $scope.instructionPages || $scope.page<1){\r\n $scope.page = 1;\r\n }\r\n }\r\n /**\r\n * Close the modal\r\n * @memberof LeaveRequestInstructionsCtrl\r\n */\r\n\t\tfunction cancel() {\r\n\t\t\t$uibModalInstance.close('close');\r\n\t\t};\r\n\t\t\r\n\t}\r\n })(); ","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.directive('specificCombinations',SpecificCombinations);\r\n\r\n \r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name SpecificCombinations\r\n * @restrict E\r\n * @description\r\n * Implementation of Specific Combinations\r\n *\r\n * Initialize the Specific Combinations of a season\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */ \r\nfunction SpecificCombinations($filter) {\r\n \r\n function link(scope, element, attrs){\r\n scope.IsEditEnabled = false;\r\n scope.selectEditablePeriod = selectEditablePeriod;\r\n scope.updateEditablePeriod = updateEditablePeriod;\r\n scope.removeSpecificCombination = removeSpecificCombination;\r\n scope.addNewSpecificCombination = addNewSpecificCombination;\r\n scope.getBorderClass = getBorderClass;\r\n scope.selectedSlotTemp = null;\r\n scope.isDisabled = isDisabled;\r\n \r\n scope.specificCombinations = $filter('filter')(scope.seasonRequests, {Type: 'All'});\r\n \r\n scope.sortableOptions = {\r\n handle: '> .row .myHandle',\r\n update: function(e, ui) {\r\n \r\n },\r\n stop: function(e, ui) {\r\n recalculatePriorities();\r\n }\r\n };\r\n \r\n \r\n \r\n function recalculatePriorities(){\r\n for(var i=0;i0){\r\n scope.selectedSlotTemp = period.LeaveRequestPrioritySlots[0];\r\n }else {\r\n scope.selectedSlotTemp = null;\r\n }\r\n scope.selectedRequestTemp = request;\r\n scope.selectedSlotDaysTemp = period.Days;\r\n period.isEditable = true;\r\n scope.IsEditEnabled = true;\r\n }else{\r\n resetEditablePeriods();\r\n }\r\n }\r\n \r\n function getBorderClass(request){\r\n var hasEmptyFields = false;\r\n var hasFilledFields = false;\r\n var cssClass= \"\";\r\n for (var i=0; i< request.LeaveRequestPriorityPeriods.length;i++){\r\n hasEmptyFields = hasEmptyFields || (!request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots || request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots.length==0);\r\n hasFilledFields = hasFilledFields || !(!request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots || request.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots.length==0);\r\n \r\n }\r\n \r\n if(hasEmptyFields && hasFilledFields ){\r\n cssClass = 'specific-combination-orange'\r\n request.HasInvalidPeriod = true;\r\n }else if(hasEmptyFields && !hasFilledFields){\r\n cssClass ='specific-combination-blue'\r\n request.HasInvalidPeriod = false;\r\n }else if (hasFilledFields && !hasEmptyFields){\r\n cssClass ='specific-combination-green'\r\n request.HasInvalidPeriod = false;\r\n }\r\n \r\n return cssClass;\r\n }\r\n \r\n function isDisabled(slot){\r\n var CSSclass=\"\";\r\n if(scope.selectedRequestTemp){\r\n for (var i=0; i< scope.selectedRequestTemp.LeaveRequestPriorityPeriods.length;i++){\r\n if( scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots && \r\n scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots.length>0 && (scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots[0].Id == slot.Id || \r\n (scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots[0].EndDay >=slot.StartDay &&\r\n scope.selectedRequestTemp.LeaveRequestPriorityPeriods[i].LeaveRequestPrioritySlots[0].StartDay <= slot.EndDay\r\n ) )\r\n ){\r\n CSSclass=\"disabled\";\r\n break;\r\n }\r\n }\r\n \r\n }\r\n \r\n return CSSclass;\r\n \r\n }\r\n \r\n \r\n function resetEditablePeriods(){\r\n for(var i=0;i 0){\r\n newSpecificCombinationPriority = scope.specificCombinations.length + 1;\r\n }\r\n var newObj= { Type : \"All\",\r\n Priority: newSpecificCombinationPriority,\r\n LeaveRequestPriorityPeriods : []\r\n }\r\n \r\n scope.seasonRequests.push(newObj);\r\n \r\n updateLeaveRequestSeason();\r\n \r\n scope.specificCombinations = $filter('filter')(scope.seasonRequests, {Type: 'All'});\r\n scope.IsEditEnabled = false;\r\n \r\n }\r\n \r\n function updateLeaveRequestSeason(){\r\n scope.seasonConfiguration.ConfigurationId = scope.seasonConfiguration.Configuration.Id\r\n for(var i=0;i 1 ? response.data.Message : \"Wrong UserName or password, please try again.\";\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t$scope.errorName = \"Wrong UserName or password, please try again.\";\r\n\t\t\t\t\t} else if (response.status == 404) {\r\n\t\t\t\t\t\t$scope.errorName = \"Could not reach the remote server for authentication. Please connect to the Internet and try again.\";\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t$scope.errorName = \"An error occured during authentication. Please make sure you are connected to the Internet and try again.\";\r\n\t\t\t\t\t};\r\n\t\t\t\t},\r\n\t\t\t\tfunction (response) {\r\n\t\t\t\t\tif (response.data && response.data.Message)\r\n\t\t\t\t\t\t$scope.errorName = response.data.Message.length > 1 ? response.data.Message : \"Could not extend your token\";\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\t$scope.errorName = \"Wrong UserName or password, please try again.\";\r\n\r\n\t\t\t\t});\r\n\t\t};\r\n\r\n /**\r\n * Redirect to reset view\r\n * @memberof LoginCtrl\r\n */\r\n\t\tfunction resetDevice() {\r\n\t\t\t$location.path(\"/reset\");\r\n\t\t}\r\n\r\n\t\t/**\r\n * Shows the token extension form\r\n * @memberof LoginCtrl\r\n */\r\n\t\tfunction showTokenExtensionForm() {\r\n\t\t\tvar username = $scope.formLogin.txtName.$modelValue;\r\n\t\t\tvar user = UserFactory.getUser();\r\n\t\t\tif (user.token && !user.tokenExtended && username === user.username)\r\n\t\t\t\t$scope.showTokenExtensionForm = true;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Extends the token\r\n\t\t * @memberof LoginCtrl\r\n\t\t */\r\n\t\tfunction extendToken() {\r\n\t\t\tUserFactory.extendToken(function () {\r\n\t\t\t\t$scope.errorName = \"\";\r\n\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t$scope.isLoggingIn = false;\r\n\t\t\t},\r\n\t\t\t\tfunction (response) {\r\n\t\t\t\t\tif (response.status === 401) {\r\n\t\t\t\t\t\tif (response.data && response.data.errorMessage) {\r\n\t\t\t\t\t\t\t$scope.errorName = response.data.Message;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\t$scope.errorName = 'We are sorry, we could not extend your token.'\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t);\r\n\t\t}\r\n\r\n\r\n\t\t/**\r\n\t\t * Shows the bootbox for extending the token\r\n\t\t * @memberof LoginCtrl\r\n\t\t */\r\n\t\tfunction showExtendTokenBootBox() {\r\n\t\t\tbootbox.dialog({\r\n\t\t\t\tmessage: `
We understand that you have forgot your password. We suggest you to contact with IT department in order to reset it. \r\n\t\t\t\tTill then we can try to give you limited access to the application. Do you want to proceed?


`,\r\n\t\t\t\ttitle: \"Forgot password\",\r\n\t\t\t\tbuttons: {\r\n\t\t\t\t\tconfirm: {\r\n\t\t\t\t\t\tlabel: ' Yes',\r\n\t\t\t\t\t\tclassName: \"btn-success\",\r\n\t\t\t\t\t\tcallback: function(){extendToken();}\r\n\t\t\t\t\t},\r\n\t\t\t\t\tcancel: {\r\n\t\t\t\t\t\tlabel: \"No\",\r\n\t\t\t\t\t\tclassName: \"btn-default\",\r\n\t\t\t\t\t\tcallback: function () { }\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t}\r\n\t}\r\n\r\n})(); ","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.service(\"PilotAPIService\", PilotAPIService)\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name PilotAPIService\r\n * @description \r\n * Api login service\r\n * @ngInject\r\n */ function PilotAPIService($http, $q, apiUrl) {\r\n\t return {\r\n /**\r\n * Login to Pilot Api\r\n * @memberof PilotAPIService\r\n * @param {number} username\r\n * @returns {string} password\r\n */\r\n\t login: function(username, password) {\r\n\t var call = $q.defer();\r\n\t \r\n\t\t $http.post(apiUrl +'/login', {'username': username, 'password': password}, {'Content-Type': 'application/json'})\r\n\t \r\n\t\t .then(\r\n\t\t\t function(responseData) {\r\n\t\t\t\tcall.resolve(responseData);\r\n\t\t\t },\r\n\t\t\t function(err) {\r\n\t\t\t\tcall.reject(err);\r\n\t\t\t }\r\n\t\t );\r\n\t return call.promise;\r\n\t }\r\n\t }\r\n\t}\r\n \r\n \r\n })(); ","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.factory('UserFactory', UserFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name UserFactory\r\n * @description \r\n * Add, Update, Delete and Get User.\r\n * @ngInject\r\n */\r\n\tfunction UserFactory($log, localStorageMD5Service, $http, apiUrl, PilotAPIService, DataCleanerFactory, GenericService) {\r\n\r\n /**\r\n * Initialize the User\r\n * @memberof UserFactory\r\n */\r\n\t\tfunction User() {\r\n\t\t\tthis.id = null;\r\n\t\t\tthis.aimsId = null;\r\n\t\t\tthis.username = null;\r\n\t\t\tthis.name = null;\r\n\t\t\tthis.shortname = null;\r\n\t\t\tthis.position = null;\r\n\t\t\tthis.hashedPwd = null;\r\n\t\t\tthis.token = null;\r\n\t\t\tthis.syncDialogLastDt = null;\r\n\t\t\tthis.getDescription = getDescription;\r\n\t\t\tthis.tokenExtended = false;\r\n\t\t}\r\n\r\n\t\tvar service =\r\n\t\t{\r\n\t\t\tgetUser: getUser,\r\n\t\t\tsetUser: setUser,\r\n\t\t\tisSecure: isSecure,\r\n\t\t\tisLoggedIn: isLoggedIn,\r\n\t\t\tclearActiveUser: clearActiveUser,\r\n\t\t\tsetActiveUser: setActiveUser,\r\n\t\t\tlogin: login,\r\n\t\t\textendToken: extendToken\r\n\t\t};\r\n\r\n\t\tvar objType = 'user';\r\n\t\tvar objCallback = User;\r\n\r\n\t\t//Object Functions\r\n\t\tfunction getDescription() {\r\n\t\t\tif (this.aimsid == null && this.name == null) return '-null-';\r\n\t\t\telse return (this.aimsid || '?') + ' - ' + (this.name || '?');\r\n\t\t}\r\n\r\n\t\t//Factory Functions\r\n /**\r\n * Get User \r\n * @memberof UserFactory\r\n * @returns {Object} User\r\n */\r\n\t\tfunction getUser() {\r\n\t\t\treturn GenericService.getOne(objType, objCallback);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t* Save User \r\n\t\t* @memberof UserFactory\r\n\t\t* @param {Object} User\r\n\t\t*/\r\n\t\tfunction setUser(user) {\r\n\t\t\tGenericService.saveAll(user, objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Checks if local storage is on secure mode \r\n * @memberof UserFactory\r\n * @param {boolean} isSecure\r\n */\r\n\t\tfunction isSecure() {\r\n\t\t\treturn localStorageMD5Service.isSecure();\r\n\t\t}\r\n\r\n /**\r\n * Check if user exists and he has logged in\r\n * @memberof UserFactory\r\n * @param {boolean} isLoggedIn\r\n */\r\n\t\tfunction isLoggedIn() {\r\n\t\t\tvar user = null;\r\n\t\t\ttry {\r\n\t\t\t\tuser = getUser();\r\n\t\t\t\tif (user != null) {\r\n\t\t\t\t\tvar act = localStorageMD5Service.get('active');\r\n\t\t\t\t\tif (!act || !act.aimsId || act.aimsId != user.aimsId) {\r\n\t\t\t\t\t\tuser = null;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else\r\n\t\t\t\t\tuser = null;\r\n\t\t\t} catch (e) {\r\n\t\t\t\tuser = null;\r\n\t\t\t}\r\n\t\t\treturn user;\r\n\t\t}\r\n\r\n /**\r\n * Clear Active User\r\n * @memberof UserFactory\r\n */\r\n\t\tfunction clearActiveUser() {\r\n\t\t\tlocalStorageMD5Service.remove('active');\r\n\t\t}\r\n\r\n /**\r\n * Save Active User \r\n * @memberof UserFactory\r\n * @param {Object} User\r\n */\r\n\t\tfunction setActiveUser(user) {\r\n\t\t\tif (user != null && user.aimsId != null) {\r\n\t\t\t\tvar value = { aimsId: user.aimsId };\r\n\t\t\t\tlocalStorageMD5Service.set('active', value);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\r\n /**\r\n * Add code to try to login locally if remote login fails with a 404 or timeout\r\n * @memberof UserFactory\r\n * @param {number} username The User Name\r\n * @param {string} password The User Password\r\n * @param {function} onsuccess callback function if the call is a success\r\n * @param {function} onerror callback function if the call failed\r\n * @param {function} onfinally callback function that runs on the end\r\n */\r\n\t\tfunction login(username, password, onsuccess, onerror, onfinally) {\r\n\r\n\t\t\tclearActiveUser();\r\n\t\t\tvar q = PilotAPIService.login(username, password);\r\n\t\t\tq.then(function (response) {\r\n\r\n\t\t\t\t// if the user that tries to log in is different than the last\r\n\t\t\t\t// logged in user, then reset all stored server data\r\n\t\t\t\tvar localUser = getUser();\r\n\t\t\t\tif (localUser != null && localUser.aimsId != null && localUser.aimsId.toString() != response.data.data.aimsId.toString()) {\r\n\t\t\t\t\tDataCleanerFactory.deleteAllData();\r\n\t\t\t\t}\r\n\t\t\t\t// delete any flights created locally, that do not have any local\r\n\t\t\t\t// reports\r\n\t\t\t\tDataCleanerFactory.deleteOrphanedLocalFlights();\r\n\r\n\t\t\t\t// assign the logged in user\r\n\t\t\t\tvar user = response.data.data;\r\n\t\t\t\t// save the hashed password for offline login\r\n\t\t\t\tuser.hashedPwd = password.getHash();\r\n\r\n\t\t\t\tsetUser(user);\r\n\t\t\t\tsetActiveUser(user);\r\n\t\t\t\tif (typeof (onsuccess) == \"function\") {\r\n\t\t\t\t\tonsuccess();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tq.catch(function (response) {\r\n\r\n\t\t\t\t// try to login using local cache\r\n\t\t\t\tif (response.status != 401) {\r\n\t\t\t\t\tvar newHashedPwd = password.getHash();\r\n\t\t\t\t\tvar usr = getUser();\r\n\t\t\t\t\t// check if we may try a local login, since the server is not\r\n\t\t\t\t\t// available\r\n\t\t\t\t\tif (usr != null && usr.username != null && usr.username == username && usr.hashedPwd != null) {\r\n\t\t\t\t\t\t// local login failed due to wrong password\r\n\t\t\t\t\t\tif (usr.hashedPwd != newHashedPwd) {\r\n\t\t\t\t\t\t\t// emulate response from server, when pass or userid is\r\n\t\t\t\t\t\t\t// incorrect\r\n\t\t\t\t\t\t\tresponse.status = 401;\r\n\t\t\t\t\t\t\tresponse.statusText = \"The username or password you entered is incorrect.\";\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tsetUser(usr);\r\n\t\t\t\t\t\t\tsetActiveUser(usr);\r\n\t\t\t\t\t\t\tif (typeof (onsuccess) == \"function\") {\r\n\t\t\t\t\t\t\t\tonsuccess();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\treturn q;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (typeof (onerror) == \"function\") {\r\n\t\t\t\t\tonerror(response);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tq.finally(function (response) {\r\n\t\t\t\tif (typeof (onfinally) == \"function\") {\r\n\t\t\t\t\tonfinally();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t\treturn q;\r\n\t\t}\r\n\r\n\r\n\t\t /**\r\n * the function that extends the token for limited time if a user forgot their password\r\n * @memberof UserFactory\r\n * @param {function} onsuccess callback function if the call is a success\r\n * @param {function} onerror callback function if the call failed\r\n */\r\n\t\tfunction extendToken(onsuccess, onerror) {\r\n\t\t\tvar user = getUser();\r\n\t\t\t$http.post(apiUrl + '/login/extendtoken', { 'Token': user.token }, { 'Content-Type': 'application/json' })\r\n\t\t\t\t.then(function (response) {\r\n\t\t\t\t\tuser.token = response.data.data;\r\n\t\t\t\t\tuser.tokenExtended = true;\r\n\t\t\t\t\tsetUser(user);\r\n\t\t\t\t\tsetActiveUser(user);\r\n\t\t\t\t\tif (typeof (onsuccess) == \"function\") {\r\n\t\t\t\t\t\tonsuccess();\r\n\t\t\t\t\t}\r\n\t\t\t\t}).catch(function (response) {\r\n\t\t\t\t\tif (typeof (onerror) == \"function\") {\r\n\t\t\t\t\t\tonerror(response);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\r\n\t\t}\r\n\t\treturn service;\r\n\t}\r\n\r\n\r\n\r\n})(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('CalendarRedirectModalCtrl', CalendarRedirectModalCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CalendarRedirectModalCtrl\r\n * @description \r\n * Modal to redirect to Calendar after all mandatory memos are read\r\n * @ngInject\r\n */\r\nfunction CalendarRedirectModalCtrl($scope, $location, $uibModalInstance) {\r\n $scope.gotoCalendar = gotoCalendar;\r\n\r\n \r\n function gotoCalendar(){\r\n cancel();\r\n $location.path('/');\r\n }\r\n \r\n /**\r\n * Closes modal\r\n * @memberof CalendarRedirectModalCtrl\r\n */\r\n function cancel() {\r\n $uibModalInstance.close('cancel');\r\n }\r\n }\r\n\r\n \r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('MandatoryModalCtrl', MandatoryModalCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name MandatoryModalCtrl\r\n * @description \r\n * Warning Modal about unread mandatory memos\r\n * @ngInject\r\n */\r\nfunction MandatoryModalCtrl($scope, mandatoryUnread, MemoFactory, $uibModal, $routeParams, $location, $uibModalInstance) {\r\n $scope.mandatoryUnread = mandatoryUnread;\r\n $scope.gotoMandatoryUnreadMemos = gotoMandatoryUnreadMemos;\r\n\r\n function gotoMandatoryUnreadMemos(){\r\n $location.path('/memos/unreadMandatory');\r\n cancel();\r\n }\r\n \r\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\r\n function cancel() {\r\n $uibModalInstance.close('cancel');\r\n }\r\n }\r\n\r\n \r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('MemoFactory', MemoFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name MemoFactory\r\n * @description \r\n * Add, Update, Delete and Get Memos.\r\n * @ngInject\r\n */\r\n function MemoFactory( FlightFactory, GroundDutyFactory, IndexedDBService, PaxInfoFactory, $q) {\r\n\r\n /**\r\n * Initialize the Memo\r\n * @memberof MemoFactory\r\n */\r\n function Memo() {\r\n this.Id = null;\r\n this.expired = false;\r\n }\r\n\r\n var objType = 'Memos';\r\n var objCallback = Memo;\r\n\r\n var service = {\r\n getMemosFromStorage: getMemosFromStorage,\r\n setMemosToStorage: setMemosToStorage,\r\n clearMemosFromStorage: clearMemosFromStorage,\r\n getMemosForFlight: getMemosForFlight,\r\n getStoredMemosIds: getStoredMemosIds,\r\n saveOneMemoToStorage: saveOneMemoToStorage,\r\n addMemoToStorage: addMemoToStorage,\r\n deleteMemoFromStorage: deleteMemoFromStorage,\r\n setMemosFromServer: setMemosFromServer,\r\n getMemosForGroundDuty: getMemosForGroundDuty,\r\n getMemosForCrewRoute: getMemosForCrewRoute,\r\n getUnreadMemos: getUnreadMemos,\r\n getMandatoryUnreadMemos: getMandatoryUnreadMemos,\r\n getAllUnreadGroundDutyMemos : getAllUnreadGroundDutyMemos,\r\n markGroundDutiesUnread : markGroundDutiesUnread,\r\n info: info\r\n };\r\n\r\n /**\r\n * Get Memos\r\n * @memberof MemoFactory\r\n * @param {function} callback \r\n */\r\n function getMemosFromStorage(callback) {\r\n //return GenericService.list(objType,objCallback);\r\n IndexedDBService.getAll(objType).then(function (results) {\r\n callback(results);\r\n });\r\n };\r\n\r\n /**\r\n * Set Memos\r\n * @memberof MemoFactory\r\n * @param {array} Memos a list of memos to set to indexedDB\r\n */\r\n function setMemosToStorage(Memos) {\r\n IndexedDBService.addAll(objType, Memos);\r\n };\r\n\r\n /**\r\n * Update Memo to Storage\r\n * @memberof MemoFactory\r\n * @param {object} Memo a memo\r\n */\r\n function saveOneMemoToStorage(Memo) {\r\n IndexedDBService.put(objType, Memo);\r\n };\r\n\r\n function info(){\r\n IndexedDBService.info(objType);\r\n }\r\n\r\n /**\r\n * Add Memo to Storage\r\n * @memberof MemoFactory\r\n * @param {object} Memo a memo\r\n */\r\n function addMemoToStorage(Memo) {\r\n IndexedDBService.add(objType, Memo);\r\n };\r\n\r\n /**\r\n * Delete Memo from Storage\r\n * @memberof MemoFactory\r\n * @param {number} MemoId The unique Identifier of the Memo\r\n */\r\n function deleteMemoFromStorage(MemoId) {\r\n IndexedDBService.remove(objType, MemoId);\r\n };\r\n\r\n /**\r\n * Clear Memo from Storage\r\n * @memberof MemoFactory\r\n */\r\n function clearMemosFromStorage() {\r\n IndexedDBService.removeAll(objType);\r\n };\r\n\r\n function ValidateCountryCategory( criteria, isDepartureCategory , isArrivalCategory ){\r\n var isValid = false;\r\n if ( criteria.Special == \"Specific\" ){\r\n isValid = ((criteria.Field == \"Intra\" && isDepartureCategory) || (criteria.Field == \"Extra\" && !isDepartureCategory))\r\n && ((criteria.FieldOptional == \"Intra\" && isArrivalCategory) || (criteria.FieldOptional == \"Extra\" && !isArrivalCategory));\r\n }\r\n else {\r\n if( criteria.Field == \"Intra\" ){\r\n isValid = (isDepartureCategory && criteria.Special != \"To\" ) || (isArrivalCategory && criteria.Special != \"From\");\r\n }\r\n else if ( criteria.Field == \"Extra\" ){\r\n isValid = (!isDepartureCategory && criteria.Special != \"To\" ) || (!isArrivalCategory && criteria.Special != \"From\");\r\n }\r\n }\r\n return isValid;\r\n }\r\n\r\n function isValid( field, departureField, arrivalField, special ){\r\n var isValid = false;\r\n\r\n var isDeparture = departureField == field;\r\n var isArrival = arrivalField == field;\r\n\r\n if(special == \"From\"){\r\n isValid = isDeparture\r\n }else if(special == \"To\" ){\r\n isValid = isArrival;\r\n }else {\r\n isValid = isArrival || isDeparture;\r\n }\r\n\r\n return isValid;\r\n }\r\n\r\n function getMemosForGroundDuty(Id, callback){\r\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(Id);\r\n\r\n if (!groundDuty) {\r\n return [];\r\n }\r\n\r\n getMemosFromStorage(function (results) {\r\n var memosCollection = results;\r\n var groundDutyMemos = [];\r\n\r\n var fromDutyDate = new Date(groundDuty.DutyDate).getTime();\r\n var toDutyDate = new Date(groundDuty.DutyDate).getTime();\r\n\r\n for (var i = 0; i < memosCollection.length; i++) {\r\n \r\n if (new Date(memosCollection[i].ValidFrom).getTime() <= fromDutyDate && new Date(memosCollection[i].ValidTo).getTime() >= toDutyDate) {\r\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\r\n var item = memosCollection[i].MemoCriteria[j];\r\n if(item.QueryType == \"GroundDutyCode\" && (item.Field == groundDuty.DutyNo || item.Field == groundDuty.GroundDutyNo )) {\r\n groundDutyMemos.push(memosCollection[i]);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n callback(groundDutyMemos);\r\n });\r\n }\r\n /**\r\n * Get Memos that are relate to this flight\r\n * @memberof MemoFactory\r\n * @param {number} Id The unique Identifier of the Memo\r\n * @param {function} callback The callback function\r\n */\r\n function getMemosForFlight(Id, callback) {\r\n var flight = FlightFactory.getFlightFromStorage(Id);\r\n if (!flight) {\r\n flight = FlightFactory.getLocalFlightFromStorage(Id);\r\n }\r\n\r\n if (!flight) {\r\n return [];\r\n }\r\n\r\n getMemosFromStorage(function (results) {\r\n var memosCollection = results;\r\n var flightMemos = [];\r\n PaxInfoFactory.getPaxInfoFromStorage(flight.FlightId, function (paxInfo) {\r\n for (var i = 0; i < memosCollection.length; i++) {\r\n \r\n if (new Date(memosCollection[i].ValidFrom).getTime() <= new Date(flight.ScheduledDeparture).getTime() && new Date(memosCollection[i].ValidTo).getTime() >= new Date(flight.ScheduledArrival).getTime()) {\r\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\r\n var item = memosCollection[i].MemoCriteria[j];\r\n if (\r\n (item.AcRegistration == flight.AcTailNo) ||\r\n (item.QueryType == \"Airport\" && isValid( item.Airport, flight.Departure, flight.Arrival, item.Special)) ||\r\n (item.FlightNo == flight.FlightNo) ||\r\n (item.AcType == flight.AcType) ||\r\n (isValidZone ( item, flight.Zones )) ||\r\n (item.RouteStart == flight.Departure && item.RouteEnd == flight.Arrival) ||\r\n (item.ViceVersa && (item.RouteStart == flight.Arrival && item.RouteEnd == flight.Departure)) ||\r\n (item.QueryType == \"Country\" && isValid( item.Country, flight.DepartureCountry, flight.ArrivalCountry, item.Special )) ||\r\n (item.QueryType == \"Schengen\" && ValidateCountryCategory( item, flight.DepartureSchengen, flight.ArrivalSchengen )) ||\r\n (item.QueryType == \"European\" && ValidateCountryCategory( item, flight.DepartureEU, flight.ArrivalEU )) ||\r\n (paxInfo && (item.QueryType == \"SsrCode\" && PassengersHasSsrCode(paxInfo, item))) || \r\n (item.QueryType == \"TrainingId\" && item.Field == flight.TrainingIndicatorId)\r\n ) {\r\n flightMemos.push(memosCollection[i]);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n callback(flightMemos);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Get Memos that are related to this crew route, by combining multiple flight and groundDuty memos \r\n * @memberof MemoFactory\r\n * @param {number} DutyNo Crew Route Identifier\r\n * @param {number} DutyDay Crew Route Day\r\n * @param {function} callback The callback function\r\n */\r\n function getMemosForCrewRoute(DutyNo, DutyDay, callback){\r\n var groundDuties = GroundDutyFactory.getGroundDutiesByDutyNo(DutyNo, DutyDay);\r\n var flights = FlightFactory.getFlightsByDutyNo(DutyNo, DutyDay);\r\n\r\n PaxInfoFactory.getAllPaxInfoFromStorage(function (paxInfoResult) {\r\n getMemosFromStorage(function (results) {\r\n var memosCollection = results;\r\n var allMemos = [];\r\n \r\n for (var i = 0; i < memosCollection.length; i++) {\r\n var inserted = false;\r\n //first check if memo is connected with any groundDuties\r\n for(var g = 0; g < groundDuties.length; g++){\r\n var fromDutyDate = new Date(groundDuties[g].DutyDate).getTime();\r\n var toDutyDate = new Date(groundDuties[g].DutyDate).getTime();\r\n if (new Date(memosCollection[i].ValidFrom).getTime() <= fromDutyDate && new Date(memosCollection[i].ValidTo).getTime() >= toDutyDate) {\r\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\r\n var item = memosCollection[i].MemoCriteria[j];\r\n if(item.QueryType == \"GroundDutyCode\" && (item.Field == groundDuties[g].DutyNo || item.Field == groundDuties[g].GroundDutyNo)){\r\n allMemos.push(memosCollection[i]);\r\n inserted = true;\r\n break;\r\n }\r\n }\r\n }\r\n if(inserted) break; //don't check other groundDuties - memo is already inserted\r\n }\r\n //if memo was checked for all groundDuties and was not connected with any, check in flights\r\n if(!inserted){\r\n for(var f = 0; f < flights.length; f++){\r\n var paxInfo = null;\r\n if (new Date(memosCollection[i].ValidFrom).getTime() < new Date(flights[f].ScheduledDeparture).getTime() && new Date(memosCollection[i].ValidTo).getTime() > new Date(flights[f].ScheduledArrival).getTime()) {\r\n //check if flight has paxInfo \r\n for(var p = 0; p < paxInfoResult.length; p++){\r\n if(paxInfoResult[p].FlightId == flights[f].FlightId){\r\n paxInfo = paxInfoResult[p];\r\n break;\r\n }\r\n }\r\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\r\n var item = memosCollection[i].MemoCriteria[j];\r\n if (\r\n (item.AcRegistration == flights[f].AcTailNo) ||\r\n (item.QueryType == \"Airport\" && isValid( item.Airport, flights[f].Departure, flights[f].Arrival, item.Special)) ||\r\n (item.FlightNo == flights[f].FlightNo) ||\r\n (item.AcType == flights[f].AcType) ||\r\n (isValidZone ( item.Zone, flights[f].Zones )) ||\r\n (item.RouteStart == flights[f].Departure && item.RouteEnd == flights[f].Arrival) ||\r\n (item.ViceVersa && (item.RouteStart == flights[f].Arrival && item.RouteEnd == flights[f].Departure)) ||\r\n (item.QueryType == \"Country\" && isValid( item.Country, flights[f].DepartureCountry, flights[f].ArrivalCountry, item.Special )) ||\r\n (item.QueryType == \"Schengen\" && ValidateCountryCategory( item, flights[f].DepartureSchengen, flights[f].ArrivalSchengen )) ||\r\n (item.QueryType == \"European\" && ValidateCountryCategory( item, flights[f].DepartureEU, flights[f].ArrivalEU )) ||\r\n (paxInfo && (item.QueryType == \"SsrCode\" && PassengersHasSsrCode(paxInfo, item))) || \r\n (item.QueryType == \"TrainingId\" && item.Field == flights[f].TrainingIndicatorId)\r\n ) {\r\n allMemos.push(memosCollection[i]);\r\n inserted = true;\r\n break;\r\n }\r\n }\r\n }\r\n if(inserted) break; //don't check other flights - memo is already inserted\r\n }\r\n }\r\n }\r\n callback(allMemos);\r\n });\r\n });\r\n\r\n }\r\n \r\n function PassengersHasSsrCode(paxInfo, memoCriterion) {\r\n var retVal = false;\r\n for (var key in paxInfo.PassengerSummaryY){\r\n if(key === memoCriterion.Field && paxInfo.PassengerSummaryY[key] > 0){\r\n retVal = true;\r\n break;\r\n }\r\n }\r\n for (var key in paxInfo.PassengerSummaryX){\r\n if(key === memoCriterion.Field && paxInfo.PassengerSummaryY[key] > 0){\r\n retVal = true;\r\n break;\r\n }\r\n }\r\n return retVal;\r\n }\r\n\r\n /**\r\n * Check if the zone is valid\r\n * @memberof MemoFactory\r\n * @param {CriteriaZone} Zone from MemoCriteria\r\n * @param {FlightZones} List of Zones from flight\r\n */\r\n function isValidZone ( CriteriaZone, FlightZones ){ \r\n if(!CriteriaZone || CriteriaZone.Type != \"Zone\" || !FlightZones || FlightZones.length == 0){\r\n return false;\r\n }else{\r\n // some is equivalent to Any()\r\n var zoneExist = FlightZones.some(function (item) {\r\n return item.Title.toUpperCase() == CriteriaZone.Field.toUpperCase() && item.Class.toUpperCase() == CriteriaZone.FieldOptional.toUpperCase();\r\n });\r\n return zoneExist;\r\n }\r\n }\r\n\r\n /**\r\n * Get Stored Memos \r\n * @memberof MemoFactory\r\n * @param {function} callback The callback function\r\n */\r\n function getStoredMemosIds(callback) {\r\n getMemosFromStorage(function (memos) {\r\n var memoIds = [];\r\n for (var i = 0; i < memos.length; i++) {\r\n\r\n var memoIdRead={\r\n Id:memos[i].Id,\r\n ReadDt:memos[i].ReadDt\r\n }\r\n\r\n memoIds.push(memoIdRead);\r\n }\r\n callback(memoIds);\r\n });\r\n }\r\n\r\n /**\r\n * set memos from server api \r\n * @memberof MemoFactory\r\n * @param {array} memos The memos \r\n * @param {array} memoIdsToSend The old memos of the storage\r\n * @param {string} lastSyncDate The last Sync Date \r\n */\r\n function setMemosFromServer(memos, memoIdsToSend, lastSyncDate) {\r\n if (!memoIdsToSend || memoIdsToSend.length == 0 || !lastSyncDate) {\r\n setMemosToStorage(memos);\r\n } else {\r\n for (var j = 0; j < memos.length; j++) {\r\n var IsMemoIncluded = false;\r\n\r\n for (var h = 0; h < memoIdsToSend.length; h++) {\r\n if (memos[j].Id == memoIdsToSend[h].Id) {\r\n IsMemoIncluded = true;\r\n break;\r\n }\r\n }\r\n\r\n if (IsMemoIncluded) {\r\n memos[j].IsUpdated = true;\r\n memos[j].IsNew = false;\r\n saveOneMemoToStorage(memos[j]);\r\n } else {\r\n memos[j].IsNew = true;\r\n memos[j].IsUpdated = false;\r\n addMemoToStorage(memos[j]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get Unread Memos \r\n * @memberof MemoFactory\r\n */\r\n function getUnreadMemos(callback) {\r\n getMemosFromStorage(function(memos){\r\n if (!memos)\r\n\t\t\t\treturn [];\r\n\r\n var result = [];\r\n var arrayLength = memos.length;\r\n\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (!memos[i].ReadDt) {\r\n result.push(memos[i]);\r\n }\r\n }\r\n callback(result);\r\n });\r\n }\r\n \r\n /**\r\n * Get Unread Mandatory Memos\r\n * @memberof MemoFactory\r\n */\r\n function getMandatoryUnreadMemos(callback) {\r\n getMemosFromStorage(function(memos){\r\n if (!memos)\r\n\t\t\t\treturn [];\r\n\r\n var result = [];\r\n var arrayLength = memos.length;\r\n\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (!memos[i].ReadDt && memos[i].IsMandatory) {\r\n result.push(memos[i]);\r\n }\r\n }\r\n callback(result);\r\n });\r\n }\r\n\r\n /**\r\n * Gets all unread memos related to a Ground Duty\r\n * @memberof MemoFactory\r\n */\r\n function getAllUnreadGroundDutyMemos(callback){\r\n getMemosFromStorage(function (results) {\r\n var memosCollection = results;\r\n var unreadGroundDutyMemos = [];\r\n for (var i = 0; i < memosCollection.length; i++) {\r\n for (var j = 0; j < memosCollection[i].MemoCriteria.length; j++) {\r\n var item = memosCollection[i].MemoCriteria[j];\r\n if(item.QueryType == \"GroundDutyCode\" && memosCollection[i].ReadDt == null) {\r\n unreadGroundDutyMemos.push(memosCollection[i]);\r\n break;\r\n }\r\n }\r\n \r\n }\r\n callback(unreadGroundDutyMemos);\r\n });\r\n }\r\n\r\n /**\r\n * Flags Ground Duties if they have at least one unread memo\r\n * @memberof MemoFactory\r\n */\r\n function markGroundDutiesUnread(){\r\n getAllUnreadGroundDutyMemos(function(groundDutyMemos){\r\n \r\n var groundDuties = GroundDutyFactory.getGroundDutiesFromStorage();\r\n \r\n if (groundDuties != null){\r\n for(var i = 0; i < groundDuties.length; i++){\r\n groundDuties[i].Unread = false;\r\n \r\n //check if this ground duty has any unread ground duty memo\r\n var fromDutyDate = new Date(groundDuties[i].DutyDate).getTime();\r\n var toDutyDate = new Date(groundDuties[i].DutyDate).getTime();\r\n \r\n for (var j = 0; j < groundDutyMemos.length; j++) {\r\n if (new Date(groundDutyMemos[j].ValidFrom).getTime() <= fromDutyDate && new Date(groundDutyMemos[j].ValidTo).getTime() >= toDutyDate) {\r\n for (var z = 0; z < groundDutyMemos[j].MemoCriteria.length; z++) {\r\n var item = groundDutyMemos[j].MemoCriteria[z];\r\n if((item.Field == groundDuties[i].DutyNo || item.Field == groundDuties[i].GroundDutyNo)) {\r\n groundDuties[i].Unread = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n GroundDutyFactory.setGroundDutiesToStorage(groundDuties);\r\n }\r\n });\r\n }\r\n\r\n return service;\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('MemoImagesFactory', MemoImagesFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name MemoImagesFactory\r\n * @description \r\n * Add, Update, Delete and Get Memo's Images.\r\n * @ngInject\r\n */ \r\nfunction MemoImagesFactory(GenericService, IndexedDBService) {\r\n\r\n /**\r\n * Initialize the MemoImage\r\n * @memberof MemoImagesFactory\r\n */\r\n function MemoImage() {\r\n\t\t\tthis.Id = null;\r\n\t\t}\r\n\r\n\t\tvar objType = 'MemoImages';\r\n\t\tvar objCallback = MemoImage;\r\n\r\n\t\tvar service = \r\n\t\t{ \r\n\t\t\tgetMemoImagesFromStorage : getMemoImagesFromStorage,\r\n\t\t\tsetMemoImagesToStorage : setMemoImagesToStorage,\r\n\t\t\tsaveOneMemoImageToStorage : saveOneMemoImageToStorage,\r\n\t\t\taddMemoImageToStorage : addMemoImageToStorage,\r\n\t\t\tdeleteMemoImageFromStorage : deleteMemoImageFromStorage,\r\n\t\t\tdeleteMemoImageByMemoId : deleteMemoImageByMemoId,\r\n\t\t\tsetImagesToServer : setImagesToServer,\r\n\t\t\tclearMemoImagesFromStorage : clearMemoImagesFromStorage,\r\n getMemoImagesByIndex : getMemoImagesByIndex\r\n\t\t};\r\n \r\n /**\r\n * Get Memo Images \r\n * @memberof MemoImagesFactory\r\n * @param {function} callback \r\n */\t\t\r\n\t\tfunction getMemoImagesFromStorage(callback) {\r\n\t\t\t//return GenericService.list(objType,objCallback);\r\n\t\t\tIndexedDBService.getAll(objType).then(function(results){\r\n\t\t\t\tcallback(results);\r\n\t\t\t});\r\n\t\t};\r\n \r\n /**\r\n * Get Memo Images by memo Id\r\n * @memberof MemoImagesFactory\r\n * @param {number} id Memo Id \r\n * @param {function} callback \r\n */\r\n function getMemoImagesByIndex(id,callback) {\r\n\t\t\t//return GenericService.list(objType,objCallback);\r\n\t\t\tIndexedDBService.getByIndex(objType,'memoId',id).then(function(results){\r\n\t\t\t\tcallback(results);\r\n\t\t\t});\r\n\t\t};\r\n\r\n /**\r\n * Add Memo Images \r\n * @memberof MemoImagesFactory\r\n * @param {array} MemoImages List of memo images\r\n */\r\n\t\tfunction setMemoImagesToStorage(MemoImages) {\r\n\t\t\t//GenericService.saveAll(Memos,objType,objCallback);\r\n\t\t\tIndexedDBService.addAll(objType, MemoImages);\r\n\t\t};\r\n \r\n /**\r\n * Update Memo Images \r\n * @memberof MemoImagesFactory\r\n * @param {object} MemoImage a memo image\r\n */\t\r\n function saveOneMemoImageToStorage(MemoImage){\r\n\t\t\tIndexedDBService.put(objType, MemoImage);\r\n\t\t};\r\n \r\n /**\r\n * Add Memo Image\r\n * @memberof MemoImagesFactory\r\n * @param {object} MemoImage a memo image\r\n */\r\n\t\tfunction addMemoImageToStorage(MemoImage){\r\n\t\t\tIndexedDBService.add(objType, MemoImage);\r\n\t\t};\r\n\r\n /**\r\n * Delete Memo Image\r\n * @memberof MemoImagesFactory\r\n * @param {number} MemoImageId a memo image Id\r\n */\r\n\t\tfunction deleteMemoImageFromStorage(MemoImageId){\r\n\t\t\tIndexedDBService.remove(objType, MemoImageId);\r\n\t\t};\r\n \r\n /**\r\n * Delete Memo Image by MemoId\r\n * @memberof MemoImagesFactory\r\n * @param {number} MemoId a memo Id\r\n */\r\n function deleteMemoImageByMemoId(MemoId){\r\n\t\t\tIndexedDBService.removeByIndex(objType,'memoId', MemoId);\r\n\t\t};\r\n \r\n /**\r\n * Set Memo Image by api call\r\n * @memberof MemoImagesFactory\r\n * @param {array} images List of memo images\r\n */ \r\n function setImagesToServer(images){\r\n for(var i=0;i 0) {\r\n\t\t\t\t\tmemos.push({ Category: memo.Category, memoList: [memo], filterList: [memo] });\r\n\t\t\t\t}\r\n\t\t\t\telse if (memos.filter(function (e) { return e.Category == memo.Category }).length > 0) {\r\n\t\t\t\t\t\r\n\t\t\t\t\tmemos.filter(function (object) {\r\n\t\t\t\t\t\tif (object.Category == memo.Category) {\r\n\t\t\t\t\t\t\treturn object;\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t})[0].memoList.push(memo);\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn memos.dynamicSort(\"Category\", true);\r\n\t\t}\r\n\r\n\t\tfunction select(category){\r\n\t\t\tselectMemoCategory(category);\r\n\t\t\ttoggleSidePanel();\r\n\t\t}\r\n\r\n\t\tfunction selectMemoCategory(category){\r\n\t\t\tvar memosByCategory = $scope.memosByCategory;\r\n\t\t\tfor(var i = 0; i < memosByCategory.length; i++){\r\n\t\t\t\tif(memosByCategory[i].Category == category.Category){\r\n\t\t\t\t\t$scope.selected = memosByCategory[i];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfunction toggleSidePanel(){\r\n\t\t\t$scope.shownSideMenu = !$scope.shownSideMenu;\r\n\t\t}\r\n\r\n\t\t//Pagination\r\n\t\t$scope.pageOptions = [\r\n\t\t\t\t{ name: '5', value: '5' }, \r\n\t\t\t\t{ name: '8', value: '8' }, \r\n\t\t\t\t{ name: '15', value: '15' },\r\n\t\t\t\t{ name: '30', value: '30' },\r\n\t\t\t\t{ name: '50', value: '50' }\r\n\t\t];\r\n \r\n\t\t$scope.viewby = $scope.pageOptions[1].value;\r\n\t\t$scope.currentPage = 1;\r\n\t\t$scope.itemsPerPage = $scope.viewby;\r\n\t\t$scope.maxSize = 5; //Number of pager buttons to show\r\n\t\t$scope.setPage = setPage;\r\n\t\t$scope.setItemsPerPage = setItemsPerPage;\r\n\r\n\t\t//Controller functions\r\n \r\n /**\r\n * Set pagination page number\r\n * @memberof MemosCtrl\r\n * @param {number} pageNo list page number\r\n */\r\n\t\tfunction setPage(pageNo) {\r\n\t\t\t$scope.currentPage = pageNo;\r\n\t\t}\r\n\r\n /**\r\n * Set items per page \r\n * @memberof MemosCtrl\r\n * @param {number} num the Number of items to show per page\r\n */\r\n\t\tfunction setItemsPerPage(num) {\r\n\t\t\t$scope.itemsPerPage = num;\r\n\t\t\t$scope.currentPage = 1; //reset to first paghe\r\n\t\t}\r\n\r\n /**\r\n * View Selected Memo\r\n * @memberof MemosCtrl\r\n * @param {object} memo The selected Memo\r\n */\r\n\t\tfunction openMemo(memo) {\r\n\t\t\tvar modalInstance = $uibModal.open({\r\n\t\t\t\ttemplateUrl: 'views/Memos/dlgMemo.html',\r\n\t\t\t\tcontroller: 'MemoModalCtrl',\r\n\t\t\t\tsize: 'lg',\r\n\t\t\t\tkeyboard: false,\r\n\t\t\t\tresolve: {\r\n\t\t\t\t\tmemo: function() {\r\n\t\t\t\t\t\treturn memo;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tmodalInstance.result.then(function() {\r\n\t\t\t\tif (memo.ReadDt == null) {\r\n\t\t\t\t\tmemo.ReadDt = new Date();\r\n\t\t\t\t\tMemoFactory.saveOneMemoToStorage(memo);\r\n //check if memo is connected to a ground duty\r\n for (var i = 0; i < memo.MemoCriteria.length; i++) {\r\n var item = memo.MemoCriteria[i];\r\n if(item.QueryType == \"GroundDutyCode\") {\r\n MemoFactory.markGroundDutiesUnread();\r\n break;\r\n }\r\n }\r\n\r\n\t\t\t\t\tsearchMemos($scope.searchText, '');\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t}\r\n\t\t\r\n\t\tfunction redirectModal(){\r\n\t\t\tvar modalInstance = $uibModal.open({\r\n\t\t\t\ttemplateUrl: 'views/Memos/dlgCalendarRedirect.html',\r\n\t\t\t\tcontroller: 'CalendarRedirectModalCtrl',\r\n\t\t\t\tbackdrop: 'static',\r\n\t\t\t\tsize: 'md',\r\n\t\t\t\tkeyboard: false\r\n\t\t\t});\r\n\t\t}\r\n\r\n /**\r\n * Search the selected text In Memo Title and body\r\n * @memberof MemosCtrl\r\n * @param {string} text The desired search text\r\n */\r\n\t\tfunction searchMemos(text, filter) {\r\n\t\t\tif(filter != ''){\r\n\t\t\t\t$scope.radioModel = filter;\r\n\t\t\t}\r\n\t\t\tvar filteredMemos = [];\r\n\t\t\tvar searchText = text.toLowerCase();\r\n var newList = $scope.memos;\r\n\t\t\tfor(var i=0;i0){\r\n continue;\r\n }\r\n }\r\n else if($scope.radioModel == 'Unread'){\r\n\t\t\t\t\tif(newList[i].ReadDt){\r\n continue;\r\n }\r\n\t\t\t\t}\r\n\t\t\t\telse if($scope.radioModel == 'Mandatory'){\r\n\t\t\t\t\tif(!newList[i].IsMandatory){\r\n continue;\r\n }\r\n\t\t\t\t}\r\n\t\t\t\telse if($scope.radioModel == 'UnreadMandatory'){\r\n\t\t\t\t\tif(newList[i].ReadDt || !newList[i].IsMandatory){\r\n continue;\r\n }\r\n\t\t\t\t}\r\n\t\t\t\tvar memoTitle = newList[i].Title.toLowerCase();\r\n\t\t\t\tvar memoBody = newList[i].Body.toLowerCase();\r\n\r\n\t\t\t\tif(memoTitle.indexOf(searchText) > -1){\r\n\t\t\t\t\tfilteredMemos.push(newList[i]);\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif(memoBody.indexOf(searchText) > -1){\r\n\t\t\t\t\tfilteredMemos.push(newList[i]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tvar memosByCategory = MemosByCategories(filteredMemos);\r\n\t\t\t$scope.memosByCategory = memosByCategory;\r\n\r\n\t\t\tsearchResultsCount();\r\n\t\t\t\r\n\t\t\tif(!memosByCategory.length){\r\n\t\t\t\t$scope.selected == null\t\t//selected could be null if search didn't return any results\r\n\t\t\t\tif($scope.radioModel=='UnreadMandatory'){\t//all mandatory memos were read\r\n\t\t\t\t\t// $scope.radioModel = 'All';\r\n\t\t\t\t\t// searchMemos(searchText, '');\r\n\t\t\t\t\tredirectModal();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if($scope.selected == null){ //search now returns results\r\n\t\t\t\t$scope.selected = memosByCategory[0];\t\r\n\t\t\t}\r\n\r\n\t\t\tvar select = false;\r\n\t\t\tfor(var i = 0; i < memosByCategory.length; i++){\r\n\t\t\t\tif($scope.selected.Category == memosByCategory[i].Category){\r\n\t\t\t\t\tselectMemoCategory(memosByCategory[i]);\r\n\t\t\t\t\tselect = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif(!select)\t$scope.selected = memosByCategory[0];\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n \r\n})();","(function() {\r\n 'use strict';\r\n \r\n \r\n a3_pilot_reports.controller('MessageCtrl',MessageCtrl);\r\n \r\n/* @ngInject */ \r\nfunction MessageCtrl($scope, $location, MessageFactory, $filter, $sce) {\r\n\t\t\t\t\r\n var messages = [];\r\n\r\n $scope.messages = MessageFactory.getMessagesFromStorage();\r\n messages = $scope.messages;\r\n\r\n $scope.state = 'messages'\r\n\r\n //Initialized scope variables\r\n\r\n $scope.openMessage = openMessage;\r\n $scope.isEnabled = false;\r\n\r\n $scope.messageCount = messages.length;\r\n\r\n $scope.trustAsHtml = trustAsHtml;\r\n \r\n $scope.setupView = setupView;\r\n \r\n /**\r\n * Trust this html style text\r\n * @memberof MessageCtrl\r\n * @param {string} body The body message\r\n */ \r\n function trustAsHtml(body){\r\n return $sce.trustAsHtml(body);\r\n }\r\n\r\n /**\r\n * Setup the message View\r\n * @memberof MessageCtrl\r\n * @param {boolean} isEnabled Show only unread messages\r\n */ \r\n function setupView(isEnabled) {\r\n $scope.messages = $filter('messageFilter')(messages, isEnabled);\r\n }\r\n\r\n /**\r\n * View Selected message\r\n * @memberof MessageCtrl\r\n * @param {object} message The selected Message\r\n */\r\n function openMessage(message) {\r\n if (message.ReadDt == null) {\r\n MessageFactory.markReaden(message.Id);\r\n message.ReadDt = new Date();\r\n }\r\n }\r\n\r\n};\r\n\t\t\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.filter('messageFilter', messageFilter);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name messageFilter\r\n * @description \r\n * Filters messages in order to show only the unread.\r\n * @ngInject\r\n */\r\nfunction messageFilter () {\r\n\treturn function(input,isEnable) {\r\n\t\t\t\tif (isEnable) {\r\n\t\t\t\t\t\tvar result = []; \r\n\t\t\t\t\t\tfor (var i = 0; i 0){\r\n\t\t\t\tfiltered = [];\r\n\t\t\t\tfor (var i=0;i3600000){\r\n\t\t\t\t\tIsOld=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn IsOld;\r\n\t\t}\r\n\r\n /**\r\n * Close the modal\r\n * @memberof PassengerCtrl\r\n */\r\n\t\tfunction cancel() {\r\n\t\t\t$uibModalInstance.dismiss('');\r\n\t\t}\r\n\t}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('PaxCtrl',PaxCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name PaxCtrl\r\n * @description \r\n * Manages the passenger seatmap and information view\r\n * @ngInject\r\n */\r\nfunction PaxCtrl($scope, FlightFactory, PaxInfoFactory, $routeParams, $uibModal, $location) {\r\n\t\tvar flightId = $routeParams.flightId;\r\n\t\tvar flight = FlightFactory.getFlightFromStorage(flightId);\r\n\t\tvar paxInfo = PaxInfoFactory.getPaxInfoFromStorage(flightId);\r\n\r\n\t\t$scope.state='pax';\r\n\t\t$scope.flight = flight;\r\n\t\t$scope.showMobileMenuFilters = false;\r\n\t\t$scope.filterPax = filterPax;\r\n\t\t$scope.viewMode = viewMode;\r\n\t\t$scope.filterRow = filterRow;\r\n\t\t$scope.filterCol = filterCol; \r\n\t\t$scope.paxInfo = paxInfo;\r\n\t\t$scope.howClose = '';\r\n\t\t$scope.IsOld = IsOld;\r\n\t\t$scope.openPassenger = openPassenger;\r\n\t\t$scope.resetFilters = resetFilters;\r\n\t\t$scope.isConnectedFlightClose = isConnectedFlightClose;\r\n\t\t$scope.TimeDifference = TimeDifference;\r\n $scope.IsProvisional = true;\r\n $scope.specialMeals = 0;\r\n \r\n\t\tif (flight==null){\r\n\t\t\tflight = FlightFactory.getLocalFlightFromStorage(flightId)\r\n\t\t}\r\n \r\n if (flight!=null){ \r\n if(paxInfo){\r\n var connectingPax = 0;\r\n for(var i=0;i3600000){\r\n\t\t\t\t\t\tIsOld=true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn IsOld;\r\n\t\t}\r\n\r\n /**\r\n * Calculates if a connecting flight is departs sort time after fligths arrival \r\n * @memberof PaxCtrl\r\n * @param {string} connection Connection STD\r\n * @return {string} cssClass\r\n */\r\n\t\t function isConnectedFlightClose(connection) {\r\n if (!connection) {\r\n return '';\r\n }\r\n\r\n var connFlightDate = new Date(connection.STD).getTime();\r\n\r\n if ($scope.flightETA > connFlightDate)\r\n return '';\r\n\r\n if ((connFlightDate - $scope.flightETA) < connection.MCT * 60000) {\r\n return 'bg-bisque';\r\n }\r\n\r\n if ((connFlightDate - $scope.flightETA) < (connection.MCT+15) * 60000) {\r\n return 'bg-cornsilk';\r\n }\r\n return '';\r\n }\r\n\r\n /**\r\n * Returns the time difference\r\n * @memberof PaxCtrl\r\n * @param {string} time Connection STD\r\n * @return {string} timeDifference\r\n */\r\n\t\tfunction TimeDifference(time){\r\n\t\t\tvar timeString = '';\r\n\t\t\tvar sign = '';\r\n\t\t\tvar dayString = null;\r\n\r\n\t\t\tif(time){\r\n\t\t\t\tvar connFlightDate = new Date(time);\r\n\t\t\t\tvar ms = connFlightDate.getTime() - $scope.flightETA ; // this is a time in milliseconds\r\n\t\t\t\tif(ms<0) {\r\n\t\t\t\t\tms = -ms;\r\n\t\t\t\t\tsign = \"-\";\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar days = Math.floor(ms / (24*60*60*1000));\r\n\t\t\t\tdays = days<0? days+1:days;\r\n\t\t\t\tvar daysms=ms % (24*60*60*1000);\r\n\t\t\t\tvar hours = Math.floor((daysms)/(60*60*1000));\r\n\t\t\t\tvar hoursms=ms % (60*60*1000);\r\n\t\t\t\tvar minutes = Math.floor((hoursms)/(60*1000));\r\n\t\t\t\ttimeString = ''+ sign + (hours > 0 ? (\"0\" + hours).substr(-2) + \":\" : '') + (\"0\" + minutes).substr(-2) + '\\'' + '';\r\n\t\t\t\tdayString = ' ' +days + 'd';\r\n\t\t\t}\r\n\t\t\treturn timeString + ((days && days!=0) ? dayString : '');\r\n\t\t}\r\n\t}\r\n\r\n})();","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.factory('PaxInfoFactory', PaxInfoFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PaxInfoFactory\r\n * @description \r\n * Add, Update, Delete and Get Passenger information.\r\n * @ngInject\r\n */\r\n\tfunction PaxInfoFactory(GenericService, FlightGateFactory, SyncLogFactory) {\r\n /**\r\n * Initialize the PaxInfo\r\n * @memberof PaxInfoFactory\r\n */\r\n\t\tfunction PaxInfo() {\r\n\t\t\tthis.Id = null;\r\n\t\t\tthis.STD_utc = null;\r\n\t\t\tthis.STD_lcl = null;\r\n\t\t\tthis.STA_utc = null;\r\n\t\t\tthis.STA_lcl = null;\r\n\t\t\tthis.AcType = null;\r\n\t\t\tthis.Registration = null;\r\n\t\t\tthis.ConfigurationC = null;\r\n\t\t\tthis.ConfigurationY = null;\r\n\t\t\tthis.PaxTotalC = null;\r\n\t\t\tthis.PaxTotalY = null;\r\n\t\t\tthis.MarketingFlightNos = null;\r\n\t\t\tthis.SupplementaryInfo = null;\r\n\t\t\tthis.LastRun = null;\r\n\t\t\tthis.Offpoints = [];\r\n\t\t\tthis.ConnFlights = [];\r\n\t\t\tthis.Seatmap = [];\r\n\t\t\tthis.curtainRows = [];\r\n\t\t\tthis.Statistics = {};\r\n\r\n\t\t\tthis.GetId = GetId;\r\n\t\t}\r\n\r\n\t\tvar objType = 'PaxInfo';\r\n\t\tvar objCallback = PaxInfo;\r\n\r\n\t\tvar service =\r\n\t\t{\r\n\t\t\tgetAllPaxInfoFromStorage: getAllPaxInfoFromStorage,\r\n\t\t\tsavePaxInfoToStorage: savePaxInfoToStorage,\r\n\t\t\tsetPaxInfoToStorage: setPaxInfoToStorage,\r\n\t\t\tgetPaxInfoFromStorage: getPaxInfoFromStorage,\r\n\t\t\tupdatePaxInfo: updatePaxInfo\r\n\t\t}\r\n\r\n /**\r\n * Overide default get Id\r\n * @memberof PaxInfoFactory\r\n * @returns {number} Id \r\n */\r\n\t\tfunction GetId() {\r\n\t\t\treturn this.FlightId;\r\n\t\t}\r\n\r\n /**\r\n * Overide default get Id\r\n * @memberof PaxInfoFactory\r\n * @returns {number} Id \r\n */\r\n\t\tfunction GetStatistics(paxInfo) {\r\n\t\t\tvar statistics = {};\r\n\t\t\tvar syncLog = SyncLogFactory.getSyncLog();\r\n\r\n\t\t\tif (paxInfo && paxInfo.Seatmap) {\r\n\r\n\t\t\t\tpaxInfo.curtainRows = [];\r\n\t\t\r\n\t\t\t\tvar cabinType;\r\n\t\t\t\tfor (var i = 0; i < paxInfo.Seatmap.length; i++) {\r\n\t\t\t\t\tfor (var j = 0; j < paxInfo.Seatmap[i].Columns.length; j++) {\r\n\r\n\r\n\t\t\t\t\t\tif (paxInfo.Seatmap[i].Columns[j].Cabin == 'J') {\r\n\t\t\t\t\t\t\tpaxInfo.Seatmap[i].Columns[j].Cabin = 'Y';\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\r\n\r\n\t\t\t\t\t\tif (cabinType == null) {\r\n\t\t\t\t\t\t\tcabinType = paxInfo.Seatmap[i].Columns[j].Cabin;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse if (cabinType != paxInfo.Seatmap[i].Columns[j].Cabin && paxInfo.Seatmap[i - 1] && paxInfo.Seatmap[i].Columns[j].Cabin != null) {\r\n\t\t\t\t\t\t\tcabinType = paxInfo.Seatmap[i].Columns[j].Cabin;\r\n\t\t\t\t\t\t\tpaxInfo.curtainRows.push(paxInfo.Seatmap[i - 1].RowNo);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\r\n\t\t\treturn statistics;\r\n\t\t}\r\n\r\n /**\r\n * Set Passenger informations\r\n * @memberof PaxInfoFactory\r\n * @param {Array} paxInfos The passenger informations \r\n */\r\n\t\tfunction setPaxInfoToStorage(paxInfos) {\r\n\t\t\tif (paxInfos) {\r\n\t\t\t\tfor (var i = 0; i < paxInfos.length; i++) {\r\n\t\t\t\t\tpaxInfos[i].Statistics = GetStatistics(paxInfos[i]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tGenericService.saveAll(paxInfos, objType, objCallback);\r\n\t\t}\r\n\r\n /**\r\n * Set a Passenger information list\r\n * @memberof PaxInfoFactory\r\n * @param {object} paxInfo A passenger information list\r\n */\r\n\t\tfunction savePaxInfoToStorage(paxInfo) {\r\n\t\t\tpaxInfo.Statistics = GetStatistics(paxInfo);\r\n\t\t\tpaxInfos[i].Seatmap = [];\r\n\t\t\tGenericService.save(paxInfo, objType, objCallback);\r\n\t\t}\r\n\r\n\r\n /**\r\n * Get Passenger information for the selected flight\r\n * @memberof PaxInfoFactory\r\n * @param {Array} paxInfos The passenger informations \r\n */\r\n\t\tfunction getPaxInfoFromStorage(flightId) {\r\n\t\t\treturn GenericService.get(flightId, objType, objCallback);\r\n\t\t}\r\n\r\n\t\t//factory functions\r\n /**\r\n * Update Passenger information\r\n * @memberof PaxInfoFactory\r\n * @param {object} paxInfo The passenger informations \r\n */\r\n\t\tfunction updatePaxInfo(paxInfo) {\r\n\t\t\tif (paxInfo) {\r\n\t\t\t\tpaxInfo.Statistics = GetStatistics(paxInfo);\r\n\t\t\t\tif (GenericService.get(paxInfo.FlightId, objType, objCallback))\r\n\t\t\t\t\tGenericService.save(paxInfo, objType, objCallback);\r\n\t\t\t\telse\r\n\t\t\t\tGenericService.add(paxInfo, objType, objCallback);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n * Get Passenger information for the selected flights\r\n * @memberof PaxInfoFactory\r\n */\r\n\t\tfunction getAllPaxInfoFromStorage() {\r\n return GenericService.list(objType, objCallback);\r\n }\r\n\t\t\r\n\t\treturn service;\r\n\t}\r\n\r\n})(); \r\n","(function() {\r\n 'use strict';\r\n \r\n\r\na3_pilot_reports.factory('AircraftTypeFactory',AircraftTypeFactory)\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name AircraftTypeFactory\r\n * @description \r\n * Manage Aircraft Types.\r\n * @ngInject\r\n */\r\nfunction AircraftTypeFactory($log,GenericValuesFactory){\r\n\r\n /**\r\n * Initialiaze AircraftType object \r\n * @memberof AircraftTypeFactory\r\n */\r\n\t\tfunction AircraftType() {\r\n\t\t\tthis.Code = null;\r\n\t\t}\r\n \r\n\t\tvar callback=AircraftType;\r\n\t\tvar type ='aircraftTypes';\r\n\t\t\t\r\n\t\tvar service = {\r\n\t\t\tfromObject : fromObject,\r\n\t\t\tfromObjectList : fromObjectList,\r\n\t\t\ttoObjectList : toObjectList,\r\n\t\t\tgetAircraftTypesFromStorage : getAircraftTypesFromStorage,\r\n\t\t\tsetAircraftTypesToStorage : setAircraftTypesToStorage,\r\n\t\t\tclearAircraftTypesFromStorage : clearAircraftTypesFromStorage \r\n\t\t}\r\n \r\n /**\r\n * Extend given AircraftType object \r\n * @memberof AircraftTypeFactory\r\n * @param {object} obj The AircraftType object that will be extended\r\n * @returns {object} AircraftType\r\n */\r\n\t\tfunction fromObject(obj) {\r\n\t\t\treturn GenericValuesFactory.fromObject(obj,callback);\r\n\t\t}\r\n \r\n /**\r\n * Extend given AircraftType object list\r\n * @memberof AircraftTypeFactory\r\n * @param {array} objList The list of AircraftType objects that will be extended\r\n * @returns {object} AircraftTypes\r\n */\r\n\t\tfunction fromObjectList(objList) {\r\n\t\t\treturn GenericValuesFactory.fromObjectList(objList,callback);\r\n\t\t}\r\n \r\n /**\r\n * Extend given AircraftType object list\r\n * @memberof AircraftTypeFactory\r\n * @param {array} objList The list of AircraftType objects that will be extended\r\n * @returns {object} AircraftTypes\r\n */\r\n\t\tfunction toObjectList(objList) {\r\n\t\t\treturn GenericValuesFactory.objList(objList);\r\n\t\t}\r\n \r\n /**\r\n * Get all the AircraftType objects\r\n * @memberof AircraftTypeFactory\r\n * @returns {array} AircraftTypes\r\n */\r\n\t\tfunction getAircraftTypesFromStorage() {\r\n\t\t\treturn GenericValuesFactory.getValuesFromStorage(callback,type);\r\n\t\t}\r\n \r\n /**\r\n * Set all the AircraftTypes\r\n * @memberof AircraftTypeFactory\r\n * @param {array} objects A list of AircraftTypes.\r\n */\r\n\t\tfunction setAircraftTypesToStorage(objList) {\r\n\t\t\tGenericValuesFactory.setValuesToStorage(objList,type);\r\n\t\t}\r\n\r\n /**\r\n * Clear all the AircraftTypes\r\n * @memberof AircraftTypeFactory\r\n */\r\n\t\tfunction clearAircraftTypesFromStorage() {\r\n\t\t\tGenericValuesFactory.clearValuesFromStorage(type);\r\n\t\t}\r\n\r\n\t\treturn service;\r\n\t}\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.filter('byCategory', byCategory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name byCategory\r\n * @description \r\n * Filter questions by catecory and search text\r\n * @ngInject\r\n */\r\nfunction byCategory() {\r\n return function (questions, obj) {\r\n\t\t\t\tvar items = {\r\n\t\t\t\t\t\tcategory:obj.category,\r\n\t\t\t\t\t\tsearchText: (obj.query) ? obj.query.toLowerCase():\"\",\r\n\t\t\t\t\t\tout: []\r\n\t\t\t\t};\r\n\t\t\t\tangular.forEach(questions, function (value, key) {\r\n\t\t\t\t\t\tif ((this.category === value.CategoryLabel) && (value.Label.toLowerCase().indexOf(this.searchText) >= 0 || value.Description.toLowerCase().indexOf(this.searchText) >= 0)) {\r\n\t\t\t\t\t\t\t\tthis.out.push(value);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t}, items);\r\n\t\t\t\treturn items.out.dynamicSort('OrderNo');\r\n\t\t\t};\r\n\t\t};\r\n\t\t\r\n \r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.controller('OpenReportDialogCtrl',OpenReportDialogCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name OpenReportDialogCtrl\r\n * @description \r\n * Manages the open report modal functionality \r\n * @ngInject\r\n */\r\nfunction OpenReportDialogCtrl ($scope, $uibModalInstance, $location, apiUrl, UserFactory, FlightFactory, PilotReportLocalEditFactory, flightId) {\r\n\r\n\t\t// load the user\r\n\t\tvar user = UserFactory.getUser();\r\n\t\t\r\n\t\t// load the flight\r\n\t\tvar flight = FlightFactory.getFlightFromStorage(flightId);\r\n\t\tif (flight == null)\r\n\t\t\treturn;\r\n\t\t\r\n\t\t// load the reports\r\n\t\tvar serverReportForThisUser = flight.getServerPilotReportForUser(user.aimsId);\r\n\t\tvar serverReportsByAnotherUser = flight.getServerPilotReportsByAnotherUser(user.aimsId);\r\n\t\tvar localReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\r\n\t\t\r\n\t\t// the user can create a new report only if there is not an existing one and there is not a server report by him\r\n\t\tif ((localReport != null) || (serverReportForThisUser != null))\r\n\t\t\t$scope.canCreateNewLocalReport = false;\r\n\t\telse\r\n\t\t\t$scope.canCreateNewLocalReport = true;\r\n\t\t\r\n\t\tvar allServerReports = new Array();\r\n\t\t\r\n\t\tif (serverReportForThisUser != null)\r\n\t\t{\r\n\t\t\tserverReportForThisUser.IsSameUser = \" (YOU)\";\r\n\t\t\tallServerReports.push(serverReportForThisUser);\r\n\t\t}\r\n\t\t\r\n\t\tfor (var i=0; i 0) && (this.WarningItems == 0) && (!this.AutolandUnsatisfactory || (this.AutolandUnsatisfactory && this.AutolandWorkOrderNoIsValid ))) {\r\n\t\t\t\t\tthis.IsValid = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t}\r\n \r\n /**\r\n * Save the Pilot Report\r\n * @memberof PilotReportLocalEditFactory\r\n */\r\n\t\tfunction saveReport() {\r\n\t\t\t// update the LastUpdated field\r\n\t\t\tthis.LastUpdated = new Date();\r\n\r\n\t\t\t// get the reports array from storage\r\n\t\t\tvar allReports = getPilotReportsFromStorage();\r\n\t\t\tif (allReports == null)\r\n\t\t\t\tallReports = [];\r\n\t\t\t\r\n\t\t\t// find the current report from the array (if present)\r\n\t\t\tvar arrayLength = allReports.length;\r\n\t\t\tvar reportIndex = -1;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (allReports[i].ReportGuid == this.ReportGuid) {\r\n\t\t\t\t\treportIndex = i;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// add or update a copy of the current report\r\n\t\t\tif (reportIndex >= 0)\r\n\t\t\t\tallReports[reportIndex] = this;\r\n\t\t\telse\r\n\t\t\t\tallReports.push(this);\r\n\t\t\t\r\n\t\t\t// save\r\n\t\t\tsetPilotReportsToStorage(allReports);\r\n\t\t}\r\n \r\n /**\r\n * Save the Report As Temp\r\n * @memberof PilotReportLocalEditFactory\r\n */\r\n\t\tfunction saveReportAsTemp() {\r\n\r\n\t\t\t// update the LastUpdated field\r\n\t\t\tthis.LastUpdated = new Date();\r\n\r\n\t\t\t// save as temp\r\n\t\t\tlocalStorageMD5Service.remove('pilotReportLocalEdit_TEMP');\r\n\t\t\tlocalStorageMD5Service.set('pilotReportLocalEdit_TEMP', this);\r\n\t\t\r\n\t\t}\r\n\r\n\t\t//Factory Functions\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\r\n /**\r\n * Extend Object from the default local Pilot Report Object\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {Object} obj a PilotReportLocalEdit\r\n * @returns {Object} PilotReportLocalEdit\r\n */\r\n\t function fromObject( obj ) {\r\n\t\t\t\t return GenericService.fromObject(obj,objCallback); \r\n\t }\r\n\r\n\t function fromObjectList( objList ) {\r\n\t\t\t\treturn GenericService.fromObjectList(objList,objCallback);\r\n\t }\r\n \r\n /**\r\n * Get Pilot Reports from storage\r\n * @memberof PilotReportLocalEditFactory\r\n * @returns {Array} PilotReports\r\n */\r\n\t function getPilotReportsFromStorage(){\r\n\t\t\t\t return GenericService.list(objType,objCallback);\r\n\t }\r\n\r\n /**\r\n * Get Pilot Reports from storage\r\n * @memberof PilotReportLocalEditFactory\r\n * @returns {Array} PilotReports\r\n */\r\n\t function setPilotReportsToStorage(pilotReportLocalEdits){\r\n\t\t\t\tGenericService.saveAll(pilotReportLocalEdits,objType,objCallback);\r\n\t }\r\n\r\n /**\r\n * Delete Pilot Temporary Report from storage\r\n * @memberof PilotReportLocalEditFactory\r\n */\r\n function deleteTempReport() {\r\n localStorageMD5Service.remove('pilotReportLocalEdit_TEMP');\r\n }\r\n \r\n /**\r\n * Delete Selected repport\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {string} reportGuid The report's Identifier\r\n */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n function deleteReport(reportGuid){\r\n var allReports = getPilotReportsFromStorage();\r\n if (allReports == null)\r\n return false; \r\n\r\n var updatedReports = [];\r\n var arrayLength = allReports.length;\r\n var reportIndex = -1;\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (allReports[i].ReportGuid == reportGuid) {\r\n reportIndex = i;\r\n // break;\r\n }\r\n else{\r\n updatedReports.push(allReports[i]); // copy report in new array\r\n }\r\n }\r\n\r\n if (reportIndex = -1){\r\n setPilotReportsToStorage(updatedReports);\r\n }\r\n }\r\n \r\n /**\r\n * Get the Pilot repport of this flight\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {number} flightId A flight Id\r\n * @return {Object} report \r\n */\r\n function getPilotReportLocalEditFromTemp() {\r\n\t\t\tvar pilotReportLocalEdit = localStorageMD5Service.get('pilotReportLocalEdit_TEMP');\r\n\t\t\tpilotReportLocalEdit = checkForNewGroundServices(pilotReportLocalEdit);\r\n return fromObject(pilotReportLocalEdit);\r\n }\t\r\n\r\n /**\r\n * Get the Pilot repport of this flight\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {number} flightId A flight Id\r\n * @return {Object} report \r\n */\r\n function getPilotReportLocalEditForFlight(flightId){\r\n var pilotReportLocalEdits = getPilotReportsFromStorage();\r\n if (pilotReportLocalEdits == null)\r\n return null;\r\n\r\n var result = null;\r\n\r\n var arrayLength = pilotReportLocalEdits.length;\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (pilotReportLocalEdits[i].FlightId == flightId)\r\n {\r\n result = pilotReportLocalEdits[i];\r\n break;\r\n }\r\n }\r\n\t\t\tresult = checkForNewGroundServices(result);\r\n return result;\r\n }\r\n /**\r\n * Get the Pilot repport\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {string} reportGuid A report Id\r\n * @return {Object} report \r\n */\r\n function getPilotReportLocalEdit(reportGuid){\r\n var pilotReportLocalEdits = getPilotReportsFromStorage();\r\n if (pilotReportLocalEdits == null)\r\n return null;\r\n\r\n var result = null;\r\n\r\n var arrayLength = pilotReportLocalEdits.length;\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (pilotReportLocalEdits[i].ReportGuid == reportGuid)\r\n {\r\n result = pilotReportLocalEdits[i];\r\n break;\r\n }\r\n\t\t\t}\r\n\t\t\tresult = checkForNewGroundServices(result);\r\n\r\n return result;\r\n\t\t}\r\n\t\t\r\n\t\t/**\r\n * add any new ground services from storage to the existing report\r\n * @memberof PilotReportLocalEditFactory\r\n\t\t * @param {Object} report\r\n * @return {Object} report \r\n */\r\n\t\tfunction checkForNewGroundServices(report) {\r\n\t\t\tif (report == null)\r\n\t\t\t\treturn report;\r\n\t\t\t\r\n\t\t\tvar depStorageGroundServices = GroundServicesFactory.getGroundServicesByStation(report.Departure);\r\n\t\t\t//var arrStorageGroundServices = GroundServicesFactory.getGroundServicesByStation(report.Arrival);\r\n\t\t\tfor (var i = 0; i < depStorageGroundServices.length; i++) {\r\n\t\t\t\tvar found = false;\r\n\t\t\t\tfor (var j = 0; j < report.DepartureGroundServices.length; j++){\r\n\t\t\t\t\tif (depStorageGroundServices[i].ServiceType === report.DepartureGroundServices[j].ServiceType){\r\n\t\t\t\t\t\t//this ground service is available according to the localstorage but its not in the report\r\n\t\t\t\t\t\tfound = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (!found){\r\n\t\t\t\t\treport.DepartureGroundServices.push(depStorageGroundServices[i]);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// for (var i = 0; i < arrStorageGroundServices.length; i++) {\r\n\t\t\t// \tvar found = false;\r\n\t\t\t// \tfor (var j = 0; j < report.ArrivalGroundServices.length; j++){\r\n\t\t\t// \t\tif (arrStorageGroundServices[i].ServiceType === report.ArrivalGroundServices[j].ServiceType){\r\n\t\t\t// \t\t\t//this ground service is available according to the localstorage but its not in the report\r\n\t\t\t// \t\t\tfound = true;\r\n\t\t\t// \t\t\tbreak;\r\n\t\t\t// \t\t}\r\n\t\t\t// \t}\r\n\t\t\t// \tif (!found){\r\n\t\t\t// \t\treport.ArrivalGroundServices.push(arrStorageGroundServices[i]);\r\n\t\t\t// \t}\r\n\t\t\t// }\r\n\t\t\treturn report;\r\n\t\t}\r\n\r\n /**\r\n * Get the number of reports that need to be synched\r\n * @memberof PilotReportLocalEditFactory\r\n * @return {number} result A Pilot Report\r\n */\r\n\t\tfunction getPilotReportLocalEditCountThatNeedToBeSynched(){\r\n var pilotReportLocalEdits = getPilotReportsFromStorage();\r\n if (pilotReportLocalEdits == null)\r\n return 0;\r\n\r\n var result = 0;\r\n\r\n var arrayLength = pilotReportLocalEdits.length;\r\n for (var i = 0; i < arrayLength; i++) {\r\n if (pilotReportLocalEdits[i].Status === 'completed')\r\n {\r\n result++;\r\n }\r\n }\r\n\t\t\r\n\t\treturn result;\r\n\t}\r\n\r\n\tfunction getPilotReportLocalEditThatNeedToBeSynched(){\r\n\t\tvar result = new Array;\r\n\t\t\r\n\t\tvar pilotReportLocalEdits = getPilotReportsFromStorage();\r\n\t\tif (pilotReportLocalEdits == null)\r\n\t\t\treturn result;\r\n\t\t\r\n\t\tvar arrayLength = pilotReportLocalEdits.length;\r\n\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\tif (pilotReportLocalEdits[i].Status === 'completed')\r\n\t\t\t{\r\n\t\t\t\tresult.push(pilotReportLocalEdits[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\treturn result;\r\n\t}\r\n\t\r\n \r\n /**\r\n * Gonstructor for a new Pilot Report\r\n * @memberof PilotReportLocalEditFactory\r\n * @return {array} result \r\n */\r\n\tfunction getNewReport(){\r\n\t\treturn new PilotReportLocalEdit();\r\n\t}\r\n\t\r\n /**\r\n * Mark selected report As Synched\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {string} reportGuid The report Guid\r\n * @return {boolean} isSuccess \r\n */ \r\n\tfunction markReportAsSynched(reportGuid){\r\n\t\t\r\n\t\tvar report = getPilotReportLocalEdit(reportGuid);\r\n\t\tif (report == null)\r\n\t\t\treturn false;\r\n\r\n\t\treport.Status = 'synched';\r\n\t\treport.saveReport();\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n /**\r\n * Save Selected Pilot repport\r\n * @memberof PilotReportLocalEditFactory\r\n * @param {Object} report A Pilot Report\r\n */\t\t\r\n function setPilotReportToStorage(report){\r\n\t\tvar allReports = getPilotReportsFromStorage();\r\n\t\tif (allReports == null)\r\n\t\t\treturn false; // cannot delete a report, if none exist\r\n\t\t\t\r\n\t\t// find the current report from the array (if present)\r\n\t\tvar updatedReports = [];\r\n\t\tvar arrayLength = allReports.length;\r\n\t\tvar reportIndex = -1;\r\n\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\tif (allReports[i].ReportGuid == report.ReportGuid) {\r\n\t\t\t\tupdatedReports.push(report);\r\n\t\t\t\t\t\t\t\treportIndex=i;\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\tupdatedReports.push(allReports[i]); // copy report in new array\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tif (reportIndex != -1){\r\n\t\t\tsetPilotReportsToStorage(updatedReports);\r\n\t\t}\r\n\t}\r\n\r\n\t\r\n\r\n\treturn service;\r\n}\r\n\r\n\r\n\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.factory('PilotReportLocalEditCreatorFactory', PilotReportLocalEditCreatorFactory);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportLocalEditCreatorFactory\r\n * @description \r\n * Create a new local Report\r\n * @ngInject\r\n */\r\nfunction PilotReportLocalEditCreatorFactory( $log,localStorageMD5Service,FlightFactory,ReportGuidFactory,PilotReportTemplateFactory,\r\nPilotReportLocalEditFactory,UserFactory, GroundServicesFactory){\r\n\r\n\t\t\r\n\t\tvar service = {\r\n\t\t\t\tcreateNewLocalReportForFlight : createNewLocalReportForFlight\r\n\t\t} \r\n \r\n /**\r\n * Create a new Local Report For the Selected Flight\r\n * @memberof PilotReportLocalEditCreatorFactory\r\n * @param {number} flightId \r\n * @returns {object} report \r\n */\r\n\tfunction createNewLocalReportForFlight(flightId,flightAimsId){\r\n\t\t\r\n\t\t// load the user\r\n\t\tvar user = UserFactory.getUser();\r\n\t\tif (user == null)\r\n\t\t\treturn null;\r\n\t\t\r\n\t\t// check if a report exists for this flight and user\r\n\t\tvar existingReport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\r\n\t\tif (existingReport != null)\r\n\t\t\treturn existingReport;\r\n\t\t\r\n\t\t// get a guid for the report\r\n\t\tvar newReportGuid = ReportGuidFactory.getNextGuid();\r\n\t\tif (newReportGuid == null)\r\n\t\t\treturn null;\t\t\r\n\r\n\t\t// load the pilot report template\r\n\t\tvar reportTemplate = PilotReportTemplateFactory.getPilotReportTemplateFromStorage();\r\n\t\tif (reportTemplate == null)\r\n\t\t\treturn null;\r\n\r\n\t\t// load the flight\r\n\t\tvar flight = FlightFactory.getFlightFromStorage(flightId,flightAimsId);\r\n\t\tif (flight == null)\r\n\t\t{\r\n\t\t\t// if not found, also check the local flights\r\n\t\t\tvar flight = FlightFactory.getLocalFlightFromStorage(flightId,flightAimsId);\r\n\t\t\t\r\n\t\t\t// if still not found, then return null\r\n\t\t\tif (flight == null)\r\n\t\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\t// create the new report\r\n\t\tvar newReport = PilotReportLocalEditFactory.getNewReport();\r\n\t\t\r\n\t\t// assign data on the new report\r\n\t\tnewReport.AuthorId = user.id;\r\n\t\tnewReport.AuthorAimsId = user.aimsId;\r\n\t\tnewReport.AuthorName = user.name;\r\n\t\tnewReport.Created = new Date();\r\n\t\tnewReport.FlightAimsId = flight.FlightAimsId;\r\n\t\tnewReport.FlightId = flight.FlightId;\r\n\t\tnewReport.LastUpdated = new Date();\r\n\t\tnewReport.AcType = flight.AcType;\r\n\t\tnewReport.AcTailNo = flight.AcTailNo;\r\n\t\tnewReport.FlightDate = flight.FlightDate;\r\n\t\tnewReport.FlightNo = flight.FlightNo;\r\n\t\tnewReport.Departure = flight.Departure;\r\n\t\tnewReport.Arrival = flight.Arrival;\r\n\t\tnewReport.ScheduledDeparture = flight.ScheduledDeparture;\r\n\t\tnewReport.ScheduledDepartureDateUTC = flight.ScheduledDepartureDateUTC;\r\n\t\tnewReport.ScheduledDepartureTimeUTC = flight.ScheduledDepartureTimeUTC;\r\n\t\tnewReport.ReportGuid = newReportGuid;\r\n\t\tnewReport.ReportId = null;\r\n\t\tnewReport.NothingToReport = false;\r\n\t\tnewReport.Status = 'pending';\r\n\t\tnewReport.Sections = reportTemplate.Sections;\r\n\t\t//details from flight (assuming flight contains these fields)\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\tif (flight.DepartureName){\r\n\t\t\tnewReport.DepartureICAO = flight.DepartureICAO;\r\n\t\t\tnewReport.DepartureCountry = flight.DepartureCountry;\r\n\t\t\tnewReport.DepartureName = flight.DepartureName;\r\n\t\t\tnewReport.ArrivalICAO = flight.ArrivalICAO;\r\n\t\t\tnewReport.ArrivalCountry = flight.ArrivalCountry;\r\n\t\t\tnewReport.ArrivalName = flight.ArrivalName;\r\n\t\t}\r\n\t\t//pax figures from flight (assuming flight contains these figures)\r\n\t\tif (typeof flight.BookedY != 'undefined'){\r\n\t\t\tnewReport.BookedC = flight.BookedC;\r\n\t\t\tnewReport.BookedY = flight.BookedY;\r\n\t\t\tnewReport.BookedInf = flight.BookedInf;\r\n\t\t\tnewReport.BookedPad = flight.BookedPad;\r\n\t\t\tnewReport.BookedChld = flight.BookedChld;\r\n\t\t\tnewReport.ActualC = flight.ActualC;\r\n\t\t\tnewReport.ActualY = flight.ActualY;\r\n\t\t\tnewReport.ActualInf = flight.ActualInf;\r\n\t\t\tnewReport.ActualPad = flight.ActualPad;\r\n\t\t\tnewReport.ActualChld = flight.ActualChld;\r\n\t\t}\r\n\t\tnewReport.crew = flight.crew;\r\n\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t//new values\r\n\t\t\t\tnewReport.DepartureTimezone=flight.DepartureTimezone;\r\n\t\t\t\tnewReport.ArrivalTimezone=flight.ArrivalTimezone;\r\n\t\t\t\tnewReport.CallSign=flight.CallSign;\r\n\t\t\t\tnewReport.ScheduledArrival=flight.ScheduledArrival;\r\n\t\t\t\tnewReport.DepartureGate=flight.DepartureGate;\r\n\t\t\r\n\t\t//add ground services\r\n\t\tnewReport.DepartureGroundServices = GroundServicesFactory.getGroundServicesByStation(flight.Departure);\r\n\t\t//We don't show Arrival Services any more...\r\n\t\t//newReport.ArrivalGroundServices = GroundServicesFactory.getGroundServicesByStation(flight.Arrival);\r\n\r\n\t\tnewReport.updateTotals();\r\n\t\t\r\n\t\t// return the new report\r\n\t\treturn newReport;\r\n\t}\r\n\r\n\t\treturn service;\r\n};\r\n\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.factory('PilotReportSendToServerFactory',PilotReportSendToServerFactory);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportSendToServerFactory\r\n * @description \r\n * Transform Pilot Reports in order to send them to the server\r\n * @ngInject\r\n */\r\nfunction PilotReportSendToServerFactory($log){\r\n\r\n /**\r\n * Initialize the PilotReportSendToServer\r\n * @memberof PilotReportSendToServerFactory\r\n */\r\n\t\tfunction PilotReportSendToServer() {\r\n\t\t\tthis.Created = null;\r\n\t\t\tthis.LastUpdated = null;\t\t\r\n\t\t\tthis.FlightAimsId = null;\r\n\t\t\tthis.FlightId = null;\r\n\t\t\tthis.FlightDate = null;\r\n\t\t\tthis.FlightNo = null;\r\n\t\t\tthis.Departure = null;\r\n\t\t\tthis.Arrival = null;\r\n\t\t\tthis.ReportGuid = null;\r\n\t\t\tthis.AuthorCrewId = null;\r\n\t\t\tthis.AuthorCrewAimsId = null;\r\n\t\t\tthis.Items = [];\r\n\t\t\tthis.Autoland = 'manual';\r\n\t\t\tthis.AutolandWorkOrderNo = null;\r\n\t\t\tthis.ArrivalGroundServices = [];\r\n\t\t\tthis.DepartureGroundServices = [];\r\n\t\t}\r\n \r\n /**\r\n * Initialize the PilotReportSendToServerItem\r\n * @memberof PilotReportSendToServerFactory\r\n */\r\n function PilotReportSendToServerItem() {\r\n\t\t\tthis.ReportGuid = null;\r\n\t\t\tthis.TemplateItemId = null;\r\n\t\t\tthis.Value = 0;\r\n\t\t\tthis.Remarks = '';\r\n\t\t}\r\n\r\n\r\n\t\tvar service = {\r\n\t\t\tgetCompletedListFromPilotReportLocalEdits : getCompletedListFromPilotReportLocalEdits\r\n\t\t} \r\n\t\r\n /**\r\n * Transform all cabin local reports in order to be sent to the server\r\n * @memberof PilotReportSendToServerFactory\r\n * @param {Array} pilotReportLocalEdits\r\n * @returns {Array} PilotReportsSendToServer \r\n */\r\n\t\tfunction getCompletedListFromPilotReportLocalEdits(pilotReportLocalEdits){\r\n\t\t\tvar result = [];\r\n\t\t\t\r\n\t\t\tif (pilotReportLocalEdits == null)\r\n\t\t\t\treturn result;\r\n\t\t\t\r\n\t\t\tvar arrayLength = pilotReportLocalEdits.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (pilotReportLocalEdits[i].Status === 'completed')\r\n\t\t\t\t{\r\n\t\t\t\t\tresult.push(getReportFromPilotReportLocalEdit(pilotReportLocalEdits[i]));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n //Temporary: fix: Ground Services: Used values (true/false) from local storage.\r\n var resultChecked = fixUsedValueLS(result);\r\n\r\n return resultChecked;\r\n }\r\n\r\n //Temporary: fix - Ground Services - local storage from true/false values. (int Used: 0:false, 1:true, 2:inop) \r\n function fixUsedValueLS(cabinReportLocalEdits){\r\n for (var i = 0; i < cabinReportLocalEdits.length; i++) {\r\n if(cabinReportLocalEdits[i].DepartureGroundServices.length > 0){\r\n for(var j = 0; j < cabinReportLocalEdits[i].DepartureGroundServices.length; j++){\r\n if (cabinReportLocalEdits[i].DepartureGroundServices[j]){\r\n if (cabinReportLocalEdits[i].DepartureGroundServices[j].Used === true) {\r\n cabinReportLocalEdits[i].DepartureGroundServices[j].Used = 1;\r\n }else if (cabinReportLocalEdits[i].DepartureGroundServices[j].Used === false){\r\n cabinReportLocalEdits[i].DepartureGroundServices[j].Used = 0;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return cabinReportLocalEdits;\r\n }\r\n\r\n\r\n\r\n\t\t\r\n /**\r\n * Transform a pilot local reports in order to be sent to the server\r\n * @memberof PilotReportSendToServerFactory\r\n * @param {object} pilotReportLocalEdit\r\n * @returns {object} PilotReportSendToServer \r\n */\r\n\t\tfunction getReportFromPilotReportLocalEdit(pilotReportLocalEdit){\r\n\t\t\tvar result = new PilotReportSendToServer();\r\n\t\t\t\r\n\t\t\tresult.Created = pilotReportLocalEdit.Created;\r\n\t\t\tresult.LastUpdated = pilotReportLocalEdit.LastUpdated;\t\t\r\n\t\t\tresult.FlightAimsId = pilotReportLocalEdit.FlightAimsId;\r\n\t\t\tresult.FlightId = pilotReportLocalEdit.FlightId;\r\n\t\t\tresult.FlightDate = pilotReportLocalEdit.FlightDate;\r\n\t\t\tresult.FlightNo = pilotReportLocalEdit.FlightNo;\r\n\t\t\tresult.Departure = pilotReportLocalEdit.Departure;\r\n\t\t\tresult.Arrival = pilotReportLocalEdit.Arrival;\r\n\t\t\tresult.ReportGuid = pilotReportLocalEdit.ReportGuid;\r\n\t\t\tresult.AuthorCrewId = pilotReportLocalEdit.AuthorId;\r\n\t\t\tresult.AuthorCrewAimsId = pilotReportLocalEdit.AuthorAimsId;\r\n\t\t\tresult.Items = new Array();\r\n\t\t\t//result.ArrivalGroundServices = pilotReportLocalEdit.ArrivalGroundServices;\r\n\t\t\tresult.DepartureGroundServices = pilotReportLocalEdit.DepartureGroundServices;\r\n \r\n if(pilotReportLocalEdit.AutolandSatisfactory){\r\n result.Autoland = 'AutolandSatisfactory';\r\n }else if(pilotReportLocalEdit.AutolandUnsatisfactory){\r\n result.Autoland = 'AutolandUnsatisfactory';\r\n\t\t\t\tresult.AutolandWorkOrderNo = pilotReportLocalEdit.AutolandWorkOrderNo;\r\n }else if(pilotReportLocalEdit.catApproachUnsatisfactory){\r\n result.Autoland = 'CATApproachUnsatisfactory';\r\n }else if(pilotReportLocalEdit.catApproachSatisfactory){\r\n result.Autoland = 'CATApproachSatisfactory';\r\n }\r\n \r\n\r\n\t\t\t\r\n\t\t\tvar sectionCount = pilotReportLocalEdit.Sections.length;\r\n\t\t\tfor (var i = 0; i < sectionCount; i++) {\r\n\t\t\t\t\r\n\t\t\t\tvar itemCount = pilotReportLocalEdit.Sections[i].Items.length;\r\n\t\t\t\tfor (var j = 0; j < itemCount; j++) {\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar newItem = new PilotReportSendToServerItem();\r\n\t\t\t\t\tnewItem.ReportGuid = pilotReportLocalEdit.ReportGuid;\r\n\t\t\t\t\tnewItem.TemplateItemId = pilotReportLocalEdit.Sections[i].Items[j].Id;\r\n\t\t\t\t\tnewItem.Value = pilotReportLocalEdit.Sections[i].Items[j].ItemHasValue ? 1 : 0;\r\n\t\t\t\t\tif (newItem.Value == 1)\r\n\t\t\t\t\t\tnewItem.Remarks = pilotReportLocalEdit.Sections[i].Items[j].ItemValue;\r\n\t\t\t\t\tresult.Items.push(newItem);\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\r\n\t\t\t}\t\t\r\n\t\t\t\r\n\t\t\treturn result;\r\n\t\t}\r\n\t\r\n\t\treturn service;\r\n\t}\r\n\r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('PilotReportSyncResultFactory',PilotReportSyncResultFactory)\r\n\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PilotReportSyncResultFactory\r\n * @description \r\n * Manage Pilot Report Sync Results\r\n * @ngInject\r\n */\r\nfunction PilotReportSyncResultFactory($log,GenericService){\r\n\r\n /**\r\n * Initialize the PilotReportSyncResult\r\n * @memberof PilotReportSyncResultFactory\r\n */\r\n\t\tfunction PilotReportSyncResult() {\r\n\t\t\tthis.reportGuid = null;\r\n\t\t\tthis.message = null;\r\n\t\t\tthis.success = null;\r\n\t\t\tthis.FlightAimsId = null;\r\n\t\t\tthis.FlightId=null;\r\n\t\t\tthis.ScheduledDepartureDateUTC = null;\r\n\t\t\tthis.FlightNo = null;\r\n\t\t\tthis.Departure = null;\r\n\t\t\tthis.Arrival = null;\r\n\t\t\tthis.ScheduledDepartureTimeUTC = null;\r\n\t\t\tthis.AcTailNo = null;\r\n\t\t\tthis.Result = null;\r\n\t\t\tthis.getRoute = getRoute;\r\n\t\t}\r\n\r\n\t\tvar objType = 'pilotReportSyncResult';\r\n\t\tvar objCallback = PilotReportSyncResult; \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\tvar service = {\r\n\t\t\tfromObjectList : fromObjectList,\r\n\t\t\tgetSyncResult : getSyncResult,\r\n\t\t\tgetPilotReportSyncResultsFromStorage : getPilotReportSyncResultsFromStorage,\r\n\t\t\tsetPilotReportSyncResultsToStorage : setPilotReportSyncResultsToStorage,\r\n\t\t\tclearPilotReportSyncResultsFromStorage : clearPilotReportSyncResultsFromStorage,\r\n\t\t\tgetSuccesses : getSuccesses,\r\n\t\t\tgetFailures : getFailures\r\n\t\t}\r\n \r\n /**\r\n * Get Report Route\r\n * @memberof PilotReportSyncResultFactory\r\n * @return {string} route\r\n */\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \r\n\t\tfunction getRoute() {\r\n\t\t\tif (this.Departure == null && this.Arrival == null) return '-null-';\r\n\t\t\telse return (this.Departure || '?') + '-' + (this.Arrival || '?');\r\n\t\t}\r\n \r\n /**\r\n * Extend an array of Objects from the default PilotReportSyncResult Object\r\n * @memberof PilotReportSyncResultFactory\r\n * @param {Array} objList an Array Of Pilot Report Sync Results\r\n * @returns {Array} PilotReportSyncResults\r\n */\r\n function fromObjectList (objList){\r\n\t\t\treturn GenericService.fromObjectList(objList,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Get Sync Result from given list\r\n * @memberof PilotReportSyncResultFactory\r\n * @param {Array} syncResults an Array Of Pilot Report Sync Results\r\n * @param {string} reportGuid The report's Guid\r\n * @returns {object} PilotReportSyncResult\r\n */\t\t\r\n\t\tfunction getSyncResult(syncResults, reportGuid){\r\n\t\t\tvar result = null;\r\n\t\t\t\r\n\t\t\tvar arrayLength = syncResults.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (syncResults[i].reportGuid == reportGuid) {\r\n\t\t\t\t\tresult = syncResults[i];\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn result;\r\n\t\t}\r\n \r\n /**\r\n * Get Sync Results\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} PilotReportSyncResults\r\n */\r\n\t\tfunction getPilotReportSyncResultsFromStorage(){\r\n\t\t\treturn GenericService.list(objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Get Sync Results\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} PilotReportSyncResults\r\n */\r\n\t\tfunction setPilotReportSyncResultsToStorage(pilotReportSyncResults){\r\n\t\t\tGenericService.saveAll(pilotReportSyncResults,objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Clear all Pilot Sync Results\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} PilotReportSyncResults\r\n */\r\n\t\tfunction clearPilotReportSyncResultsFromStorage(){\r\n\t\t\tGenericService.removeAll(objType,objCallback);\r\n\t\t}\r\n \r\n /**\r\n * Get Successfull Sync Results from given syncResult\r\n * @memberof PilotReportSyncResultFactory\r\n * @returns {array} successes\r\n */\t\r\n\t\tfunction getSuccesses(syncResults){\r\n\t\t\tvar result = 0;\r\n\r\n\t\t\tfor (var i=0; iAttentionUnable to create a new log!
Available pool of resources has been depleted and you need to synchronize with the server to renew it.\", \r\n\t\t\t\t\tfunction() {\r\n\t\t\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t\t\t$scope.$apply();\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\t\r\n\t\t\t\t// load the new report\r\n\t\t\t\treport = newLocalReport;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if (reportId == 'temp') {\r\n\t\t\t\r\n\t\t\t// load the report from the temp place\r\n\t\t\treport = PilotReportLocalEditFactory.getPilotReportLocalEditFromTemp();\r\n\t\t\t\r\n\t\t\tif (report == null) {\r\n\t\t\t\t\r\n\t\t\t\t// since we could not load the temp report, delete it\r\n\t\t\t\tPilotReportLocalEditFactory.deleteTempReport();\r\n\r\n\t\t\t\tbootbox.alert(\"

Warning

Unable to load temporary log.
No temporary log found in this device\", \r\n\t\t\t\t\tfunction() {\r\n\t\t\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t\t\t$scope.$apply();\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\t\r\n\t\t\t// load the report\r\n\t\t\treport = PilotReportLocalEditFactory.getPilotReportLocalEdit(reportId);\r\n\t\t\t\r\n\t\t\tif (report == null) {\r\n\t\t\t\tbootbox.alert(\"

Warning

Unable to load the requested log.
This entry does not exist in this device, our its data are corrupted and the entry is unusable.\", \r\n\t\t\t\t\tfunction() {\r\n\t\t\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t\t\t$scope.$apply();\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n \r\n\t\t//flight\r\n\r\n var flight = FlightFactory.getFlightFromTotalFlights(report.FlightId);\r\n\t\t\r\n if(!flight){\r\n\t\t\t// go to dashboard if no flight\r\n\t\t\t$location.path(\"/\");\r\n\t\t}\r\n \r\n\t\t$scope.showAutolandSection = autolandSupportingAcTypes.includes(flight.AcType);\r\n\t\t$scope.showCatIIApprachSection = showCatIIApprachAcTypes.includes(flight.AcType);\r\n \r\n/* //find late arrival report item and fill it with previous Late Aircraft Arrival\r\n var lateArrivalreportItem = null; \r\n report.Sections.forEach(\r\n function(section){\r\n var filteredItems = section.Items.filter(\r\n function(item){\r\n return item.Id == aircraftLateArrivalReportId\r\n });\r\n if(filteredItems.length==1){\r\n lateArrivalreportItem = filteredItems[0];\r\n }\r\n }\r\n );\r\n \r\n var inadequateGroundTimeReportItem = null; \r\n report.Sections.forEach(\r\n function(section){\r\n var filteredItems = section.Items.filter(\r\n function(item){\r\n return item.Id == inadequateGroundTimeReportId\r\n });\r\n if(filteredItems.length==1){\r\n inadequateGroundTimeReportItem = filteredItems[0];\r\n }\r\n }\r\n );*/\r\n \r\n/* var aircaftPositions = AircaftPositionsFactory.getAircaftPositionsByFlightId(flight.FlightId);\r\n if(aircaftPositions && aircaftPositions.PreviousSTA && !$scope.isTurboProp){\r\n var startofTAT = moment.utc(flight.ScheduledDeparture).add(-45, 'm');\r\n var prevATA = moment.utc(aircaftPositions.PreviousATA);\r\n var prevSTA = moment.utc(aircaftPositions.PreviousSTA);\r\n var lateArrival = 0;\r\n var inadequateGroundTime = 0;\r\n if(startofTAT.diff(prevSTA, 'm')>=0 && aircaftPositions.PreviousATA){\r\n \r\n var comparedValue = startofTAT;\r\n if(lateArrival > 0){\r\n var comparedValue = prevATA;\r\n }\r\n lateArrival = prevATA.diff(comparedValue, 'm');\r\n }else{\r\n lateArrival = aircaftPositions.PreviousATA ? prevATA.diff(prevSTA, 'm') : 0;\r\n inadequateGroundTime = prevSTA.diff(startofTAT, 'm');\r\n if(lateArrival<0){\r\n inadequateGroundTime = inadequateGroundTime + lateArrival;\r\n }\r\n }\r\n \r\n if(lateArrival>0 && lateArrivalreportItem && !lateArrivalreportItem.ItemHasValue){\r\n lateArrivalreportItem.ItemValue = \"Late Aircraft Arrival \" + lateArrival + \" minutes\";\r\n lateArrivalreportItem.ItemHasValue= true;\r\n }\r\n \r\n if(inadequateGroundTime>0 && inadequateGroundTimeReportItem && !inadequateGroundTimeReportItem.ItemHasValue){\r\n inadequateGroundTimeReportItem.ItemValue = \"Inadequate Ground Time \" + inadequateGroundTime + \" minutes\";\r\n inadequateGroundTimeReportItem.ItemHasValue= true;\r\n }\r\n }\r\n */\r\n \r\n \r\n\t\t$scope.flight = flight;\r\n\t \t$scope.panels = {\r\n\t\t\tshowOnlyOne: true,\r\n\t\t\treport: {\r\n\t\t\t\tvisible: true,\r\n\t\t\t\topen: true,\r\n\t\t\t\tcssClass: function() {\r\n\t\t\t\t\treturn report.IsValid ? 'panel-green' : 'panel-orange';\r\n\t\t\t\t}\r\n\t\t\t},\r\n autoland: {\r\n\t\t\t\topen: (report.AutolandSatisfactory || report.AutolandUnsatisfactory)\r\n\t\t\t},\r\n \r\n catApproach: {\r\n\t\t\t\topen: (report.catApproachSatisfactory || report.catApproachUnsatisfactory)\r\n\t\t\t},\r\n\t\t\t Flight: {\r\n\t\t\t\tvisible: true,\r\n\t\t\t\topen: false,\r\n\t\t\t\tcssClass: function(report) {\r\n\t\t\t\t\tif (report.WarningItems > 0)\r\n\t\t\t\t\t\treturn 'panel-orange';\r\n\t\t\t\t\telse if (report.ActiveItems > 0)\r\n\t\t\t\t\t\treturn 'panel-green';\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\treturn 'panel-default';\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tgroundServices: {\r\n\t\t\t\tvisible: true,\r\n\t\t\t\topen: false,\r\n\t\t\t\tcssClass: function() {\r\n\t\t\t\t\tif (report.GroundServicesSectionHasValue)\r\n\t\t\t\t\t\treturn 'panel-green';\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\treturn 'panel-default';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t$scope.GetCategoryCSS = GetCategoryCSS;\r\n\r\n\t\tfunction GetCategoryCSS(items, category){\r\n\t\t\t\r\n\t\t\tvar itemsInCategory = items.filter(function(item) {\r\n\t\t\t\treturn item.CategoryLabel == category;\r\n\t\t\t});\r\n\t\t\tvar completed = itemsInCategory.some(function(item) {\r\n\t\t\t\treturn item.ItemHasValue == true && item.ItemValue && item.ItemValue.length > 0;\r\n\t\t\t});\r\n\t\t\tvar draft = itemsInCategory.some(function(item) {\r\n\t\t\t\treturn item.ItemHasValue == true && (!item.ItemValue || item.ItemValue == \"\");\r\n\t\t\t});\r\n\t\t\tif (draft)\r\n\t\t\t\treturn 'panel-orange';\r\n\t\t\telse if (completed)\r\n\t\t\t\treturn 'panel-green';\r\n\t\t\telse\r\n\t\t\t\treturn 'panel-gray';\r\n\t\t}\r\n\t\t\r\n\t\t\r\n\t\t$scope.countDHC = 0;\r\n\t\tif (report.crew) $scope.countDHC = report.crew.filter(function(item){return (item.isDHC==true);}).length;\r\n\t\t\t \r\n\t\tif(report && report.ScheduledArrival){\r\n\t\t\tvar nowTimeStamp = new Date().getTime();\r\n\t\t\tvar schedullDepartureTimestamp = new Date(report.ScheduledArrival).getTime();\r\n\r\n\t\t\t$scope.isFuture = nowTimeStamp\"+title+\"\",\r\n\t\t\t\tbuttons: {\r\n\t\t\t\t\tcancel: {\r\n\t\t\t\t\t\tlabel: \"Cancel\",\r\n\t\t\t\t\t\tclassName: \"btn-default\",\r\n\t\t\t\t\t},\r\n\t\t\t\t\tdanger: {\r\n\t\t\t\t\t\tlabel: \"Reset CP Flight Log\",\r\n\t\t\t\t\t\tclassName: \"btn-warning\",\r\n\t\t\t\t\t\tcallback: function() {\r\n\t\t\t\t\t\t\t//add code here to remove report from temp location and possibly from permanent location\r\n\t\t\t\t\t\t\t//TODO:\r\n\t\t\t\t\t\t\tPilotReportLocalEditFactory.deleteReport(report.ReportGuid);\r\n\t\t\t\t\t\t\t// delete the temp report\r\n\t\t\t\t\t\t\tPilotReportLocalEditFactory.deleteTempReport();\r\n \r\n FlightFactory.updateFlightFromReport(report);\r\n\t\t\t\t\t\t\t// set editing page to none\r\n\t\t\t\t\t\t\tSettingsMain.setEditingPage(null);\r\n\t\t\t\t\t\t\t//next code moves user to main page\r\n\t\t\t\t\t\t\t$timeout(function(){\r\n if($location.path()==\"/report/temp\"){\r\n $scope.openReport();\r\n }else{\r\n $route.reload();\r\n }})\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n \r\n /**\r\n * Show information about the save action\r\n * @memberof ReportCtrl\r\n * @param {string} state The action of the save completed or draft or discard\r\n */\r\n\t\tfunction infoSaveOperation(state){\r\n\t\t\tif(state=='completed'){\r\n\t\t\t\t\t$scope.infosaveactiontype = state;\r\n\t\t\t\t\t$scope.infosaveaction = true;\r\n\t\t\t}else if(state=='draft'){\r\n\t\t\t\t\t$scope.infosaveactiontype = state;\r\n\t\t\t\t\t$scope.infosaveaction = true\r\n\t\t\t}else if(state=='discard'){\r\n\t\t\t\t\t$scope.infosaveactiontype = state;\r\n\t\t\t\t\t$scope.infosaveaction = true\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t$timeout(function(){\r\n\t\t\t\t\t $scope.infosaveaction = false;\r\n\t\t\t},5000);\r\n\t\t}\r\n\r\n\t\tfunction discard(){\r\n\t\t\tif (report==null){\r\n\t\t\t\treport = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(flightId);\r\n\t\t\t}\r\n\t\t\tvar guid = report.ReportGuid;\r\n\t\t\tvar status = report.Status;\r\n\r\n\t\t\t// delete the temp report\r\n\t\t\tPilotReportLocalEditFactory.deleteTempReport();\r\n\r\n\t\t\t//reuse guid if this was a new report\r\n\t\t\tif (status == 'pending')\r\n\t\t\t\tReportGuidFactory.restoreGuid(report.ReportGuid); \r\n\t\t\t\t\r\n\t\t\t// new / edit existing / load from temp\r\n\t\t\tif (reportId.startsWith('new:')) {\r\n\t\t\t\tvar flightId = $routeParams.flightId; \r\n\t\t\t\t// create a new report\r\n\t\t\t\tvar newLocalReport = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight(flightId);\r\n\r\n\t\t\t\tif (newLocalReport == null) {\r\n\t\t\t\t\tbootbox.alert(\"

Attention

Unable to create a new log!
Available pool of resources has been depleted and you need to synchronize with the server to renew it.\",\r\n\t\t\t\t\t\tfunction() {\r\n\t\t\t\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t\t\t\t$scope.$apply();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// load the new report\r\n\t\t\t\t\treport = newLocalReport;\r\n\t\t\t\t}\r\n\t\t\t} else if (reportId == 'temp') {\r\n\t\t\t\t// load the report from the temp place\r\n\t\t\t\treport = PilotReportLocalEditFactory.getPilotReportLocalEditFromTemp();\r\n\r\n\t\t\t\tif (report == null && status!='pending') {\r\n\t\t\t\t\t// since we could not load the temp report, delete it\r\n\t\t\t\t\tPilotReportLocalEditFactory.deleteTempReport();\r\n\r\n\t\t\t\t\tbootbox.alert(\"

Warning

Unable to load temporary log.
No temporary log found in this device or the report was corrupted\",\r\n\t\t\t\t\t\tfunction() {\r\n\t\t\t\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t\t\t\t$scope.$apply();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t\tif (report==null) { \r\n\t\t\t\t\treport = PilotReportLocalEditCreatorFactory.createNewLocalReportForFlight($scope.flight.FlightId);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// load the report\r\n\t\t\t\treport = PilotReportLocalEditFactory.getPilotReportLocalEdit(reportId);\r\n\t\t\t\tif (report == null) {\r\n\t\t\t\t\tbootbox.alert(\"

Warning

Unable to load the requested log.
This entry does not exist in this device, our its data are corrupted and the entry is unusable.\",\r\n\t\t\t\t\t\tfunction() {\r\n\t\t\t\t\t\t\t$location.path(\"/\");\r\n\t\t\t\t\t\t\t$scope.$apply();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\t\r\n\t\t\t$scope.report = report;\r\n\t\t\tinfoSaveOperation('discard');\r\n\t\t}\r\n\r\n\r\n\t\tfunction validationWorkOrderNo(){\r\n\t\t\tif(!isNaN(+report.AutolandWorkOrderNo) && report.AutolandWorkOrderNo.length == 6){\r\n\t\t\t\treport.AutolandWorkOrderNoIsValid = true;\r\n\t\t\t\treport.updateTotals();\r\n\t\t\t\tif (report.Status != 'synched')\r\n\t\t\t\treport.saveReportAsTemp();\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\treport.AutolandWorkOrderNoIsValid = false;\r\n\t\t\t\treport.IsValid = false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n};\r\n\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('ReportGuidFactory', ReportGuidFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name ReportGuidFactory\r\n * @description \r\n * Manages ReportGuid\r\n * @ngInject\r\n */\r\nfunction ReportGuidFactory($log,localStorageMD5Service){\r\n\r\n\r\n /**\r\n * Initialize the ReportGuid\r\n * @memberof ReportGuidFactory\r\n */\r\n function ReportGuid() {\r\n\t\t\tthis.Guid = null;\r\n\t\t}\r\n\r\n\t\tvar objType = 'reportGuids';\r\n\t\tvar objCallback = ReportGuid; \r\n\t\t\r\n\t\tvar service = {\r\n\t\t\tfromObject:fromObject,\r\n\t\t\tfromObjectList:fromObjectList,\r\n\t\t\ttoObjectList:toObjectList,\r\n\t\t\tgetReportGuidsFromStorage:getReportGuidsFromStorage,\r\n\t\t\tsetReportGuidsToStorage:setReportGuidsToStorage,\r\n\t\t\tclearReportGuidsFromStorage:clearReportGuidsFromStorage,\r\n\t\t\tgetNextGuid:getNextGuid,\r\n\t\t\tgetRemainingReportGuids : getRemainingReportGuids,\r\n\t\t\trestoreGuid : restoreGuid\r\n\t\t}\r\n\t\r\n /**\r\n * Extend Object from the default ReportGuid Object\r\n * @memberof ReportGuidFactory\r\n * @param {Object} obj a ReportGuid\r\n * @returns {Object} ReportGuid\r\n */\r\n\t\tfunction fromObject(obj) {\r\n\t\t\tif (obj==null) return null;\r\n\t\t\tvar reportGuid = new ReportGuid();\r\n\t\t\treportGuid.Guid = obj;\r\n\t\t\treturn reportGuid;\r\n\t\t};\r\n \r\n /**\r\n * Extend an array of Objects from the default ReportGuid Object\r\n * @memberof ReportGuidFactory\r\n * @param {Array} objList an Array Of ReportGuids\r\n * @returns {Array} ReportGuids\r\n */\r\n\t\tfunction fromObjectList (objList) {\r\n\t\t\tif (objList==null) return null;\r\n\t\t\t\r\n\t\t\tvar arrayLength = objList.length;\r\n\t\t\tvar reportGuids = new Array();\r\n\t\t\t\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tvar reportGuid = new ReportGuid();\r\n\t\t\t\treportGuid.Guid = objList[i];\r\n\t\t\t\treportGuids.push(reportGuid);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn reportGuids;\r\n\t\t}\r\n \r\n /**\r\n * Extend an array of Objects from the default ReportGuid Object\r\n * @memberof ReportGuidFactory\r\n * @param {Array} objList an Array Of ReportGuids\r\n * @returns {Array} ReportGuids\r\n */\r\n\t\tfunction toObjectList( guidList ) {\r\n\t\t\tif (guidList==null) return null;\r\n\t\t\t\r\n\t\t\tvar arrayLength = guidList.length;\r\n\t\t\tvar objList = new Array();\r\n\t\t\t\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tobjList.push(guidList[i].Guid);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn objList;\r\n\t\t}\r\n \r\n\t\t /**\r\n * Get all the reportGuid objects\r\n * @memberof reportGuid\r\n * @returns {array} ACSupplies\r\n */\r\n\t\tfunction getReportGuidsFromStorage() {\r\n\t\t\tvar reportGuids = localStorageMD5Service.get('reportGuids');\r\n\t\t\treturn fromObjectList(reportGuids);\r\n\t\t}\r\n \r\n /**\r\n * Set all the reportGuid objects\r\n * @memberof ReportGuidFactory\r\n * @return {string} reportGuid\r\n */\r\n\t\tfunction setReportGuidsToStorage (reportGuids){\r\n\t\t\tlocalStorageMD5Service.set('reportGuids',reportGuids);\r\n\t\t}\r\n \r\n /**\r\n * Delete all the reportGuid objects\r\n * @memberof ReportGuidFactory\r\n */\r\n function clearReportGuidsFromStorage (){\r\n\t\t\tlocalStorageMD5Service.remove('reportGuids');\r\n\t\t}\r\n \r\n /**\r\n * Get the next available guid and remove it from pool\r\n * @memberof ReportGuidFactory\r\n * @return {string} reportGuid\r\n */\r\n\t\tfunction getNextGuid(){\r\n\t\t\tvar reportGuids = getReportGuidsFromStorage();\r\n\t\t\tif (reportGuids == null)\r\n\t\t\t\treturn null;\r\n\t\t\t\r\n\t\t\tvar validGuidIndex = -1;\r\n\t\t\tvar resultingGuid = null;\r\n\t\t\t\r\n\t\t\tvar arrayLength = reportGuids.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (reportGuids[i].Guid != null && reportGuids[i].Guid != '')\r\n\t\t\t\t{\r\n\t\t\t\t\tvalidGuidIndex = i;\r\n\t\t\t\t\tresultingGuid = reportGuids[i].Guid;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (validGuidIndex >= 0) {\r\n\t\t\t\t// remove the guid from the array\r\n\t\t\t\treportGuids.splice(validGuidIndex, 1);\r\n\t\t\t\t\r\n\t\t\t\t// save the new array\r\n\t\t\t\tsetReportGuidsToStorage(toObjectList(reportGuids));\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn resultingGuid;\r\n\t\t}\r\n\t\t\r\n \r\n /**\r\n * Get the count of remaining reportGuid objects\r\n * @memberof reportGuid\r\n * @returns {number} reportGuidsLength\r\n */\r\n\t\tfunction getRemainingReportGuids(){\r\n\t\t\tvar reportGuids = getReportGuidsFromStorage();\r\n\t\t\tif (reportGuids == null)\r\n\t\t\t\treturn 0;\r\n\t\t\t\r\n\t\t\treturn reportGuids.length;\r\n\t\t}\r\n \r\n /**\r\n * Restore previously used guid into the pool of guids,Used when a report is being cancelled or deleted (and it has not been sent to the server)\r\n * @memberof ReportGuidFactory\r\n * @param {string} reportGuid\r\n */\r\n\t\tfunction restoreGuid(guid) {\r\n\t\t\t//reject incorrect values\r\n\t\t\tif (typeof guid == 'undefined' || guid == null || guid == '')\r\n\t\t\t\treturn false;\r\n\t\t\tvar reportGuids = getReportGuidsFromStorage();\r\n\t\t\tif (reportGuids == null)\r\n\t\t\t\treportGuids = [];\r\n\r\n\t\t\tvar arrayLength = reportGuids.length;\r\n\t\t\tfor (var i = 0; i < arrayLength; i++) {\r\n\t\t\t\tif (reportGuids[i].Guid == guid) {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t//add the guid into the pool of guids\r\n\t\t\tvar repGuid = fromObject(guid);\r\n\t\t\treportGuids.push(repGuid);\r\n\r\n\t\t\t// save the new array\r\n\t\t\tsetReportGuidsToStorage(toObjectList(reportGuids));\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\treturn service;\r\n}\r\n\r\n })(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('ReportsHistoryCtrl', ReportsHistoryCtrl);\r\n\r\n\r\n function ReportsHistoryCtrl($scope, $routeParams, $timeout, ReportsHistoryFactory, FlightFactory) {\r\n var reportId = $routeParams.reportId;\r\n var flightId = $routeParams.flightId;\r\n var reportType = $routeParams.reportType;\r\n var flight = FlightFactory.getFlightFromStorage(flightId);\r\n\r\n window.addEventListener('online', function (e) { $timeout(checkConnectionStatus()); });\r\n\r\n $scope.reports = [];\r\n $scope.flight = flight;\r\n $scope.contentToShow = \"loading\";\r\n $scope.errorMessage = \"\";\r\n $scope.showImage = showImage;\r\n $scope.imageData = \"\";\r\n $scope.closeImage=closeImage;\r\n\r\n $scope.init = function () {\r\n checkConnectionStatus();\r\n }\r\n $scope.init();\r\n\r\n /**\r\n * Fetches the reports\r\n * @memberof ReportsHistoryCtrl \r\n */\r\n function fetchReports() {\r\n ReportsHistoryFactory.getReportsHistory(reportId,reportType)\r\n .then(response => handleResponse(response))\r\n .catch(function () { showError(\"We could not get any reports!\"); });\r\n }\r\n\r\n /**\r\n * Displays the error message\r\n * @memberof ReportsHistoryCtrl \r\n * @param {string} message message to display\r\n */\r\n function showError(message) {\r\n $scope.contentToShow = \"error\";\r\n $scope.errorMessage = message;\r\n }\r\n\r\n /**\r\n * Checks if the client is online or offline \r\n * if is online fetches the reports else displays relative message\r\n * @memberof ReportsHistoryCtrl \r\n */\r\n function checkConnectionStatus() {\r\n var isOnline = window.navigator.onLine;\r\n if (isOnline) {\r\n fetchReports()\r\n }\r\n else {\r\n showError(\"Please check the internet connection!\");\r\n }\r\n }\r\n\r\n /**\r\n * Handles the response from the API \r\n * if is success displays the reports else shows the error message.\r\n * @memberof ReportsHistoryCtrl \r\n * @param {object} response the response object from API\r\n */\r\n function handleResponse(response) {\r\n if (response.data.success) {\r\n if (response.data.data.length > 0) {\r\n $scope.contentToShow = \"reports\";\r\n $scope.reports = response.data.data;\r\n }\r\n else {\r\n showError(\"There are no reports for this flight!\");\r\n }\r\n }\r\n else {\r\n showError(\"We could not get any reports!\");\r\n }\r\n }\r\n\r\n /**\r\n * Displays the image in bootbox dialog box\r\n * @memberof ReportsHistoryCtrl \r\n * @param {object} ImageData The\r\n */\r\n function showImage(ImageData) {\r\n $scope.contentToShow = \"image\";\r\n $scope.imageData = ImageData;\r\n }\r\n \r\n /**\r\n * The function that closes the image and displays the reports again\r\n * @memberof ReportsHistoryCtrl \r\n */\r\n function closeImage(){\r\n $scope.contentToShow = \"reports\";\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('ReportsHistoryFactory', ReportsHistoryFactory)\r\n\r\n /* @ngInject */\r\n function ReportsHistoryFactory($http, apiUrl) {\r\n\r\n /**\r\n * Fetches the ReportIncidents from API\r\n * @memberof ReportsHisReportsHistoryFactorytoryCtrl \r\n */\r\n function getReportsHistory(reportId, reportType) {\r\n return $http.get(apiUrl + '/reports/GetHistoryReport?reportId=' + reportId + '&type=' + reportType, { 'Content-Type': 'application/json' })\r\n .then(x => { return x });\r\n }\r\n\r\n var service = {\r\n getReportsHistory: getReportsHistory,\r\n }\r\n return service;\r\n }\r\n\r\n})(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.filter('searchTextFilterforCategories', searchTextFilterforCategories);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc filter\r\n * @name searchTextFilterforCategories\r\n * @description \r\n * Filter questions by search text\r\n * @ngInject\r\n */\r\nfunction searchTextFilterforCategories() {\r\n return function (input, obj) {\r\n\t\r\n\t\t\tvar items = {\r\n\t\t\t\t\tsearchText: (obj.searchText) ? obj.searchText.toLowerCase():\"\",\r\n\t\t\t\t\tout: []\r\n\t\t\t};\r\n\t\t\tif(!items.searchText || items.searchText == ''){\r\n\t\t\t\titems.out = input;\r\n\t\t\t}else{\r\n\t\t\t\tangular.forEach(input, function (value, key) {\r\n\t\t\t\t\t\tif (value.Label.toLowerCase().indexOf(this.searchText) >= 0 || value.Description.toLowerCase().indexOf(this.searchText) >= 0) {\r\n\t\t\t\t\t\t\t\tthis.out.push(value);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t}, items);\r\n\t\t\t}\r\n\r\n\t\t\tvar categoryLabels = items.out.dynamicSort('CategoryOrderNo').map(function(r){\r\n\t\t\t\treturn r.CategoryLabel;\r\n\t\t\t});\r\n\r\n\t\t\treturn categoryLabels.unique();\r\n\t };\r\n\t};\r\n })(); ","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.factory('ServerCabinReportFactory',ServerCabinReportFactory)\r\n\r\n/* @ngInject */ \r\nfunction ServerCabinReportFactory($log,GenericService){\r\n\r\n\t\tfunction ServerCabinReport() {\r\n\t\t\tthis.AuthorAimsId = null;\r\n\t\t\tthis.AuthorName = null;\r\n\t\t\tthis.Created = null;\r\n\t\t\tthis.FlightAimsId = null;\r\n\t\t\tthis.FlightId=null;\r\n\t\t\tthis.LastUpdated = null;\r\n\t\t\tthis.ReportGuid = null;\r\n\t\t\tthis.ReportId = null;\r\n\t\t\tthis.getDescription = getDescription;\r\n\t\t}\r\n\r\n\t\tfunction getDescription() {\r\n\t\t\tif (this.Created == null && this.AuthorName == null) return '-null-';\r\n\t\t\telse return (this.Created || '?') + ' - ' + (this.AuthorName || '?');\r\n\t\t}\r\n\t\t\r\n\t\tvar objCallback = ServerCabinReport;\r\n\r\n\t\tvar service = {\r\n\t\t\t\tfromObjectList : fromObjectList,\r\n\t\t}\r\n\r\n\t\tfunction fromObjectList(objList) {\r\n\t\t\treturn GenericService.fromObjectList(objList,objCallback);\r\n\t\t}\r\n\t\r\n\treturn service;\r\n\t}\r\n\r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.factory('ServerPilotReportFactory',ServerPilotReportFactory)\r\n\r\n/* @ngInject */ \r\nfunction ServerPilotReportFactory(GenericService){\r\n\t\t// Define the constructor function.\r\n\t\tfunction ServerPilotReport() {\r\n\t\t\tthis.AuthorAimsId = null;\r\n\t\t\tthis.AuthorName = null;\r\n\t\t\tthis.Created = null;\r\n\t\t\tthis.FlightAimsId = null;\r\n\t\t\tthis.FlightId=null;\r\n\t\t\tthis.LastUpdated = null;\r\n\t\t\tthis.ReportGuid = null;\r\n\t\t\tthis.ReportId = null;\r\n\t\t\tthis.ReportedItems = null;\r\n\t\t\tthis.Source = null;// use ServerPilotReport.constSource* values\r\n\t\t\tthis.getDescription = getDescription;\r\n\t\t\tthis.isNothingToReport = isNothingToReport;\r\n\t\t}\r\n\r\n\t\tvar objCallback = ServerPilotReport;\r\n\t\r\n\t\tfunction getDescription() {\r\n\t\t\tif (this.Created == null && this.AuthorName == null && this.ReportedItems == null) return '-null-';\r\n\t\t\telse return (this.AuthorAimsId || '?') + ' ' + (this.AuthorName || '?') + ' @ ' + (this.Created || '?') + (this.ReportedItems || 0) ==0 ? ' :: Nothing to report' : (this.ReportedItems || 0) + ' items logged';\r\n\t\t}\r\n\t\t\t\t\t\t\r\n\t\tfunction isNothingToReport(){\r\n\t\t\treturn (this.ReportedItems || 0) == 0;\r\n\t\t}\r\n\r\n\t\tvar service = {\r\n\t\t\tfromObjectList : fromObjectList, \r\n\t\t\tconstSourceLocalOwn : 'localOwn', // stored locally by this user\r\n\t\t\tconstSourceLocalOther : 'localOther', // stored locally by another user\r\n\t\t\tconstSourceStoredOwn : 'storedOwn', // stored on the server by this user\r\n\t\t\tconstSourceStoredOther : 'storedOther' // stored on the server by another user\r\n\t\t}\r\n\r\n\t\tfunction fromObjectList(objList) {\r\n\t\t\treturn GenericService.fromObjectList(objList,objCallback);\r\n\t\t};\r\n\t\r\n\treturn service;\t\t\t\t\t\t \r\n\t}\r\n\r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.filter('unique', unique)\r\n\r\n/* @ngInject */ \r\nfunction unique() {\r\n return function(input, key) {\r\n var unique = {};\r\n var uniqueList = [];\r\n for(var i = 0; i < input.length; i++){\r\n if(typeof unique[input[i][key]] == \"undefined\"){\r\n unique[input[i][key]] = \"\";\r\n uniqueList.push(input[i]);\r\n }\r\n }\r\n return uniqueList;\r\n }\r\n}\r\n\r\n })(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('FatigueCtrl', FatigueCtrl);\r\n\r\n function FatigueCtrl($scope, $routeParams, FlightFactory, SafetyReportFactory, $location) {\r\n var flightId = $routeParams.flightId;\r\n var flight = FlightFactory.getFlightFromStorage(flightId);\r\n\r\n $scope.flight = flight;\r\n $scope.responseMessage = \"\";\r\n $scope.showPanel = \"submit\";\r\n $scope.formData = {\r\n flightId: $routeParams.flightId,\r\n flightNo: flight.FlightNo,\r\n flightDate: flight.ScheduledDeparture,\r\n flightDep: flight.Departure,\r\n flightArr: flight.Arrival,\r\n flightRegistration: flight.AcTailNo,\r\n occurenceTitle: \"\",\r\n description: \"\",\r\n attachedFiles: []\r\n };\r\n\r\n $scope.sizeLimitKb = 25000;\r\n $scope.fileTooLargeMsg = false;\r\n $scope.confirmCreateFatigueReport = confirmCreateFatigueReport;\r\n $scope.fileUploaded = fileUploaded;\r\n $scope.removeFile = removeFile;\r\n $scope.isIFileTooLarge = isFileTooLarge;\r\n $scope.submitFatigueReport = submitFatigueReport;\r\n\r\n \r\n function submitFatigueReport() {\r\n if ($scope.fatigueReport.$valid) {\r\n confirmCreateFatigueReport();\r\n } else {\r\n bootbox.alert(\"Please fill in all the required fields.\");\r\n }\r\n }\r\n\r\n function confirmCreateFatigueReport() {\r\n bootbox.dialog({\r\n message: \"Would you like to proceed with the Fatigue Report?

\",\r\n title: \"Send Report\",\r\n buttons: {\r\n confirm: {\r\n label: 'Confirm',\r\n className: \"btn-success\",\r\n callback: function () {\r\n $scope.showPanel = \"loading\";\r\n SafetyReportFactory.saveFatigueReport($scope.formData)\r\n .then(res => handleSubmitResponse(res));\r\n }\r\n },\r\n cancel: {\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function () { }\r\n }\r\n }\r\n })\r\n }\r\n\r\n function handleSubmitResponse(res) {\r\n var alertStyle = res.success ? \"success\" : \"warning\";\r\n\r\n bootbox.dialog({\r\n message: \"
\" + res.message + \"
\",\r\n title: \"Response Message\",\r\n buttons: {\r\n cancel:{\r\n label: \"Close\",\r\n className: \"btn-default\",\r\n callback: function(){\r\n if (res.success) {\r\n $timeout(gotoFlightInfo(flightId));\r\n }\r\n else {\r\n $timeout($scope.showPanel = \"submit\");\r\n }\r\n }\r\n } \r\n }\r\n })\r\n \r\n }\r\n\r\n function isFileTooLarge(image) {\r\n var isLarge= false;\r\n if (image && image.dataURL != null) {\r\n isLarge = (image.dataURL.length > $scope.sizeLimitKb * 1024);\r\n }\r\n return isLarge;\r\n }\r\n \r\n function fileUploaded(data) {\r\n var fileResult = data; //$scope.imageBrowsed;\r\n var uploadedFile = {};\r\n \r\n uploadedFile.fileBlobb = fileResult.dataURL;\r\n uploadedFile.description = fileResult.fileType || fileResult.file.type;\r\n uploadedFile.fileName = fileResult.fileName;\r\n \r\n // var files = $scope.formData.attachedFiles;\r\n if ($scope.formData.attachedFiles.length < 5) {\r\n // var n = Object.create(attachedFile);\r\n $scope.formData.attachedFiles.push(uploadedFile);\r\n \r\n } else {\r\n $scope.showMaxFiles = true;\r\n }\r\n }\r\n \r\n function removeFile(attachedFile){\r\n var files = $scope.formData.attachedFiles;\r\n var arrayLenght = files.length;\r\n var itemIndex = -1;\r\n for (var i = 0; i < arrayLenght; i++) {\r\n if (files[i].fileName == attachedFile.fileName) {\r\n itemIndex = i;\r\n break;\r\n }\r\n }\r\n \r\n if (itemIndex >= 0) {\r\n files.splice(itemIndex, 1);\r\n \r\n return attachedFile;\r\n }\r\n if($scope.showMaxImages){\r\n appendPhoto();\r\n }\r\n $scope.showMaxImages = false;\r\n \r\n }\r\n\r\n function gotoFlightInfo(flightId){\r\n $location.path('/flightinfo/' + flightId);\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.controller('SafetyCtrl', SafetyCtrl);\r\n\r\nfunction SafetyCtrl($scope,$timeout, operationalPhases, $routeParams, FlightFactory, SafetyReportFactory, UserFactory, $location){\r\n var flightId = $routeParams.flightId;\r\n var flight = FlightFactory.getFlightFromStorage(flightId);\r\n var user = UserFactory.getUser();\r\n $scope.flight = flight;\r\n \r\n $scope.tcas = false;\r\n\t$scope.egpws = false;\r\n $scope.bird = false;\r\n $scope.selectedCategory = \"General\";\r\n $scope.operationalPhases = angular.fromJson(operationalPhases);\r\n $scope.categories= [ \"General\", \"TCAS\", \"Bird Strike\", \"EGPWS\"];\r\n $scope.usefulnesses = [\"NECESSARY\", \"NUISANCE\", \"USEFUL\"];\r\n $scope.showMaxImages = false;\r\n\r\n $scope.responseMessage = \"\";\r\n $scope.showPanel = \"submit\";\r\n\r\n $scope.formData = {\r\n flightId: $routeParams.flightId,\r\n flightNo: flight.FlightNo,\r\n flightDate: flight.ScheduledDeparture,\r\n flightDep:flight.Departure,\r\n flightArr: flight.Arrival,\r\n flightRegistration: flight.AcTailNo,\r\n occurenceTitle: \"\",\r\n description: \"\",\r\n selectedPhase: \"\",\r\n meteo: \"\",\r\n trainingFlight: findTrainingFlight(),\r\n attachedFiles: [],\r\n // tcasType: {}, \r\n \r\n atcCallsign: \"\",\r\n alertType: \"\",\r\n usefulness: \"\",\r\n originalRa: \"\",\r\n subsequentRa: \"\",\r\n isRaFollowed: \"\",\r\n eventLocation: \"\",\r\n airMiss: \"\",\r\n trafficBearing: null,\r\n distance: null,\r\n altitude: null,\r\n relativeAltitude: null,\r\n visualContact: \"\",\r\n seatbeltSign: \"\",\r\n paxNo: null,\r\n\r\n // birdStrikeType: {},\r\n birdSpecies: \"\",\r\n numberSeen: \"\",\r\n birdNo: null,\r\n birdSize: \"\",\r\n areaOfDamage: \"\",\r\n speed: null,\r\n height: null,\r\n hasPilotWarned: \"\",\r\n birdEventLocation: \"\",\r\n runwayUsed: \"\",\r\n //egpwsType: {}\r\n eqpwsEventLocation: \"\"\r\n };\r\n\r\n $scope.confirmCreateReport = confirmCreateReport;\r\n $scope.fileUploaded = fileUploaded;\r\n $scope.removeFile = removeFile;\r\n $scope.showSelectedCategory = showSelectedCategory;\r\n $scope.submitForm = submitForm;\r\n\r\n function findTrainingFlight(){\r\n return flight.crew.some(function(item){\r\n return item.aimsId == user.aimsId && item.TrainingIndicatorCode != null && item.TrainingIndicatorCode.length > 0;\r\n })\r\n }\r\n\r\n function showSelectedCategory() {\r\n\r\n if ($scope.selectedCategory == \"TCAS\"){\r\n $scope.tcas = true;\r\n $scope.egpws = false;\r\n $scope.bird = false;\r\n clearForm();\r\n }\r\n else if ($scope.selectedCategory == \"EGPWS\"){\r\n $scope.egpws = true;\r\n $scope.tcas = false;\r\n $scope.bird = false;\r\n clearForm();\r\n }\r\n else if ($scope.selectedCategory == \"Bird Strike\"){\r\n $scope.bird = true;\r\n $scope.tcas = false;\r\n $scope.egpws = false;\r\n clearForm();\r\n }\r\n else {\r\n $scope.tcas = false;\r\n $scope.egpws = false;\r\n $scope.bird = false;\r\n clearForm();\r\n } \r\n }\r\n\r\n function clearForm(){\r\n // tcas type fields\r\n $scope.formData.atcCallsign = \"\";\r\n $scope.formData.alertType = \"\";\r\n $scope.formData.usefulness = \"\";\r\n $scope.formData.originalRa = \"\";\r\n $scope.formData.subsequentRa = \"\";\r\n $scope.formData.isRaFollowed = \"\";\r\n $scope.formData.eventLocation = \"\";\r\n $scope.formData.airMiss = \"\";\r\n $scope.formData.trafficBearing = null;\r\n $scope.formData.distance = null;\r\n $scope.formData.altitude = null;\r\n $scope.formData.relativeAltitude = null;\r\n $scope.formData.visualContact = \"\";\r\n $scope.formData.seatbelt = \"\";\r\n $scope.formData.paxNo = null;\r\n\r\n // bird strike type fields\r\n $scope.formData.birdSpecies = \"\";\r\n $scope.formData.numberSeen = \"\";\r\n $scope.formData.birdNo = null;\r\n $scope.formData.birdSize = \"\";\r\n $scope.formData.areaOfDamage = \"\";\r\n $scope.formData.speed = null;\r\n $scope.formData.height = null;\r\n $scope.formData.hasPilotWarned = \"\";\r\n $scope.formData.birdEventLocation = \"\";\r\n $scope.formData.runwayUsed = \"\";\r\n\r\n // egpws type field\r\n $scope.formData.eqpwsEventLocation = \"\";\r\n } \r\n\r\n function submitForm() { \r\n if ($scope.formFlightReport.$valid) {\r\n confirmCreateReport(); \r\n //console.log($scope.formData.attachedFiles); \r\n }else {\r\n bootbox.alert(\"Please fill in all the required fields.\");\r\n }\r\n }\r\n\r\n function confirmCreateReport() {\r\n bootbox.dialog({\r\n message: \"Would you like to proceed with the Safety Report?

\",\r\n title: \"Send Report\",\r\n buttons: {\r\n confirm:{\r\n label: 'Confirm',\r\n className: \"btn-success\",\r\n callback: function(){\r\n $scope.showPanel = \"loading\";\r\n SafetyReportFactory.saveSafetyReport($scope.formData)\r\n .then(res => handleSubmitResponse(res));\r\n }\r\n }, \r\n cancel:{\r\n label: \"Cancel\",\r\n className: \"btn-default\",\r\n callback: function(){}\r\n }\r\n }\r\n })\r\n } \r\n\r\n function handleSubmitResponse(res) {\r\n var alertStyle = res.success ? \"success\" : \"warning\";\r\n\r\n bootbox.dialog({\r\n message: \"
\" + res.message + \"
\",\r\n title: \"Response Message\",\r\n buttons: {\r\n cancel:{\r\n label: \"Close\",\r\n className: \"btn-default\",\r\n callback: function(){\r\n if (res.success) {\r\n $timeout(gotoFlightInfo(flightId));\r\n }\r\n else {\r\n $timeout($scope.showPanel = \"submit\");\r\n }\r\n }\r\n } \r\n }\r\n })\r\n \r\n }\r\n\r\n \r\n function isFileTooLarge(image) {\r\n var isLarge= false;\r\n if (image && image.dataURL != null) {\r\n isLarge = (image.dataURL.length > $scope.sizeLimitKb * 1024);\r\n }\r\n return isLarge;\r\n }\r\n\r\n function fileUploaded(data) {\r\n var fileResult = data; //$scope.imageBrowsed;\r\n var uploadedFile = {};\r\n\r\n\r\n if (isFileTooLarge(data)) {\r\n $scope.fileTooLargeMsg = true;\r\n } else {\r\n $scope.fileTooLargeMsg = false;\r\n uploadedFile.fileBlobb = fileResult.dataURL;\r\n uploadedFile.description = fileResult.fileType || fileResult.file.type;\r\n uploadedFile.fileName = fileResult.fileName;\r\n\r\n // var files = $scope.formData.attachedFiles;\r\n if ($scope.formData.attachedFiles.length < 5) {\r\n // var n = Object.create(attachedFile);\r\n $scope.formData.attachedFiles.push(uploadedFile);\r\n\r\n } else {\r\n $scope.showMaxFiles = true;\r\n }\r\n }\r\n }\r\n\r\n function removeFile(attachedFile){\r\n var files = $scope.formData.attachedFiles;\r\n var arrayLenght = files.length;\r\n var itemIndex = -1;\r\n for (var i = 0; i < arrayLenght; i++) {\r\n if (files[i].fileName == attachedFile.fileName) {\r\n itemIndex = i;\r\n break;\r\n }\r\n }\r\n \r\n if (itemIndex >= 0) {\r\n files.splice(itemIndex, 1);\r\n\r\n return attachedFile;\r\n }\r\n if($scope.showMaxImages){\r\n appendPhoto();\r\n }\r\n $scope.showMaxImages = false;\r\n }\r\n\r\n function gotoFlightInfo(flightId){\r\n $location.path('/flightinfo/' + flightId);\r\n }\r\n\r\n}\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('SafetyReportFactory', SafetyReportFactory);\r\n\r\n function SafetyReportFactory($http, apiUrl) {\r\n\r\n var submitResponseObj = { success: false, message: '' };\r\n \r\n var service = {\r\n saveSafetyReport: saveSafetyReport,\r\n saveFatigueReport: saveFatigueReport\r\n };\r\n\r\n function saveSafetyReport(safetyReport) {\r\n var aqdBaseURL = apiUrl + '/SafetyReports/SaveSafetyReport';\r\n return $http.post(aqdBaseURL, safetyReport, { 'Content-Type': 'application/json' })\r\n .then (res => getResponse(res))\r\n .catch(res => getResponseFailed(res));\r\n }\r\n\r\n function saveFatigueReport(fatigueReport) {\r\n var aqdBaseURL = apiUrl + '/SafetyReports/SaveFatigueReport';\r\n\r\n return $http.post(aqdBaseURL, fatigueReport, { 'Content-Type': 'application/json' })\r\n .then (res => getResponse(res))\r\n .catch(res => getResponseFailed(res));\r\n }\r\n\r\n function getResponse(res) {\r\n submitResponseObj.success = res.data.success;\r\n if (res.data.success) {\r\n submitResponseObj.message = \"Safety Report Submited successfully\";\r\n }\r\n else {\r\n submitResponseObj.message = res.data.errorMessage;\r\n }\r\n return submitResponseObj;\r\n }\r\n\r\n function getResponseFailed(res) {\r\n submitResponseObj.success = false;\r\n submitResponseObj.message = \"Something went wrong!\"\r\n return submitResponseObj;\r\n }\r\n\r\n return service;\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('AcknowledgeModalCtrl', AcknowledgeModalCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name AcknowledgeModalCtrl\r\n * @description \r\n * Warning Modal about unread mandatory memos\r\n * @ngInject\r\n */\r\n function AcknowledgeModalCtrl($scope, ScheduleAcknowledgeFactory, $route, $uibModalInstance) {\r\n\r\n $scope.ConfirmAcknowledge = ConfirmAcknowledge;\r\n $scope.cancel = cancel;\r\n $scope.showContent = 'confirm';\r\n $scope.responseObj = { success: false, message: '', Results: [] };\r\n $scope.results = [];\r\n\r\n function ConfirmAcknowledge(){\r\n $scope.showContent = 'loading';\r\n ScheduleAcknowledgeFactory.acknowledgeChanges()\r\n .then(res => handleSubmitResponse(res))\r\n .catch(res => handleSubmitResponse(res));\r\n \r\n }\r\n\r\n function handleSubmitResponse(res) {\r\n $scope.showContent = 'results';\r\n $scope.responseObj = res;\r\n }\r\n\r\n /**\r\n * Closes modal\r\n * @memberof ProposalInfoModalCtr\r\n */\r\n function cancel() {\r\n $uibModalInstance.close('cancel');\r\n\r\n if($scope.responseObj.success){\r\n $route.reload();\r\n }\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.factory('ScheduleAcknowledgeFactory', ScheduleAcknowledgeFactory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name ScheduleAcknowledgeFactory\r\n * @description \r\n * Get list, Update list & Acknowledge schedule changes\r\n * @ngInject\r\n */\r\n\tfunction ScheduleAcknowledgeFactory(localStorageMD5Service,GenericService, $http, apiUrl, defaultCalendarDate) {\r\n\r\n\r\n /**\r\n * Initialize the ScheduleChanges\r\n * @memberof ScheduleAcknowledgeFactory\r\n */\r\n function ScheduleChanges() {\r\n this.dates = [];\r\n this.showScheduleChangesModal = false;\r\n }\r\n\r\n var objType = 'ScheduleChanges';\r\n var objCallback = ScheduleChanges;\r\n\r\n var response = { success: false, \r\n message: '', \r\n Results: []\r\n };\r\n\r\n\t\tvar service = {\r\n\t\t\tsetAllScheduleChangesToStorage : setAllScheduleChangesToStorage,\r\n\t\t\tgetScheduleChangesFromStorage : getScheduleChangesFromStorage,\r\n updateShowScheduleChangesModal: updateShowScheduleChangesModal,\r\n showScheduleChangesModal: showScheduleChangesModal,\r\n hasScheduleChanges : hasScheduleChanges,\r\n acknowledgeChanges : acknowledgeChanges\r\n\t\t};\r\n\r\n\t\t/**\r\n\t\t * Save All Schedule changes\r\n\t\t * @param {array} objList \r\n\t\t */\r\n function setAllScheduleChangesToStorage(objList) {\r\n if(objList == null || !objList.length > 0){\r\n GenericService.removeAll(objType);\r\n }\r\n else{\r\n var scheduleChanges = { dates: objList, showScheduleChangesModal: true}\r\n GenericService.saveOne(scheduleChanges, objType, objCallback);\r\n\r\n //GenericService.saveAll(objList,objType);\r\n }\r\n }\r\n\r\n\t\t/**\r\n\t\t * Get all Schedule changes\r\n\t\t */\r\n function getScheduleChangesFromStorage(){\r\n var dateList = [];\r\n var scheduleChanges = GenericService.getOne(objType, objCallback);\r\n\r\n if(scheduleChanges != null && scheduleChanges.dates != null ){\r\n scheduleChanges.dates.forEach(function (dateS) {\r\n var stringToDate = moment.utc(dateS);\r\n dateList.push(stringToDate);\r\n });\r\n }\r\n \r\n return dateList;\r\n\t\t}\r\n\r\n /* Update scheduleChanges object to storage\r\n * @memberof ScheduleAcknowledgeFactory\r\n * @param {bool} canShowModal whether the modal can be display\r\n */\r\n function updateShowScheduleChangesModal(canShowModal){\r\n var scheduleChanges = GenericService.getOne(objType, objCallback);\r\n scheduleChanges.showScheduleChangesModal = canShowModal;\r\n GenericService.saveOne(scheduleChanges, objType, objCallback);\r\n }\r\n\r\n /**\r\n * ShowScheduleChangesModal check\r\n * @memberof ScheduleAcknowledgeFactory\r\n * @returns {bool} returns the value of showAutolandModal property\r\n */\r\n function showScheduleChangesModal(){\r\n var scheduleChanges = GenericService.getOne(objType, objCallback);\r\n\r\n if(scheduleChanges && scheduleChanges.dates != null && scheduleChanges.dates.length >0)\r\n {\r\n var fistChange = moment.utc(scheduleChanges.dates[0]);\r\n var today = moment.utc();\r\n if(defaultCalendarDate){\r\n today = moment.utc(defaultCalendarDate);\r\n }\r\n var datediff = fistChange.diff(today,'days'); \r\n\r\n return datediff <= 1 && scheduleChanges.showScheduleChangesModal; \r\n\r\n }else{\r\n return false;\r\n }\r\n }\r\n\r\n function hasScheduleChanges(){\r\n var dates = getScheduleChangesFromStorage(); \r\n\t\t\treturn dates != null && dates.length >0;\r\n }\r\n\r\n /**\r\n * Acknowledge Changes \r\n * @param {date} dateFrom The first schedule change date\r\n * @param {date} dateTo The last schedule change date\r\n * @returns {promise} response\r\n */\r\n function acknowledgeChanges(){\r\n //get dates from local storage\r\n var datesToAcknowledge = getScheduleChangesFromStorage();\r\n\r\n return $http.post(apiUrl + '/ScheduleAcknowledge/AcknowledgeScheduleChanges', datesToAcknowledge, { 'Content-Type': 'application/json' })\r\n .then(res => updateScheduleChangesCallBack(res))\r\n .catch(res => acknowledgeFailedCallBack(res));\r\n }\r\n\r\n /**\r\n * Update Schedule changes dates\r\n * @param {object} res \r\n * @param {object} objectToAdd \r\n * @returns {object} response\r\n */\r\n function updateScheduleChangesCallBack(res) {\r\n response.success = res.data.success;\r\n if (res.data.success) {\r\n //update local storage\r\n setAllScheduleChangesToStorage(res.data.data.DatesWithChanges);\r\n response.message = \"Success! Your Acknowledge has been sent\";\r\n response.Results = res.data.data.Results;\r\n }\r\n else {\r\n response.message = res.data.errorMessage\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * The callback function upon failure on submit\r\n * @returns {object} response\r\n */\r\n function acknowledgeFailedCallBack(res) {\r\n \r\n response.success = false;\r\n response.message = \"Oops! Something went wrong\"\r\n\r\n //TODO::Check status=500 error: returns res = {data: {…}, status: 500, config: {…}, statusText: \"Internal Server Error\", headers: ƒ}\r\n // res.data.data is null\r\n if(res.data.data && res.data.data.Results){\r\n response.Results = res.data.data.Results;\r\n }else{\r\n //log results\r\n console.log(res);\r\n }\r\n return response;\r\n }\r\n\r\n\r\n\t\treturn service;\r\n\t}\r\n})();\r\n","(function () {\r\n'use strict';\r\n\r\na3_pilot_reports.service(\"SWUpdateService\", SWUpdateService);\r\n\r\n/**\r\n* @memberof PilotReports\r\n* @ngdoc service\r\n* @name SWUpdateService\r\n* @description \r\n* manages the service-worker update\r\n* @ngInject\r\n*/\r\nfunction SWUpdateService(LogService) {\r\n /**\r\n * initialize service worker\r\n * @memberof SWUpdateService\r\n */\r\n function initialize() {\r\n // Delay registration until after the page has loaded\r\n window.addEventListener('load', function () {\r\n //kill switch. uncomment this and comment out everything else sw related\r\n // navigator.serviceWorker.getRegistrations().then(function (registrations) {\r\n // //returns installed service workers\r\n // if (registrations.length) {\r\n // for(var registration of registrations) {\r\n // registration.unregister();\r\n // }\r\n // }\r\n // });\r\n\r\n //register the service worker and work with the promise it returns\r\n navigator.serviceWorker.register('service-worker.js').then(function (reg) {\r\n // use a variable to make sure we refresh the page only once\r\n var refreshing;\r\n\r\n //fires when a new Service Worker takes control of the current page (refreshes the page)\r\n navigator.serviceWorker.addEventListener('controllerchange', function () {\r\n if (refreshing) return;\r\n refreshing = true;\r\n window.location.reload();\r\n });\r\n }).catch(function (e) {\r\n LogService.error(e, 'Tried to register the service worker');\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * poll the server for new service worker file (new app version)\r\n * @memberof SWUpdateService\r\n */ \r\n function checkUpdates(reg) {\r\n if (reg == null)\r\n return;\r\n \r\n //ask server for new service worker\r\n reg.update();\r\n }\r\n\r\n /**\r\n * If new service worker has been waiting too long, force update\r\n * @memberof SWUpdateService\r\n */\r\n function checkVersionExpiration(reg) {\r\n if (reg == null)\r\n return;\r\n reg.waiting.postMessage('checkVersionExpiration');\r\n }\r\n\r\n /**\r\n * Activate the new service worker that was waiting\r\n * @memberof SWUpdateService\r\n */\r\n function update(reg){\r\n reg.waiting.postMessage('skipWaiting');\r\n }\r\n\r\n return {\r\n initialize: initialize,\r\n checkUpdates: checkUpdates,\r\n checkVersionExpiration: checkVersionExpiration,\r\n update: update\r\n };\r\n}\r\n\r\n})();","(function () {\r\n\t'use strict';\r\n\r\n\ta3_pilot_reports.service(\"InfoAPIService\", InfoAPIService);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name InfoAPIService\r\n * @description \r\n * Information service which gets latest pax and gate data\r\n * @ngInject\r\n */\r\n\tfunction InfoAPIService($http, $q, apiUrl, LogService, SyncAPIService, UserFactory, FlightGateFactory, FlightFactory, PaxInfoFactory, AircaftPositionsFactory, GroundDutyFactory, FlightCheckInsFactory) {\r\n /**\r\n * get latest Passenger information\r\n * @memberof InfoAPIService\r\n * @return {object} promise\r\n */\r\n\t\tfunction getPax(flightId) {\r\n\r\n\t\t\t//Prepare to request training courses fetch\r\n\t\t\tvar flight = FlightFactory.getFlightFromTotalFlights(flightId);\r\n\t\t\tvar flightInfo = {\r\n\t\t\t\tFlightId: flightId,\r\n\t\t\t\tFlightCourses : flight ? flight.Courses : []\r\n\t\t\t};\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tvar user = UserFactory.getUser();\r\n\t\t\tvar call = $q.defer();\r\n\t\t\t$http.post(apiUrl + '/info/Pax', flightInfo, { 'Content-Type': 'application/json' })\r\n\t\t\t\t.then(\r\n\t\t\t\t\tfunction (responseData) {\r\n\t\t\t\t\t\tif (responseData == undefined || responseData.data == undefined || responseData.data.data == undefined) {\r\n\t\t\t\t\t\t\tvar err = new Error();\r\n\t\t\t\t\t\t\terr.status = -1;\r\n\t\t\t\t\t\t\tvar msg = \"ResponseData error in info/gates :\" + JSON.stringify(responseData);\r\n\t\t\t\t\t\t\tLogService.debug(msg, err)\r\n\t\t\t\t\t\t\tcall.reject(err);\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar newDutyInfo = responseData.data.data;\r\n newDutyInfo.FlightId = flightId;\r\n updateFlightLocalStorage(newDutyInfo);\r\n\r\n\t\t\t\t\t\tupdateCrewCheckIn(newDutyInfo);\r\n\r\n\t\t\t\t\t\t// return true\r\n\t\t\t\t\t\tcall.resolve(responseData);\r\n\t\t\t\t\t},\r\n\t\t\t\t\tfunction (err) {\r\n\t\t\t\t\t\tcall.reject(err);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\treturn call.promise;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Gets latest info for each duty in a crew route\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {object} crewRouteDuty \r\n\t\t * @param {function} callback \r\n\t\t */\r\n\t\tfunction refreshCrewRoute(crewRouteDuty , callback) {\r\n\r\n\t\t\tvar crewRouteInfo = {\r\n dutyNo: crewRouteDuty.DutyNo,\r\n dutyDay: crewRouteDuty.DutyDay,\r\n from: crewRouteDuty.DutyBegin,\r\n to: crewRouteDuty.DutyEnd,\r\n FlightCourses: crewRouteDuty.Courses\r\n };\r\n\r\n\t\t\treturn $http.post(apiUrl + '/info/RefreshCrewRoute', crewRouteInfo, { 'Content-Type': 'application/json' })\r\n\t\t\t.then(callback);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Updates Flight's Data Status depending on Refresh respond\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {object} newDuty - Refresh respond\r\n\t\t * @param {array} dataStatus \r\n\t\t */\r\n\t\tfunction updateFlightStatusSetter(newDuty, dataStatus){\r\n\t\t\tif (newDuty.FlightInfo) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Flight Status\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Flight Status\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.AircraftPositions && newDuty.AircraftPositions.length > 0) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Aircraft Movement\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Aircraft Movement\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.FlightInfo && newDuty.FlightInfo.crew && newDuty.FlightInfo.crew.length > 0) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Crew Info\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Crew Info\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.FlightInfo && newDuty.FlightInfo.crew && newDuty.FlightInfo.crew.length > 0 && newDuty.FlightInfo.crew.filter(x => x.PhoneNumber != null).length > 0) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Crew Contacts\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Crew Contacts\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.CabinServiceManagementLists && newDuty.CabinServiceManagementLists.length > 0) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Meals\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Meals\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.CabinServiceManagementLists && newDuty.CabinServiceManagementLists.length > 0 && newDuty.CabinServiceManagementLists[0].ConnectingFlights && newDuty.CabinServiceManagementLists[0].ConnectingFlights.length > 0) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Connections\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Connections\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.CabinServiceManagementLists && newDuty.CabinServiceManagementLists.length > 0 && newDuty.CabinServiceManagementLists[0].ConnectingFlights && newDuty.CabinServiceManagementLists.length > 0) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Pax Info\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Pax Info\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty.TrainingCourses && newDuty.TrainingCourses.length > 0) {\r\n updateStatusSetter(dataStatus, [\"Training Info\"], \"SUCCESS\", \"Successfully updated\");\r\n } else {\r\n updateStatusSetter(dataStatus, [\"Training Info\"], \"N/A\", \"No available data\");\r\n }\r\n\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Updates Ground Duty's Data Status depending on Refresh respond\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {array} newDuty - Refresh respond\r\n\t\t * @param {array} dataStatus \r\n\t\t */\r\n\t\tfunction updateGroundStatusSetter(newDuty, dataStatus){\r\n\t\t\tif(newDuty){\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Duty Info\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t}else{\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Duty\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\r\n\t\t\tif (newDuty && newDuty.RelatedGroundDuties && newDuty.RelatedGroundDuties.length > 1) {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Instructors\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Trainees\"], \"SUCCESS\", \"Successfully updated\");\r\n\t\t\t} else {\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Instructors\"], \"N/A\", \"No available data\");\r\n\t\t\t\tupdateStatusSetter(dataStatus, [\"Trainees\"], \"N/A\", \"No available data\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Changes the state of Data Status\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {array} dataStatus \r\n\t\t * @param {array} array - Datatype to change\r\n\t\t * @param {string} status - New status\r\n\t\t * @param {string} text - New text\r\n\t\t */\r\n\t\tfunction updateStatusSetter(dataStatus, array, status, text) {\r\n\r\n\t\t\tvar objsTochange = dataStatus.filter(function (x) {\r\n\t\t\t\tvar res = array.filter(function (s) { return s == x.datatype });\r\n\t\t\t\treturn res.length > 0 ? true : false;\r\n\t\t\t});\r\n\r\n\t\t\tobjsTochange.forEach(function (x) {\r\n\t\t\t\tx.status = status;\r\n\t\t\t\tx.text = text;\r\n\r\n\t\t\t\tvar index = dataStatus.map(function (x) { return x.datatype }).indexOf(x.datatype);\r\n\t\t\t\tdataStatus[index] = x;\r\n\t\t\t});\r\n\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Update Flight Info in Local Storage\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {object} duty \r\n\t\t */\r\n\t\tfunction updateFlightLocalStorage(duty){\r\n\t\t\t// save flight gates to local storage\r\n\t\t\t//var flightGates = duty.FlightGates;\r\n\t\t\t//FlightGateFactory.processUpdatedData(flightGates);\r\n\t\t\t//Update Aircraft positions\r\n\t\t\tif (duty.AircraftPositions != null && duty.AircraftPositions.length > 0) {\r\n\t\t\t\tAircaftPositionsFactory.updateAircraftPositionsToStorage(duty.AircraftPositions[0], duty.FlightId);\r\n\t\t\t}\r\n \r\n\t\t\t// update flight to local storage\r\n\t\t\tFlightFactory.mergeFlightInfo(duty.FlightInfo);\r\n\t\t\t//Enrich flight info after sync\r\n\t\t\tSyncAPIService.updatePilotReportLocalEditFromSynch();\r\n\t\t\t// update paxinfo to local storage\r\n\r\n\t\t\tif (duty.CabinServiceManagementLists && duty.CabinServiceManagementLists.length > 0) {\r\n\t\t\t\tPaxInfoFactory.updatePaxInfo(duty.CabinServiceManagementLists[0]);\r\n\t\t\t}\r\n\r\n\t\t\t// update messages to local storage\r\n\t\t\t// MessageFactory.markReadAsSynched(duty.Messages);\r\n\t\t\t// MessageFactory.storeMessagesFromServer(duty.Messages);\r\n\r\n\t\t}\r\n\t\t/**\r\n\t\t * Update Flight crew check-in Info in Local Storage\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {object} duty \r\n\t\t */\r\n\t\tfunction updateCrewCheckIn (duty){\r\n\t\t\tif(duty.FlightInfo){\r\n\t\t\t\tFlightCheckInsFactory.updateFlightCrewCheckInToStorage(duty);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Update Ground Duty Info in Local Storage\r\n\t\t * @memberof InfoAPIService\r\n\t\t * @param {object} duty \r\n\t\t */\r\n\t\tfunction updateGroundDutyLocalStorage(duty){\r\n\t\t\tGroundDutyFactory.mergeGroundDutyInfo(duty);\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tgetPax: getPax,\r\n\t\t\trefreshCrewRoute : refreshCrewRoute,\r\n updateFlightStatusSetter : updateFlightStatusSetter,\r\n updateGroundStatusSetter : updateGroundStatusSetter,\r\n updateStatusSetter : updateStatusSetter,\r\n updateFlightLocalStorage : updateFlightLocalStorage,\r\n updateGroundDutyLocalStorage : updateGroundDutyLocalStorage\r\n\t\t};\r\n\t}\r\n})(); ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.service(\"SyncAPIService\", SyncAPIService);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name SyncAPIService\r\n * @description \r\n * Generic Sync service which sends all your reports and Get all the latest data\r\n * @ngInject\r\n */\r\n function SyncAPIService($http, $q, apiUrl\r\n , FlightFactory, ReportGuidFactory, PilotReportTemplateFactory, SyncLogFactory, PilotReportLocalEditFactory\r\n , PilotReportSendToServerFactory, PilotReportSyncResultFactory, AircraftTypeFactory, DataCleanerFactory\r\n , MessageFactory, LogService, GroundDutyFactory, FlightGateFactory, MemoFactory, PaxInfoFactory, CrewRouteFactory, CrewMealFactory\r\n , MemoImagesFactory, AircaftPositionsFactory, AirportContactFactory, AirportHotelFactory, AimsCrewMemosFactory\r\n , GroundServicesFactory, LeaveRequestFactory, AutolandFactory, CrewHotelFactory, CourseFactory, ScheduleAcknowledgeFactory \r\n , CrewCallFactory, PreviousDutyFactory, LogCallFactory, CheckInFactory,FlightCheckInsFactory) {\r\n\r\n /**\r\n * Find if a relative old flight exists and if exists update it \r\n * @memberof SyncAPIService\r\n * @param {object} oldflight\r\n * @param {array} flights\r\n * @return {boolean} hasRelativeFlight\r\n */\r\n function relativeFlightMatcher(oldflight, flights) {\r\n var relativeReports = [];\r\n var relativeFlights = [];\r\n var found = false;\r\n\r\n for (var i = 0; i < flights.length; i++) {\r\n if (oldflight.FlightNo == flights[i].FlightNo && oldflight.FlightDate == flights[i].FlightDate && oldflight.Departure == flights[i].Departure) {\r\n relativeFlights.push(flights[i]);\r\n found = true;\r\n break;\r\n }\r\n }\r\n\r\n if (!found) {\r\n var flight = null;\r\n var oldFlightNo = null;\r\n var lastDigit = oldflight.FlightNo.substr(oldflight.FlightNo.length - 1, 1)\r\n\r\n oldFlightNo = (!isNaN(lastDigit)) ? oldflight.FlightNo : oldflight.FlightNo.substr(0, oldflight.FlightNo.length - 1);\r\n\r\n\r\n for (var i = 0; i < flights.length; i++) {\r\n lastDigit = flights[i].FlightNo.substr(flights[i].FlightNo.length - 1, 1);\r\n\r\n flight = (!isNaN(lastDigit)) ? flights[i].FlightNo : flights[i].FlightNo.substr(0, flights[i].FlightNo.length - 1);\r\n\r\n if (oldFlightNo == flight && oldflight.FlightDate == flights[i].FlightDate && oldflight.Departure == flights[i].Departure) {\r\n relativeFlights.push(flights[i]);\r\n }\r\n }\r\n }\r\n\r\n if (relativeFlights.length == 1) {\r\n var pilotReportLocalEdit = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(oldflight.FlightId);\r\n pilotReportLocalEdit.FlightAimsId = relativeFlights[0].FlightAimsId;\r\n pilotReportLocalEdit.FlightId = relativeFlights[0].FlightId;\r\n PilotReportLocalEditFactory.setPilotReportToStorage(pilotReportLocalEdit);\r\n\r\n return true;\r\n } else if (relativeFlights.length > 1) {\r\n for (var i = 1; i < relativeFlights.length; i++) {\r\n for (var j = 0; j < relativeFlights.length - i; j++) {\r\n if (relativeFlights[j].FlightNo > relativeFlights[j + 1].FlightNo) {\r\n var a = relativeFlights[j];\r\n relativeFlights[j] = relativeFlights[j + 1];\r\n relativeFlights[j + 1] = a;\r\n }\r\n }\r\n }\r\n\r\n var pilotReportLocalEdit = PilotReportLocalEditFactory.getPilotReportLocalEditForFlight(oldflight.FlightId);\r\n pilotReportLocalEdit.FlightAimsId = relativeFlights[0].FlightAimsId;\r\n pilotReportLocalEdit.FlightId = relativeFlights[0].FlightId;\r\n PilotReportLocalEditFactory.setPilotReportReportToStorage(pilotReportLocalEdit);\r\n\r\n return true;\r\n } else {\r\n\r\n return false;\r\n }\r\n\r\n\r\n };\r\n return {\r\n /**\r\n * Send and get the latest information \r\n * @memberof SyncAPIService\r\n * @param {object} aimsId\r\n * @param {array} memoIdsToSend \r\n */\r\n doSync: function (aimsId, memoIdsToSend) {\r\n\r\n //clear CrewMeal ratings from local storage that have timestamp older than 20 days\r\n DataCleanerFactory.deleteOldCrewMealsRatings();\r\n\r\n // get the saved pilot reports\r\n var allSavedReports = PilotReportLocalEditFactory.getPilotReportsFromStorage();\r\n\r\n // keep only the ones that are ready to be sent\r\n var reportsToSend = PilotReportSendToServerFactory.getCompletedListFromPilotReportLocalEdits(allSavedReports);\r\n var messagesToSend = MessageFactory.getMessagesFromStorage();\r\n\r\n var lastLog = SyncLogFactory.getSyncLog();\r\n var lastSyncDate = lastLog.date;\r\n\r\n //Get call requests made while offline\r\n var phoneCallLog = {\r\n CrewCallReports: LogCallFactory.getLogCallsFromStorage()\r\n }\r\n\r\n var syncData = {\r\n \"SyncPilotReports\": reportsToSend, \"Messages\": messagesToSend,\r\n \"MemoIds\": memoIdsToSend,\r\n \"CrewCallLog\" : phoneCallLog,\r\n \"LastSyncDate\": lastSyncDate\r\n };\r\n\r\n var call = $q.defer();\r\n\r\n $http.post(apiUrl + '/sync', syncData, { 'Content-Type': 'application/json' })\r\n .then(\r\n function (responseData) {\r\n if (responseData == undefined \r\n || responseData.data == undefined \r\n || responseData.data.data == undefined\r\n || responseData.data.data.SyncPilotData == undefined) {\r\n var err = new Error();\r\n err.status = -1;\r\n var msg = \"ResponseData error in sync :\" + JSON.stringify(responseData);\r\n LogService.debug(msg, err)\r\n call.reject(err);\r\n return;\r\n }\r\n var response = responseData.data.data;\r\n \r\n //keep flights, will be used to retain a flight for old unsynched reports\r\n var orgFlights = FlightFactory.getFlightsFromStorage();\r\n\r\n // clear existing server data\r\n FlightFactory.clearFlightsFromStorage();\r\n ReportGuidFactory.clearReportGuidsFromStorage();\r\n PilotReportTemplateFactory.clearPilotReportTemplateFromStorage();\r\n AircraftTypeFactory.clearAircraftTypesFromStorage();\r\n PilotReportSyncResultFactory.clearPilotReportSyncResultsFromStorage();\r\n MessageFactory.clearMessagesFromStorage();\r\n // save flight data to local storage\r\n var flightData = response.SyncPilotData.flights;\r\n var flights = FlightFactory.markScheduleChangedFlights(flightData, orgFlights);\r\n\r\n var pilotReports = response.SyncPilotData.pilotReports;\r\n var cabinReports = response.SyncPilotData.cabinReports;\r\n var messages = response.SyncPilotData.messages;\r\n\r\n for (var i = 0; i < messages.length; i++) {\r\n messages[i].AuthorName = messages[i].AuthorName.replace(\"GATEWAY\\\\\", \"\");\r\n messages[i].AuthorName = messages[i].AuthorName.replace(\".\", \" \");\r\n }\r\n\r\n MessageFactory.setMessagesToStorage(messages);\r\n\r\n GroundDutyFactory.mergeGroundDutiesToStorage(response.SyncPilotData.groundDuties);\r\n CrewRouteFactory.setCrewRoutesToStorage(response.SyncPilotData.CrewRoutes);\r\n CrewMealFactory.setCrewMealsToStorage(response.SyncPilotData.CateringCrewMeals);\r\n CrewHotelFactory.setCrewHotelsToStorage(response.SyncPilotData.CrewHotels);\r\n CheckInFactory.setCheckInInfoToStorage(response.CrewCheckInInfo);\r\n \r\n //Save schedule changes dates \r\n ScheduleAcknowledgeFactory.setAllScheduleChangesToStorage(response.SyncPilotData.ScheduleChanges)\r\n\r\n //clean crew call logs\r\n if(response.SyncPilotData.CrewCallLog && response.SyncPilotData.CrewCallLog.ResponseSuccess){\r\n LogCallFactory.cleanLogsFromStorage();\r\n }\r\n \r\n //save training courses\r\n var rawTrainingCourses = response.SyncPilotData.TrainingCourses;\r\n var courses = [];\r\n\r\n rawTrainingCourses.forEach(function(course) {\r\n courses.push({\r\n Id: course.Id,\r\n Title: course.Title,\r\n HasLimitedInfo: true\r\n });\r\n });\r\n\r\n CourseFactory.setCoursesFromServer(courses);\r\n\r\n //clean crew member info\r\n CrewCallFactory.cleanOldData(response.SyncPilotData.flights);\r\n PreviousDutyFactory.cleanOldData(response.SyncPilotData.flights);\r\n FlightCheckInsFactory.cleanOldData(response.SyncPilotData.flights);\r\n \r\n FlightGateFactory.processUpdatedData(response.SyncPilotData.flightGates);\r\n\r\n AircaftPositionsFactory.setAircaftPositionsToStorage(response.SyncPilotData.AircaftPositions);\r\n AirportContactFactory.setAirportContactsToStorage(response.SyncPilotData.AirportContacts);\r\n AirportHotelFactory.setAirportHotelsToStorage(response.SyncPilotData.AirportHotels);\r\n AutolandFactory.setAutolandToStorage(response.SyncPilotData.AutolandOperations, flightData)\r\n\r\n //save, update or add memos\r\n var memos = response.SyncPilotData.memos;\r\n MemoFactory.setMemosFromServer(memos, memoIdsToSend, lastSyncDate);\r\n\r\n //delete leftover memos\r\n var serverMemoIds = response.SyncPilotData.memoIds;\r\n for (var i = 0; i < serverMemoIds.length; i++) {\r\n MemoFactory.deleteMemoFromStorage(serverMemoIds[i]);\r\n }\r\n\r\n for (var i = 0; i < memos.length; i++) {\r\n MemoImagesFactory.deleteMemoImageByMemoId(memos[i].Id);\r\n }\r\n\r\n var images = response.SyncPilotData.Images;\r\n MemoImagesFactory.setImagesToServer(images);\r\n\r\n for (var i = 0; i < serverMemoIds.length; i++) {\r\n MemoImagesFactory.deleteMemoImageByMemoId(serverMemoIds[i]);\r\n }\r\n\r\n\r\n PaxInfoFactory.setPaxInfoToStorage(response.SyncPilotData.cabinServiceManagementLists);\r\n\r\n // save guids to local storage\r\n var reportGuids = response.SyncPilotData.guids;\r\n ReportGuidFactory.setReportGuidsToStorage(reportGuids);\r\n\r\n // save pilot report template to storage\r\n var pilotReportTemplate = response.SyncPilotData.pilotReportTemplate;\r\n PilotReportTemplateFactory.setPilotReportTemplateToStorage(pilotReportTemplate);\r\n\r\n // save aircraft types to local storage\r\n var aircraftTypes = response.SyncPilotData.aircraftTypes;\r\n AircraftTypeFactory.setAircraftTypesToStorage(aircraftTypes);\r\n\r\n //save all GroundServices to local storage\r\n var groundServices = response.SyncPilotData.GroundServices;\r\n GroundServicesFactory.setGroundServicesToStorage(groundServices);\r\n\r\n // save Aims Crew Memos to local storage\r\n AimsCrewMemosFactory.setAimsCrewMemosToStorage(response.SyncPilotData.aimsCrewMemos);\r\n\r\n // get the sync results\r\n var syncResults = PilotReportSyncResultFactory.fromObjectList(response.SyncPilotData.reportResults);\r\n\r\n // mark sent reports as synched\r\n for (var j = 0; j < reportsToSend.length; j++) {\r\n var syncResult = PilotReportSyncResultFactory.getSyncResult(syncResults, reportsToSend[j].ReportGuid);\r\n\r\n if (syncResult != null) {\r\n if (syncResult.success) {\r\n PilotReportLocalEditFactory.markReportAsSynched(reportsToSend[j].ReportGuid);\r\n syncResult.Result = 'Successfully submitted';\r\n } else {\r\n syncResult.Result = 'Submission error';\r\n }\r\n\r\n // find flight and append report fields (storage cleared: use orgFlight)\r\n var flight = null;\r\n if (orgFlights != null) {\r\n for (var i = 0; i < orgFlights.length; i++) {\r\n if ((orgFlights[i].FlightId != null && orgFlights[i].FlightId == reportsToSend[j].FlightId) || (orgFlights[i].FlightAimsId != null && orgFlights[i].FlightAimsId == reportsToSend[j].FlightAimsId)) {\r\n flight = orgFlights[i];\r\n break;\r\n }\r\n }\r\n }\r\n //var flight = FlightFactory.getFlightFromStorage(reportsToSend[j].FlightAimsId);\r\n\r\n if (flight != null) {\r\n syncResult.FlightAimsId = flight.FlightAimsId;\r\n syncResult.FlightId = flight.FlightId;\r\n syncResult.ScheduledDepartureDateUTC = flight.ScheduledDepartureDateUTC;\r\n syncResult.FlightNo = flight.FlightNo;\r\n syncResult.Departure = flight.Departure;\r\n syncResult.Arrival = flight.Arrival;\r\n syncResult.ScheduledDepartureTimeUTC = flight.ScheduledDepartureTimeUTC;\r\n syncResult.AcTailNo = flight.AcTailNo;\r\n }\r\n }\r\n }\r\n\r\n // save the sync results\r\n PilotReportSyncResultFactory.setPilotReportSyncResultsToStorage(syncResults);\r\n\r\n // log the sync user and date\r\n SyncLogFactory.setSyncLog(aimsId, response.SyncPilotData.version, response.SyncPilotData.toDate);\r\n\r\n // delete local flights with no local reports\r\n DataCleanerFactory.deleteOrphanedLocalFlights();\r\n\r\n LeaveRequestFactory.saveLeaveRequestInformation(response.SyncPilotData.LeaveRequestInformation);\r\n\r\n //**************** ADD CODE TO KEEP FLIGHTS IF THEY STIL HAVE AN NOT SYCNHED REPORT *********************//\r\n //find flight ids used by draft or completed (not synched for some reason) reports\r\n if (allSavedReports) {\r\n var verifyFlightAimsIds = [];\r\n var verifyFlightIds = [];\r\n for (var i = 0; i < allSavedReports.length; i++) {\r\n if (allSavedReports[i].Status == 'draft' || allSavedReports[i].Status == 'completed')\r\n verifyFlightAimsIds.push(allSavedReports[i].FlightAimsId);\r\n verifyFlightIds.push(allSavedReports[i].FlightId);\r\n }\r\n //search these ids into the newly received flights\r\n if (verifyFlightAimsIds.length > 0) {\r\n var missingIds = [];\r\n var missingAimsIds = [];\r\n var found, id, aimsId;\r\n for (var i = 0; i < verifyFlightAimsIds.length; i++) {\r\n found = false;\r\n aimsId = verifyFlightAimsIds[i];\r\n id = verifyFlightIds[i];\r\n for (var f = 0; f < flights.length; f++) {\r\n if ((flights[f].FlightId != null && flights[f].FlightId == id) || (flights[f].FlightAimsId != null && flights[f].FlightAimsId == aimsId)) {\r\n found = true;\r\n break;\r\n }\r\n }\r\n if (!found)\r\n missingIds.push(id);\r\n missingAimsIds.push(aimsId);\r\n }\r\n //search missing flights in flights stored before sync\r\n if (orgFlights) {\r\n for (var m = 0; m < missingIds.length; m++) {\r\n id = missingIds[m];\r\n aimsId = missingAimsIds[m];\r\n for (var o = 0; o < orgFlights.length; o++) {\r\n if ((orgFlights[o].FlightId != null && orgFlights[o].FlightId == id) || (orgFlights[o].FlightAimsId != null && orgFlights[o].FlightAimsId == aimsId)) {\r\n if (!relativeFlightMatcher(orgFlights[o], flights)) {\r\n flights.push(orgFlights[o]);\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n //FlightFactory.setFlightsToStorage(flights);\r\n FlightFactory.storeFlightsWithReportsAndMessages(flights, pilotReports, cabinReports, messages);\r\n // return true\r\n call.resolve(responseData);\r\n },\r\n function (err) {\r\n call.reject(err);\r\n }\r\n );\r\n return call.promise;\r\n },\r\n /**\r\n * Update local reports from synced Fligths \r\n * @memberof SyncAPIService\r\n */\r\n updatePilotReportLocalEditFromSynch: function () {\r\n var pilotReportLocalEdits = PilotReportLocalEditFactory.getPilotReportsFromStorage();\r\n if (pilotReportLocalEdits != undefined && pilotReportLocalEdits != null) {\r\n for (var i = 0; i < pilotReportLocalEdits.length; i++) {\r\n var flight = FlightFactory.getFlightFromStorage(pilotReportLocalEdits[i].FlightId, pilotReportLocalEdits[i].FlightAimsId);\r\n if ((pilotReportLocalEdits[i].Status == \"draft\" || pilotReportLocalEdits[i].Status == \"completed\") && (flight != undefined)) {\r\n\r\n pilotReportLocalEdits[i].Departure = flight.Departure;\r\n pilotReportLocalEdits[i].Arrival = flight.Arrival;\r\n pilotReportLocalEdits[i].AcType = flight.AcType;\r\n pilotReportLocalEdits[i].AcTailNo = flight.AcTailNo;\r\n pilotReportLocalEdits[i].FlightNo = flight.FlightNo;\r\n pilotReportLocalEdits[i].DepartureICAO = flight.DepartureICAO;\r\n pilotReportLocalEdits[i].DepartureCountry = flight.DepartureCountry;\r\n pilotReportLocalEdits[i].DepartureName = flight.DepartureName;\r\n pilotReportLocalEdits[i].ArrivalICAO = flight.ArrivalICAO;\r\n pilotReportLocalEdits[i].ArrivalCountry = flight.ArrivalCountry;\r\n pilotReportLocalEdits[i].ArrivalName = flight.ArrivalName;\r\n pilotReportLocalEdits[i].ScheduledDepartureDateUTC = flight.ScheduledDepartureDateUTC;\r\n pilotReportLocalEdits[i].ScheduledDepartureTimeUTC = flight.ScheduledDepartureTimeUTC;\r\n pilotReportLocalEdits[i].ScheduledDeparture = flight.ScheduledDeparture;\r\n pilotReportLocalEdits[i].BookedC = flight.BookedC;\r\n pilotReportLocalEdits[i].BookedY = flight.BookedY;\r\n pilotReportLocalEdits[i].BookedInf = flight.BookedInf;\r\n pilotReportLocalEdits[i].BookedPad = flight.BookedPad;\r\n pilotReportLocalEdits[i].BookedChld = flight.BookedChld;\r\n pilotReportLocalEdits[i].ActualC = flight.ActualC;\r\n pilotReportLocalEdits[i].ActualY = flight.ActualY;\r\n pilotReportLocalEdits[i].ActualInf = flight.ActualInf;\r\n pilotReportLocalEdits[i].ActualPad = flight.ActualPad;\r\n pilotReportLocalEdits[i].ActualChld = flight.ActualChld;\r\n\r\n pilotReportLocalEdits[i].DepartureGate = flight.DepartureGate;\r\n pilotReportLocalEdits[i].DepartureTimezone = flight.DepartureTimezone;\r\n pilotReportLocalEdits[i].ArrivalTimezone = flight.ArrivalTimezone;\r\n pilotReportLocalEdits[i].CallSign = flight.CallSign;\r\n pilotReportLocalEdits[i].ScheduledArrival = flight.ScheduledArrival;\r\n\r\n\r\n\r\n pilotReportLocalEdits[i].crew = flight.crew;\r\n\r\n }\r\n }\r\n PilotReportLocalEditFactory.setPilotReportsToStorage(pilotReportLocalEdits);\r\n }\r\n }\r\n };\r\n }\r\n\r\n\r\n\r\n})(); ","(function() {\r\n 'use strict';\r\n \r\n \r\na3_pilot_reports.controller('SynchCtrl',SynchCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SynchCtrl\r\n * @description \r\n * Manage Sync View\r\n * @ngInject\r\n */ \r\nfunction SynchCtrl($scope, $uibModalInstance, UserFactory, FlightFactory, PilotReportLocalEditFactory, SyncAPIService, SyncLogFactory, ReportGuidFactory,PilotReportSyncResultFactory,DataCleanerFactory,MessageFactory,MemoFactory,$route) {\r\n\t\t$scope.syncResultsVisible = false;\r\n\t\t$scope.isSynching = false;\r\n\r\n\t\t// get the number of reports to synch\r\n\t\tvar reportstobesynched = PilotReportLocalEditFactory.getPilotReportLocalEditThatNeedToBeSynched();\r\n\t\t\r\n\t\t// display the number of reports to synch\r\n\t\t$scope.number_of_reports_to_sync = reportstobesynched.length;\r\n\t\t\r\n\t\t// get the last sync date\r\n\t\t$scope.isFirstSync = false;\r\n\t\t$scope.isTooOldSync = false;\r\n\t\t$scope.lastSyncDate = '-';\r\n\t\t$scope.syncVersion = '1.1';\r\n\t\t\r\n\t\tvar lastLog = SyncLogFactory.getSyncLog();\r\n\t\tif (lastLog == null) {\r\n\t\t\t$scope.isFirstSync = true;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tif (lastLog.date != null) {\r\n\t\t\t\t$scope.lastSyncDate = new Date(lastLog.date).toUTC().toString('dd-MM-yyyy HH:mm') + ' UTC';\r\n\t\t\t\tif (Date.today().add(-3).days().toUTC().isAfter(new Date(lastLog.date).toUTC()))\r\n\t\t\t\t\t$scope.isTooOldSync = true;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (lastLog.version != null)\r\n\t\t\t\t$scope.syncVersion = lastLog.version;\r\n\t\t}\r\n\r\n\t\t// get the report credits\r\n\t\t$scope.reportCredits = ReportGuidFactory.getRemainingReportGuids();\r\n\t\t\r\n\t\t// setup the grid\r\n\t\t$scope.syncTableData = PilotReportLocalEditFactory.getPilotReportLocalEditThatNeedToBeSynched();\r\n\t\t\r\n\t\t$scope.doSynch = doSynch;\r\n $scope.ok = ok;\r\n $scope.cancel = cancel;\r\n $scope.showSyncResults = showSyncResults;\r\n $scope.syncResultsOk = syncResultsOk;\r\n \r\n /**\r\n * Start Synch functionality\r\n * @memberof SynchCtrl\r\n */\r\n function doSynch() {\r\n\t\t\t//waiting for memoIds before we sync\r\n\t\t\tMemoFactory.getStoredMemosIds(function(memoIdsToSend){\r\n\t\t\t\t\t\t\t\t// get the user\r\n\t\t\t\t\t\t\t\tvar user = UserFactory.getUser();\r\n\r\n\t\t\t\t\t\t\t\t// call the remote service for data\r\n\t\t\t\t\t\t\t\tvar q = SyncAPIService.doSync(user.aimsId,memoIdsToSend);\r\n\t\t\t\t\t\t\t\t$scope.isSynching = true;\r\n\r\n\t\t\t\t\t\t\t\tq.then(function(response){\r\n\t\t\t\t\t\t\t\t\t\t$scope.isSynching = false;\r\n\t\t\t\t\t\t\t\t\t\tif ($scope.number_of_reports_to_sync > 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\t$scope.showSyncResults('synched');\r\n\t\t\t\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\t\t\t\t\t$scope.showSyncResults('synched-no-send');\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t DataCleanerFactory.deleteSynchedLocalPilotReports();\r\n\t\t\t\t\t\t\t\t DataCleanerFactory.deleteOrphanedLocalReports();\r\n\t\t\t\t\t\t\t\t SyncAPIService.updatePilotReportLocalEditFromSynch();\r\n\t\t\t\t\t\t\t\t MemoFactory.markGroundDutiesUnread();\r\n\t\t\t\t\t\t\t\t});\r\n\r\n\t\t\t\t\t\t\t\tq.catch(function(err){\r\n\t\t\t\t\t\t\t\t\t\t$scope.isSynching = false;\r\n\r\n\t\t\t\t\t\t\t\t\t\tif (err.status == -1)\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\t\t$scope.errorName = \"There were problems during the server synchronization. Please try again.\";\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\telse if (err.status != 401)\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\t\t// if an error was encountered display an error message\r\n\t\t\t\t\t\t\t\t\t\t\t\t$scope.errorName = \"Could not reach the remote server. Please connect to the Internet and try again.\";\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\t\t$uibModalInstance.close('');\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t\t\r\n\t\t};\r\n\t\t\r\n /**\r\n * Close modal\r\n * @memberof SynchCtrl\r\n */\r\n function ok() {\r\n\t\t\t$uibModalInstance.close('');\r\n\t\t};\r\n\r\n /**\r\n * show Report Sync Results\r\n * @memberof SynchCtrl\r\n */\r\n\t\tfunction cancel() {\r\n\t\t\t$uibModalInstance.close('cancel');\r\n\r\n\t\t};\r\n \r\n /**\r\n * show Report Sync Results\r\n * @memberof SynchCtrl\r\n */\r\n function showSyncResults(syncResult) {\r\n\r\n\t\t\t$scope.syncResultsVisible = true;\r\n\r\n\t\t\t// setup the grid\r\n\t\t\t$scope.syncResultsTableData = PilotReportSyncResultFactory.getPilotReportSyncResultsFromStorage();\r\n\t\t\t$scope.syncSuccesses = PilotReportSyncResultFactory.getSuccesses($scope.syncResultsTableData);\r\n\t\t\t$scope.syncFailures = PilotReportSyncResultFactory.getFailures($scope.syncResultsTableData);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\tif ($scope.syncResultsTableData != null) {\r\n\t\t\t\t\t$scope.reports_to_sync = $scope.syncResultsTableData.length;\r\n\t\t\t} else {\r\n\t\t\t\t\t$scope.reports_to_sync = 0;\r\n\t\t\t}\r\n\r\n\t\t\tif ($scope.syncSuccesses == 1) {\r\n\t\t\t\t\t$scope.sync_successes_descr = 'Pilot Report was';\r\n\t\t\t} else {\r\n\t\t\t\t\t$scope.sync_successes_descr = 'Pilot Reports were';\r\n\t\t\t}\r\n\r\n\t\t\tif ($scope.syncFailures == 1) {\r\n\t\t\t\t\t$scope.sync_failures_descr = 'Pilot Report was';\r\n\t\t\t} else {\r\n\t\t\t\t\t$scope.sync_failures_descr = 'Pilot Reports were';\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t$scope.unreadMessages=MessageFactory.getCountOfUnreadMessages();\r\n\t\t};\r\n\r\n /**\r\n * show Report Sync Results\r\n * @memberof SynchCtrl\r\n */\r\n\t\tfunction syncResultsOk() {\r\n\t\t\t$uibModalInstance.close('synched');\r\n\t\t\t$route.reload();\r\n\r\n\t\t}\r\n\r\n}\r\n\r\n\t\t\r\n \r\n })(); ","(function() {\r\n 'use strict';\r\n \r\n\r\na3_pilot_reports.factory('SyncLogFactory',SyncLogFactory);\r\n\r\n/* @ngInject */ \r\nfunction SyncLogFactory($log,GenericService){\r\n\t\t\t\t\t\t\t\t\r\n\t// Define the constructor function.\r\n\tfunction SyncLog() {\r\n\t\tthis.userAimsId = null;\r\n\t\tthis.date = null;\r\n\t\tthis.version = null;\r\n\t\tthis.lastShow = null;\r\n this.isUpdated = false;\r\n\t\tthis.lastScheduleDate = null;\r\n\t\tthis.forceSync = false;\r\n\t\t//checks if sync log displayed in the last X minutes, to avoid constantly\r\n\t\t//showing the sync dialog\r\n\t\tthis.canShowSync = canShowSync;\r\n\t}\r\n\t\t\r\n\t\tvar objType = 'syncLog';\r\n\t\tvar objCallback = SyncLog; \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\tvar service = {\r\n\t\t\t\tgetSyncLog : getSyncLog,\r\n\t\t\t\tsetSyncLog : setSyncLog,\r\n\t\t\t\tupdateSyncVersion : updateSyncVersion,\r\n\t\t\t\tsetLastShow : setLastShow,\r\n\t\t\t\tclearSyncLog : clearSyncLog,\r\n getLastScheduleDate : getLastScheduleDate,\r\n\t\t\t\tsetLastScheduleDate : setLastScheduleDate,\r\n\t\t\t\tforceSync : forceSync\r\n\t\t}\r\n\t\t\r\n\t\tfunction canShowSync(){\r\n\t\t\t\tvar can = false;\r\n\t\t\t\tif (this.lastShow == null)\r\n\t\t\t\t\t\tcan = true;\r\n\t\t\t\telse if ((new Date()).add(-10).minutes().toUTC().isAfter(new Date(this.lastShow).toUTC())) {\r\n\t\t\t\t\t\tcan = true;\r\n\t\t\t\t}\r\n\t\t\t\treturn can;\r\n\t\t}\r\n\r\n\tfunction getSyncLog(){\r\n return GenericService.getOne(objType,objCallback);\r\n\t}\r\n\r\n\tfunction setSyncLog(userAimsId,version,lastScheduleDate){\r\n\t\t\t\tvar newLog = new SyncLog();\r\n\t\t\t\tnewLog.userAimsId = userAimsId;\r\n\t\t\t\tnewLog.date = new Date();\r\n\t\t\t\tnewLog.version = version;\r\n\t\t\t\tnewLog.lastShow = new Date();\r\n\t\t\t\tnewLog.isUpdated = false;\r\n\t\t\t\tnewLog.forceSync = false;\r\n newLog.lastScheduleDate = new Date(lastScheduleDate).getTime();\r\n\t\t\t\tGenericService.saveOne(newLog,objType,objCallback);\r\n\t}\r\n\t\t\r\n\t\tfunction updateSyncVersion(version){\r\n\r\n\t\t\t\tvar syncLog = getSyncLog();\r\n\t\t\t\t\r\n\t\t\t\tsyncLog.version=version;\r\n\t\t\t\tsyncLog.isUpdated=true;\r\n\r\n\t\t\t\tGenericService.saveOne(syncLog,objType,objCallback);\r\n\t\t}\r\n \r\n function getLastScheduleDate() {\r\n var syncLog = getSyncLog();\r\n if (syncLog == null){\r\n return null;\r\n }else{ \r\n\t\t\t return syncLog.lastScheduleDate;\r\n }\r\n\t\t}\r\n\r\n\t\tfunction setLastScheduleDate(date) {\r\n var log = getSyncLog();\r\n\t\t\tif (log == null) log = new SyncLog();\r\n\t\t\tlog.lastScheduleDate = date;\r\n\r\n\t\t\tGenericService.saveOne(log,objType,objCallback);\r\n\t\t}\r\n\r\n\t\r\n\tfunction setLastShow(){\r\n\t\tvar log = getSyncLog();\r\n\t\tif (log == null) log = new SyncLog();\r\n\t\tlog.lastShow = new Date();\r\n\t\t\r\n GenericService.saveOne(log,objType,objCallback);\r\n\t}\r\n\t\r\n\tfunction clearSyncLog(){\r\n\t\tGenericService.removeAll(objType,objCallback);\r\n\t}\r\n\t\r\n\t/**\r\n\t * Forces Sync Modal to appear\r\n\t * @memberof SyncLogFactory\r\n\t */\r\n\tfunction forceSync(){\r\n\t\tvar syncLog = getSyncLog();\r\n\t\tif (syncLog == null) syncLog = new SyncLog();\r\n\t\tsyncLog.forceSync = true;\r\n\t\tGenericService.saveOne(syncLog,objType,objCallback);\r\n\t}\r\n\r\n\r\n\t// Return constructor - this is what defines the actual\r\n\t// injectable in the DI framework.\r\n\treturn service;\r\n};\r\n\r\n })(); ","(function() {\r\n 'use strict';\r\n\r\na3_pilot_reports.factory('PhotoFactory', PhotoFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name PhotoFactory\r\n * @description \r\n * Manage Report's Photos.\r\n * @ngInject\r\n */ \r\nfunction PhotoFactory(GenericModalFactory) {\r\n\r\n /**\r\n * Initialiaze Photo object \r\n * @memberof PhotoFactory\r\n */\r\n\t\tfunction Photo() {\r\n\t\t\tthis.Id = null;\r\n\t\t\tthis.Remarks = null;\r\n\t\t\tthis.RemarksShort = null;\r\n\t\t\tthis.PhotoData = null;\r\n\t\t\tthis.FileType = null;\r\n\t\t}\r\n\r\n\t\tvar service = {\r\n\t\t\tcreateNew : createNew,\r\n\t\t\tfromObject : fromObject,\r\n\t\t\tfromObjectList : fromObjectList,\r\n\t\t\tdeleteFromList : deleteFromList\r\n\t\t}\r\n\r\n /**\r\n * Create a new Photo object \r\n * @memberof PhotoFactory\r\n * @returns {object} Photo\r\n */\t\t\r\n\t\tfunction createNew() {\r\n\t\t\treturn GenericModalFactory.createNew(Photo)\r\n\t\t}\r\n\r\n /**\r\n * Extend given Photo object \r\n * @memberof PhotoFactory\r\n * @param {object} obj The Photo object that will be extended\r\n * @returns {object} Photo\r\n */ \r\n\t\tfunction fromObject(obj) {\r\n\t\t\treturn GenericModalFactory.fromObject(obj,Photo)\r\n\t\t}\r\n\r\n /**\r\n * Delete Photo object from given list\r\n * @memberof PhotoFactory\r\n * @param {object} obj The Photo object that will be deleted\r\n * @returns {array} Photos\r\n */\r\n\t\tfunction deleteFromList(obj, objList) {\r\n\t\t\treturn GenericModalFactory.deleteFromList(obj, objList)\r\n\t\t}\r\n\t\t\r\n /**\r\n * Extend given Photo object \r\n * @memberof PhotoFactory\r\n * @param {object} obj The Photo object that will be extended\r\n * @returns {object} Photo\r\n */ \r\n\t\tfunction fromObjectList(objList) {\r\n\t\t\treturn GenericModalFactory.fromObjectList(objList,Photo)\r\n\t\t}\r\n\r\n\t\treturn service;\r\n\t}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('TicketCtrl', TicketCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name TicketCtrl\r\n * @description \r\n * Send a ticket\r\n * @ngInject\r\n */\r\nfunction TicketCtrl($scope,UserFactory, PhotoFactory, TicketAPIService,$location,$uibModal, version) {\r\n \r\n var user = UserFactory.getUser();\r\n user\r\n $scope.submitted = false;\r\n $scope.ticket = {};\r\n $scope.ticket.photos = [];\r\n $scope.maximumAttatchedPhotos = 3;\r\n $scope.showMaxImages = false;\r\n $scope.quality = 0.6;\r\n $scope.width = 1280;\r\n $scope.height = 1024;\r\n $scope.sizeLimitKb = 1000;\r\n $scope.imageTooLargeMsg = false;\r\n $scope.gotoHome = gotoHome;\r\n $scope.state = 'ticket';\r\n\r\n $scope.ticket.Version = version;\r\n \r\n appendPhoto();\r\n\r\n $scope.sendTicket = sendTicket;\r\n $scope.imageUploaded = imageUploaded;\r\n $scope.removePhoto = removePhoto;\r\n \r\n if(user && user.aimsId && UserFactory.isLoggedIn()){\r\n $scope.ticket.aimsId = user.aimsId\r\n $scope.isLogged = true;\r\n }\r\n \r\n /**\r\n * Redirects to home view\r\n * @memberof TicketCtrl\r\n */\r\n function gotoHome(){\r\n $location.path(\"/\");\r\n }\r\n \r\n /**\r\n * Send application ticket information\r\n * @memberof TicketCtrl\r\n */\r\n function sendTicket(){\r\n $scope.submitted = true;\r\n if (validateTicket()){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Dialogs/dlgTicketSend.html',\r\n controller: 'TicketModalCtrl',\r\n size: 'md',\r\n backdrop: 'static',\r\n keyboard: false,\r\n resolve: {\r\n ticket: function() {\r\n return $scope.ticket;\r\n },\r\n }\r\n })\r\n\r\n modalInstance.result.then(function() {\r\n $location.path(\"/\"); \r\n });\r\n }\r\n \r\n }\r\n \r\n \r\n /**\r\n * Validate ticket before sending\r\n * @memberof TicketCtrl\r\n * @return {boolean} isValid\r\n */\r\n function validateTicket(){\r\n var isValid = false;\r\n \r\n if ($scope.ticket.aimsId && $scope.ticket.title && $scope.ticket.description){\r\n isValid = true;\r\n }\r\n \r\n return isValid;\r\n }\r\n \r\n /**\r\n * is Image Too Large \r\n * @memberof TicketCtrl\r\n * @return {boolean} isValid\r\n */\r\n function isImageTooLarge(image) {\r\n var isLarge= false;\r\n if (image && image.dataURL != null) {\r\n isLarge = (image.dataURL.length > $scope.sizeLimitKb * 1024);\r\n }\r\n return isLarge;\r\n }\r\n\r\n /**\r\n * Upload Image\r\n * @memberof TicketCtrl\r\n */\r\n function imageUploaded(data,img) {\r\n //console.log('told of a new image', imageResult, this.imageBrowsed, $scope.imageBrowsed);\r\n var imageResult = data; //$scope.imageBrowsed;\r\n if (imageResult != null) {\r\n if(isImageTooLarge(data)){\r\n $scope.imageTooLargeMsg = true;\r\n }else{\r\n $scope.imageTooLargeMsg = false;\r\n img.PhotoData = imageResult.dataURL;\r\n img.FileType = imageResult.fileType || imageResult.file.type;\r\n img.Remarks = imageResult.fileName;\r\n appendPhoto();\r\n }\r\n\r\n }\r\n }\r\n \r\n /**\r\n * Allows to add more photos up to the maximum number allowed\r\n * @memberof TicketCtrl\r\n */\r\n function appendPhoto(){\r\n if($scope.ticket.photos.length< $scope.maximumAttatchedPhotos){\r\n var photo = PhotoFactory.createNew();\r\n $scope.ticket.photos.push(photo);\r\n }else{\r\n $scope.showMaxImages = true;\r\n }\r\n }\r\n \r\n /**\r\n * Remove Selected photo\r\n * @memberof TicketCtrl\r\n * @param {object} photo\r\n */\r\n function removePhoto(photo){\r\n PhotoFactory.deleteFromList(photo, $scope.ticket.photos);\r\n if($scope.showMaxImages){\r\n appendPhoto();\r\n }\r\n $scope.showMaxImages = false;\r\n\r\n }\r\n \r\n \r\n\r\n}\r\n\r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.service(\"TicketAPIService\", TicketAPIService);\r\n \r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc service\r\n * @name TicketAPIService\r\n * @description \r\n * Manages the api calls for the Ticket report system\r\n * @ngInject\r\n */\r\nfunction TicketAPIService($http, $q, apiUrl, localStorageMD5Service, LogService) {\r\n /**\r\n * Send Ticket\r\n * @memberof TicketAPIService\r\n * @return {object} promise\r\n */\r\n function sendTicket(ticket) {\r\n var call = $q.defer();\r\n \r\n ticket.DeviceData = getStoredValues();\r\n $http.post(apiUrl +'/ticket', ticket, {'Content-Type': 'application/json'})\r\n .then(\r\n function(responseData) {\r\n\r\n if(responseData==undefined || responseData.data==undefined || responseData.data.data==undefined) {\r\n var err=new Error();\r\n err.status=-1;\r\n var msg= \"ResponseData error while sending a ticket :\" + JSON.stringify(responseData);\r\n LogService.debug(msg,err)\r\n call.reject(err);\r\n }else{\r\n // return true\r\n call.resolve(responseData);\r\n }\r\n\r\n },\r\n function(err) {\r\n call.reject(err);\r\n }\r\n );\r\n return call.promise;\r\n }\r\n \r\n \r\n /**\r\n * Get all values from localstorage\r\n * @memberof TicketAPIService\r\n */\r\n function getStoredValues() {\r\n var values = [];\r\n var keys = localStorageMD5Service.keys();\r\n if (keys) {\r\n var key, value, sizeActual, error;\r\n for (var i = 0; i < keys.length; i++) {\r\n key = keys[i];\r\n try {\r\n value = localStorageMD5Service.get(key);\r\n value = angular.toJson(value);\r\n sizeActual = localStorageMD5Service.usedSize(key);\r\n error = null;\r\n } catch (e) {\r\n error = e.message || e.errorMessage;\r\n }\r\n values.push({\r\n key: key,\r\n value: value,\r\n error: error,\r\n size: (value) ? value.length : 0,\r\n sizeActual: sizeActual\r\n });\r\n }\r\n }\r\n return values;\r\n\r\n }\r\n\r\n return {\r\n sendTicket: sendTicket\r\n }; \r\n}\r\n \r\n})();","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('TicketModalCtrl', TicketModalCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name TicketCtrl\r\n * @description \r\n * Report a bug of the application\r\n * @ngInject\r\n */\r\nfunction TicketModalCtrl($scope, $uibModalInstance, $timeout, TicketAPIService, LogService, PhotoFactory, ticket) {\r\n $scope.successful = false;\r\n $scope.error = false;\r\n\r\n\t\tvar q = TicketAPIService.sendTicket(ticket);\r\n\r\n q.then(function(responseData){\r\n\t\t\tif(responseData.data.data){\r\n $scope.successful = true;\r\n\t\t\t}\r\n\t\t\telse {\r\n $scope.error = true;\r\n\t\t\t}\r\n $timeout(function() {\r\n\t\t\t\t\t$uibModalInstance.close();\r\n }, 3000);\r\n\t\t},\r\n\t\tfunction(){\r\n $scope.error = true;\r\n $timeout(function() {\r\n\t\t\t\t\t$uibModalInstance.close();\r\n }, 3000);\r\n\t\t});\r\n}\r\n \r\n \r\n})();\r\n ","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('competencesReadOnly', competencesReadOnly);\r\n /**\r\n * @memberof PilotnReports\r\n * @ngdoc directive\r\n * @name competencesReadOnly\r\n * @restrict E\r\n * @description\r\n * Implementation of competences read only\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function competencesReadOnly() {\r\n function link(scope, element, attrs) {\r\n if(scope.trainee.Competences){\r\n scope.trainee.Competences.forEach(function (competence) {\r\n competence.hasSelectedSubCompetence = competence.SubCompetences.some(x => x.Selected);\r\n }); \r\n }\r\n \r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/TrainingReadOnly/competences-read-only.tpl.html',\r\n scope: {trainee : \"=\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n\r\n a3_pilot_reports.directive('courseReadOnly', courseReadOnly);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name courseReadOnly\r\n * @restrict E\r\n * @description\r\n * Initialize read only view of what was submitted\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function courseReadOnly() {\r\n function link(scope) {\r\n scope.leftScroll = leftScroll;\r\n scope.rightScroll = rightScroll;\r\n scope.selectedTraineeSession = selectedTraineeSession;\r\n scope.selected = false;\r\n scope.selectedAbsentTraineeSession = selectedAbsentTraineeSession;\r\n\r\n scope.selectedPhase = scope.phases.find(x => x.PhaseId == scope.session.PhaseId);\r\n\r\n scope.selectedTraineeBadge = {\r\n crewId: scope.session.TraineesSessions[0].CrewId\r\n }; \r\n\r\n function leftScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\r\n }\r\n \r\n function rightScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\r\n } \r\n\r\n \r\n function selectedTraineeSession() { \r\n return function( traineeSession ) {\r\n var showSession = false;\r\n if (traineeSession.CrewId === scope.selectedTraineeBadge.crewId){\r\n showSession = true;\r\n }\r\n return showSession;\r\n };\r\n }\r\n\r\n function selectedAbsentTraineeSession() { \r\n return function( traineeSession ) {\r\n var showPanel = false;\r\n if (traineeSession.CrewId === scope.selectedTraineeBadge.crewId && traineeSession.Items.length == 0){\r\n showPanel = true;\r\n }\r\n return showPanel;\r\n };\r\n }\r\n \r\n }\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/TrainingReadOnly/course-read-only.tpl.html\",\r\n scope : { phases:\"=\", session:\"=\"},\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('gradingReadOnly', gradingReadOnly);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name gradingReadOnly\r\n * @restrict E\r\n * @description\r\n * Implementation of grading read only\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function gradingReadOnly() {\r\n function link(scope, element, attrs) {\r\n if(scope.settings){\r\n scope.grading.GradeType = scope.settings.GradeType;\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/TrainingReadOnly/grading-read-only.tpl.html',\r\n scope: {grading : \"=\", settings : \"=\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n \r\n a3_pilot_reports.directive('pilotFunctionReadOnly', pilotFunctionReadOnly);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name pilotFunctionReadOnly\r\n * @restrict E\r\n * @description\r\n * Implementation of sector history\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function pilotFunctionReadOnly(FlightFactory, UserFactory, $timeout, $routeParams) {\r\n function link(scope, element, attrs) {\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/TrainingReadOnly/pilot-function-read-only.tpl.html',\r\n scope: {session:\"=\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('sectorHistory', sectorHistory);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name sectorHistory\r\n * @restrict E\r\n * @description\r\n * Implementation of sector history\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function sectorHistory() {\r\n function link(scope, element, attrs) {\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/TrainingReadOnly/sector-history.tpl.html',\r\n scope: {history : \"=\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n\r\n a3_pilot_reports.directive('syllabusProgressReadOnly', syllabusProgressReadOnly);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name syllabusReadOnly\r\n * @restrict E\r\n * @description\r\n * Initialize read only view of submitted syllabus\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function syllabusProgressReadOnly() {\r\n function link(scope) {\r\n scope.showRemarks = {\r\n value: false\r\n };\r\n scope.oneAtATime = true;\r\n scope.filterItems = filterItems;\r\n scope.toggleItems = toggleItems;\r\n\r\n setSyllabus(scope.history);\r\n\r\n function setSyllabus(history) {\r\n var traineeSessionItems = [];\r\n scope.phase.Syllabus.SyllabusItems.forEach(function (item) {\r\n \r\n var syllabusItem = JSON.parse(JSON.stringify(item));\r\n syllabusItem.Tries = [];\r\n syllabusItem.Selected = false;\r\n\r\n var relatedSessionItem = history.SyllabusProgress.find(x => x.SyllabusItemId == syllabusItem.Id);\r\n \r\n if(relatedSessionItem){\r\n syllabusItem.hasRemarks = relatedSessionItem.Tries.some(x => x.Comments && x.Comments.length>0) ||\r\n relatedSessionItem.Tries.some(t=> t.TryGrading.Competences.some(x => x.Comments && x.Comments.length>0));\r\n syllabusItem.Selected = true;\r\n syllabusItem.Tries = relatedSessionItem.Tries;\r\n syllabusItem.Tries.forEach(function(attempt){\r\n attempt.Selected = true;\r\n });\r\n }\r\n\r\n setPanelStyle(syllabusItem); \r\n traineeSessionItems.push(syllabusItem);\r\n });\r\n\r\n history.ItemsGrouped = SyllabusGrouping(traineeSessionItems);\r\n }\r\n\r\n \r\n function setPanelStyle(item){\r\n var historyTriesCount = item.Tries.filter(x => x.isReadOnly).length;\r\n var newTriesCount = item.Tries.filter(x => !x.isReadOnly && x.Selected).length;\r\n item.TriesPerformedCount = historyTriesCount + newTriesCount;\r\n\r\n var completedItem = item.TriesPerformedCount >= item.MandatoryCount;\r\n\r\n if(item.MandatoryCount == 0){ //non-mandatory items are considered completed if performed at least once\r\n completedItem = item.TriesPerformedCount>=1;\r\n }\r\n\r\n if(completedItem){\r\n item.PanelClass = 'panel-green panel-border-left-green ';\r\n }\r\n else{\r\n item.PanelClass = 'panel-border-left-blue ';\r\n }\r\n }\r\n\r\n function SyllabusGrouping(items) {\r\n //Syllabus Items Group By 'GroupId'\r\n var syllabusGroups = [];\r\n items.forEach(function (item) {\r\n if (!syllabusGroups.some(x => x.Id == item.SelectedGroup.Id)) {\r\n if (!item.SelectedGroup) {\r\n item.SelectedGroup = {\r\n Id: 0,\r\n Title: 'General'\r\n };\r\n }\r\n\r\n var syllabusGroup = {\r\n Id: item.SelectedGroup.Id,\r\n Title: item.SelectedGroup.Title ? item.SelectedGroup.Title : 'General',\r\n Items: []\r\n };\r\n\r\n syllabusGroup.Items.push(item);\r\n syllabusGroups.push(syllabusGroup);\r\n }\r\n else {\r\n syllabusGroups.filter(x => x.Id == item.SelectedGroup.Id)[0].Items.push(item);\r\n }\r\n });\r\n\r\n return syllabusGroups;\r\n }\r\n\r\n function filterItems(){\r\n return function( item ) {\r\n var showItem = true;\r\n if(scope.showRemarks.value){\r\n showItem = item.hasRemarks;\r\n \r\n }\r\n else{\r\n scope.oneAtATime = true;\r\n }\r\n return showItem;\r\n };\r\n }\r\n\r\n function toggleItems(){\r\n scope.oneAtATime = !scope.showRemarks.value;\r\n \r\n scope.history.ItemsGrouped.forEach(function(syllabusGroup){\r\n syllabusGroup.Items.forEach(function(item){\r\n item.isOpen = scope.showRemarks.value;\r\n });\r\n });\r\n }\r\n }\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'views/TrainingReadOnly/syllabus-progress-read-only.tpl.html',\r\n scope : { phase:\"=\", history:\"=\"},\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function () {\r\n\r\n a3_pilot_reports.directive('syllabusReadOnly', syllabusReadOnly);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name syllabusReadOnly\r\n * @restrict E\r\n * @description\r\n * Initialize read only view of submitted syllabus\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function syllabusReadOnly() {\r\n function link(scope) {\r\n setSyllabus(scope.traineeSession);\r\n\r\n\r\n function setSyllabus(traineeSession) {\r\n\r\n var traineeSessionItems = [];\r\n scope.phase.Syllabus.SyllabusItems.forEach(function (item) {\r\n var syllabusItem = JSON.parse(JSON.stringify(item));\r\n syllabusItem.Tries = [];\r\n syllabusItem.Selected = false;\r\n\r\n var relatedSessionItem = null;\r\n if(scope.type == \"signature\"){\r\n relatedSessionItem = traineeSession.Items.find(x => x.Id == syllabusItem.Id);\r\n }\r\n else{\r\n relatedSessionItem = traineeSession.Items.find(x => x.SyllabusItemId == syllabusItem.Id);\r\n }\r\n\r\n if(relatedSessionItem){\r\n syllabusItem.Selected = true;\r\n syllabusItem.Tries = relatedSessionItem.Tries;\r\n }\r\n\r\n if(scope.type == \"signature\"){\r\n setPanelStyleByProgress(syllabusItem); \r\n }\r\n else{\r\n setPanelStyleBySelected(syllabusItem); \r\n }\r\n\r\n \r\n traineeSessionItems.push(syllabusItem);\r\n });\r\n\r\n traineeSession.ItemsGrouped = SyllabusGrouping(traineeSessionItems);\r\n\r\n traineeSession.ItemsGrouped.forEach(function(group){\r\n group.Items.forEach(function(item){\r\n //find first not ReadOnly try\r\n item.firstTry = item.Tries.find(x => !x.isReadOnly);\r\n });\r\n });\r\n }\r\n\r\n \r\n function setPanelStyleByProgress(item){\r\n var historyTriesCount = item.Tries.filter(x => x.isReadOnly).length;\r\n var newTriesCount = item.Tries.filter(x => !x.isReadOnly && x.Selected).length;\r\n item.TriesPerformedCount = historyTriesCount + newTriesCount;\r\n\r\n var completedItem = item.TriesPerformedCount >= item.MandatoryCount;\r\n\r\n if(item.MandatoryCount == 0){ //non-mandatory items are considered completed if performed at least once\r\n completedItem = item.TriesPerformedCount>=1;\r\n }\r\n\r\n if(completedItem){\r\n item.PanelClass = 'panel-green panel-border-left-green ';\r\n }\r\n else{\r\n item.PanelClass = 'panel-border-left-blue ';\r\n }\r\n }\r\n\r\n function setPanelStyleBySelected(item){\r\n var newTriesCount = item.Tries.filter(x => x.Selected).length;\r\n var selectedItem = newTriesCount>0;\r\n\r\n if(selectedItem){\r\n item.PanelClass = 'panel-green panel-border-left-green ';\r\n }\r\n else{\r\n item.PanelClass = 'panel-border-left-blue ';\r\n }\r\n }\r\n\r\n function SyllabusGrouping(items) {\r\n //Syllabus Items Group By 'GroupId'\r\n var syllabusGroups = [];\r\n items.forEach(function (item) {\r\n if (!syllabusGroups.some(x => x.Id == item.SelectedGroup.Id)) {\r\n if (!item.SelectedGroup) {\r\n item.SelectedGroup = {\r\n Id: 0,\r\n Title: 'General'\r\n };\r\n }\r\n\r\n var syllabusGroup = {\r\n Id: item.SelectedGroup.Id,\r\n Title: item.SelectedGroup.Title ? item.SelectedGroup.Title : 'General',\r\n Items: []\r\n };\r\n\r\n syllabusGroup.Items.push(item);\r\n syllabusGroups.push(syllabusGroup);\r\n }\r\n else {\r\n syllabusGroups.filter(x => x.Id == item.SelectedGroup.Id)[0].Items.push(item);\r\n }\r\n });\r\n\r\n return syllabusGroups;\r\n }\r\n\r\n }\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'views/TrainingReadOnly/syllabus-read-only.tpl.html',\r\n scope : { phase:\"=\", traineeSession:\"=\", type:\"=\"},\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('certificateExam', certificateExam);\r\n /**\r\n * @ngdoc directive\r\n * @name certificateExam\r\n * @restrict E\r\n * @description\r\n * Implementation of certificate exam grading\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function certificateExam(TrainingSessionFactory, FlightSessionFactory) {\r\n function link(scope, element, attrs) {\r\n if (scope.trainees) collapseAll();\r\n\r\n scope.validateTrainee = validateTrainee;\r\n scope.getRemainingCharacters = getRemainingCharacters;\r\n scope.collapseAll = collapseAll;\r\n scope.gradeUp = gradeUp;\r\n scope.gradeDown = gradeDown;\r\n\r\n var courseId = scope.dutyCourse.Id;\r\n\r\n var isGround = false;\r\n if(scope.groundDuty){\r\n isGround = true;\r\n var date = scope.groundDuty.DutyDateS;\r\n var dutyId = scope.groundDuty.Id;\r\n }\r\n else{\r\n var date = scope.crewRouteDuty.date;\r\n var dutyNo = scope.crewRouteDuty.DutyNo;\r\n var dutyDay = scope.crewRouteDuty.DutyDay;\r\n } \r\n\r\n var gradeBase = scope.selectedPhase.ReleaseGrading.CertificateGradeBase;\r\n\r\n scope.gradeBase = gradeBase;\r\n scope.gradeMin = 0;\r\n scope.gradeMax = 100;\r\n\r\n //Accordion setting\r\n scope.oneAtATime = true;\r\n scope.gradingStatus = 'All';\r\n\r\n\r\n //Initialize trainees \r\n scope.sessions = [];\r\n scope.trainees.filter(x => x.EligibilityStatus && !x.Session.Absent).forEach(function (trainee) {\r\n var session = trainee.Session.ReleaseGrading;\r\n session.Name = trainee.Name;\r\n session.AimsId = trainee.AimsId;\r\n session.isOpen = false;\r\n\r\n if(!session.CertificateOutcome) session.CertificateOutcome = \"Pass\";\r\n if(gradeBase && !session.Grade) session.Grade = gradeBase;\r\n if(!gradeBase) session.Grade = null;\r\n\r\n scope.sessions.push(session);\r\n });\r\n\r\n scope.sessions.forEach(function(traineeSession){\r\n validateGrading(traineeSession);\r\n });\r\n\r\n function validateGrading(trainee){\r\n // Invalid grading\r\n // 1. If none\r\n // 2. Over gradeMax\r\n // 3. Below gradeMin\r\n // 4. Non numeric\r\n trainee.isCertificateValid = gradeBase ? trainee.Grade != null && trainee.Grade != undefined : true;\r\n }\r\n\r\n function validateTrainee(trainee){\r\n if(gradeBase){\r\n validateGrading(trainee);\r\n if(trainee.isCertificateValid){\r\n calculateOutcome(trainee);\r\n }\r\n }\r\n \r\n if(isGround){\r\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) { console.log(e) })\r\n }\r\n else{\r\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) { console.log(e) })\r\n }\r\n }\r\n\r\n function gradeUp(trainee){\r\n if(trainee.isCertificateValid && trainee.Grade < scope.gradeMax){\r\n trainee.Grade++;\r\n }\r\n if(!trainee.isCertificateValid){\r\n trainee.Grade++;\r\n }\r\n validateTrainee(trainee);\r\n }\r\n\r\n function gradeDown(trainee){\r\n if(trainee.isExamValid && trainee.Grade > scope.gradeMin){\r\n trainee.Grade--;\r\n }\r\n if(!trainee.isExamValid){\r\n trainee.Grade--;\r\n }\r\n validateTrainee(trainee);\r\n }\r\n\r\n function calculateOutcome(trainee){\r\n if(trainee.Grade < gradeBase){\r\n trainee.CertificateOutcome = \"Fail\";\r\n }\r\n else{\r\n trainee.CertificateOutcome = \"Pass\";\r\n }\r\n }\r\n \r\n\r\n function getRemainingCharacters(text, max) {\r\n if (typeof (text) === \"undefined\" || text === null) return '';\r\n if (typeof (max) === \"undefined\" || max === null || max < 0 || !max) max = 4000;\r\n var length = text.length;\r\n\r\n return 'characters left: ' + (max - length);\r\n }\r\n\r\n function collapseAll() {\r\n scope.isAllOpen = !scope.isAllOpen;\r\n scope.trainees.forEach(function (trainee) {\r\n var session = trainee.Session.ReleaseGrading;\r\n session.isOpen = scope.isAllOpen;\r\n });\r\n }\r\n\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/certificate-exam.tpl.html',\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('CompetenceModalCtrl', CompetenceModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name CompetenceModalCtrl\r\n * @description \r\n * Show competence grading helper\r\n * @ngInject\r\n */\r\n\r\n function CompetenceModalCtrl($scope, $uibModalInstance, competence){\r\n $scope.close = close;\r\n $scope.competence = competence;\r\n\r\n /**\r\n * Close the modal\r\n * @memberof CompetenceModalCtrl\r\n */\r\n function close(){\r\n $uibModalInstance.close($scope.competence.Grading);\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('courseFooter', courseFooter);\r\n\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name courseFooter\r\n * @restrict E\r\n * @description\r\n * Implementation of courseFooter (appears in course view)\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\r\n function courseFooter($location, $routeParams) {\r\n function link(scope) {\r\n scope.gotoCalendar = gotoCalendar;\r\n scope.gotoGroundDuty = gotoGroundDuty;\r\n scope.gotoCrewRoute = gotoCrewRoute;\r\n scope.gotoFlight = gotoFlight;\r\n\r\n function gotoCalendar() {\r\n $location.path(\"/\");\r\n }\r\n\r\n function gotoGroundDuty() {\r\n $location.path('/groundDuty/' + Number($routeParams.dutyId));\r\n }\r\n\r\n function gotoCrewRoute() {\r\n var dutyNo = scope.crewRouteDuty.DutyNo;\r\n var dutyDay = scope.crewRouteDuty.DutyDay;\r\n $location.path('/crewRoute/' + dutyNo + '/' + dutyDay);\r\n }\r\n\r\n function gotoFlight(){\r\n var flightId = Number($routeParams.flightId)\r\n $location.path('/flightinfo/' + flightId);\r\n }\r\n\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: true,\r\n templateUrl: \"views/Training/course-footer.tpl.html\",\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('course', course);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name course\r\n * @restrict E\r\n * @description\r\n * Implementation of training course\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function course(GroundDutyFactory, CourseFactory, TrainingSessionFactory, FlightSessionFactory, $timeout, $uibModal, $location, $routeParams, $window) {\r\n function link(scope, element, attrs) {\r\n var courseId = scope.dutyCourse.Id;\r\n\r\n var isGround = false;\r\n if(scope.groundDuty){\r\n isGround = true;\r\n var date = scope.groundDuty.DutyDateS;\r\n var dutyId = scope.groundDuty.Id;\r\n }\r\n else{\r\n var date = scope.crewRouteDuty.date;\r\n var dutyNo = scope.crewRouteDuty.DutyNo;\r\n var dutyDay = scope.crewRouteDuty.DutyDay;\r\n\r\n var trainingFlightIds = scope.crewRouteDuty.Courses.find(x => x.CourseId == courseId && new moment(x.Date).isSame(date)).TrainingFlightIds;\r\n \r\n if(scope.course.Media) scope.course.Media.radioModel = \"Flight\";\r\n }\r\n\r\n scope.isGround = isGround;\r\n \r\n scope.updateSession = updateSession;\r\n scope.availableCourseInfo = false;\r\n scope.oneTraineeAtATime = true;\r\n scope.allAbsent = false;\r\n scope.SubmitSession = SubmitSession;\r\n scope.close = close;\r\n scope.updateTraineeSignatures = updateTraineeSignatures;\r\n scope.checkReleaseAvailability = checkReleaseAvailability;\r\n scope.setReleaseStatus = setReleaseStatus;\r\n scope.reloadReleasePanel = reloadReleasePanel;\r\n scope.showReleasePanel = showReleasePanel;\r\n\r\n scope.filterSelectedSyllabus = filterSelectedSyllabus;\r\n scope.filterPresentTrainees = filterPresentTrainees;\r\n\r\n scope.selectedPhaseIndex = selectedPhaseIndex();\r\n\r\n scope.releaseTrainee = releaseTrainee;\r\n scope.showReleaseBtn = showReleaseBtn;\r\n scope.showGroupReleaseBtn = showGroupReleaseBtn;\r\n scope.releaseGroup = releaseGroup;\r\n scope.validateTraineeForm = validateTraineeForm;\r\n scope.openTraineeSignature = openTraineeSignature;\r\n scope.resetSignature = resetSignature;\r\n\r\n scope.getTraineeClass = getTraineeClass;\r\n scope.leftScroll = leftScroll;\r\n scope.rightScroll = rightScroll;\r\n scope.togglePanel = togglePanel; \r\n \r\n scope.isReleaseSelected = false;\r\n scope.toggleBtn = toggleBtn;\r\n \r\n function toggleBtn(){\r\n scope.isReleaseSelected = !scope.isReleaseSelected; \r\n }\r\n\r\n function selectedPhaseIndex(){ \r\n var index = 0;\r\n scope.course.CrewCoursePhases.some(function(phase, i) {\r\n if (phase.PhaseId == scope.selectedPhase.PhaseId) {\r\n index = i;\r\n return true;\r\n }\r\n });\r\n return index;\r\n }\r\n\r\n function filterSelectedSyllabus(){\r\n return function( syllabus ) {\r\n var showTrainee = true;\r\n if(scope.traineeSyllabi && scope.traineeSyllabi.length > 1){\r\n showTrainee = syllabus.TraineeIds[0] == scope.selectedTrainee.CrewId;\r\n }\r\n return showTrainee;\r\n };\r\n }\r\n\r\n function filterPresentTrainees(){\r\n return function( trainee ) {\r\n return !trainee.Session.Absent;\r\n };\r\n }\r\n\r\n scope.reloadFooter = true;\r\n scope.reloadRelease = true;\r\n \r\n setTraineeSessions();\r\n updateSession();\r\n setReleaseStatus();\r\n\r\n function ResetTraineeSignatures(){\r\n scope.trainees.forEach(function(trainee){\r\n trainee.Session.Authorized = false;\r\n });\r\n } \r\n\r\n function setReleaseStatus(){\r\n scope.trainees.forEach(function(trainee){trainee.ShowReleaseWarning = false;});\r\n scope.course.AvailableRelease = checkReleaseAvailability();\r\n \r\n //Handle trainee signatures\r\n scope.requiresTraineeSignature = RequiresTraineeSignature();\r\n if(!scope.requiresTraineeSignature) ResetTraineeSignatures();\r\n scope.allSignaturesComplete = !scope.trainees.filter(x => !x.Session.Absent).some(x => !x.Session.Authorized);\r\n scope.someSignaturesComplete = scope.trainees.filter(x => !x.Session.Absent).some(x => x.Session.Authorized);\r\n \r\n\r\n //For flights : check minDays - minSectors\r\n if(!isGround && scope.course.AvailableRelease && (scope.selectedPhase.MinDays > 0 || scope.selectedPhase.MinSectors > 0)){\r\n scope.trainees.filter(x => x.AvailableRelease).forEach(function(trainee){\r\n var phaseInfo = trainee.Phases.find(x => x.PhaseId == scope.selectedPhase.PhaseId);\r\n var completedDays = 0;\r\n var completedSectors = 0;\r\n if(phaseInfo.Sessions){ //previous sessions\r\n completedDays = phaseInfo.Sessions.length;\r\n\r\n phaseInfo.Sessions.forEach(function(pastSession){\r\n if(pastSession.Sectors){\r\n completedSectors = completedSectors + pastSession.Sectors.length;\r\n }\r\n })\r\n }\r\n \r\n trainee.CompletedDays = completedDays + 1 ; //add current day\r\n trainee.CompletedSectors = completedSectors + trainingFlightIds.length; //add current sectors\r\n if(trainee.CompletedDays < scope.selectedPhase.MinDays || trainee.CompletedSectors < scope.selectedPhase.MinSectors){\r\n trainee.ShowReleaseWarning = true;\r\n }\r\n });\r\n }\r\n\r\n //For ground: check aircraft visits\r\n if(isGround && (scope.course.AvailableRelease || scope.selectedPhase.ModuleType==\"Check\") && scope.selectedPhase.AircraftTypes.length){\r\n var trainees = scope.trainees;\r\n if(scope.selectedPhase.ModuleType!=\"Check\") trainees.filter(x => x.AvailableRelease);\r\n trainees.forEach(function(trainee){\r\n var phaseInfo = trainee.Phases.find(x => x.PhaseId == scope.selectedPhase.PhaseId);\r\n var visitedAircrafts = [];\r\n \r\n if(phaseInfo.Sessions){ //previous sessions\r\n phaseInfo.Sessions.forEach(function(session){\r\n visitedAircrafts = visitedAircrafts.concat(session.AircraftTypesVisited)\r\n });\r\n }\r\n \r\n if(scope.course.Media){\r\n trainee.visitedAircrafts = visitedAircrafts.concat(scope.course.Media.inputAircrafts); //add current arvis\r\n }\r\n trainee.pendingAircrafts = [];\r\n trainee.pairPendingAircrafts = []; \r\n\r\n var pendingAircrafts = [];\r\n scope.selectedPhase.AircraftTypes.forEach(function(type){\r\n var array = type.split(',');\r\n\r\n //if arvi requirement is not met\r\n if (trainee.visitedAircrafts && !array.some(x => trainee.visitedAircrafts.includes(x))) {\r\n var pendingArviList = [];\r\n if (array.length > 1) \r\n {\r\n array.forEach(function(arvi){\r\n pendingArviList.push(arvi);\r\n });\r\n }\r\n else\r\n {\r\n pendingArviList.push(array[0]);\r\n }\r\n pendingAircrafts.push(pendingArviList);\r\n }\r\n });\r\n\r\n trainee.pendingAircrafts = pendingAircrafts;\r\n trainee.ShowReleaseWarning = trainee.pendingAircrafts.length>0;\r\n });\r\n }\r\n scope.showReleaseWarning = scope.trainees.some(x => x.ShowReleaseWarning);\r\n }\r\n\r\n function reloadReleasePanel(){\r\n setReleaseStatus();\r\n scope.reloadRelease = false;\r\n $timeout(function () {\r\n scope.reloadRelease = true;\r\n }, 100);\r\n\r\n }\r\n\r\n function updateSession() {\r\n scope.trainees.forEach(function(trainee) {trainee.Session.selected = false;});\r\n\r\n if(scope.selectedTraineeBadge && scope.trainees.find(x => x.CrewId == scope.selectedTraineeBadge.CrewId)){\r\n scope.trainees.find(x => x.CrewId == scope.selectedTraineeBadge.CrewId).Session.selected = true;\r\n scope.selectedTrainee = scope.trainees.find(x => x.Session.selected);\r\n }\r\n\r\n if(isGround){\r\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) { console.log(e) })\r\n }\r\n else{\r\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) { console.log(e) })\r\n }\r\n }\r\n\r\n function setTraineeSessions() {\r\n var phase = scope.selectedPhase;\r\n // Set Day Grading\r\n var dayCompetences = phase.DayGrading.Competences;\r\n dayCompetences.forEach(function (competence) { \r\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences); \r\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences); \r\n\r\n //Filter out from optional the ones common with mandatory\r\n competence.OptionalSub = competence.OptionalSub.filter(c => !competence.MandatorySub.includes(c));\r\n\r\n });\r\n var dayGradingSessions = scope.trainees.map(x => x.Session.DayGrading);\r\n dayGradingSessions.forEach(function (traineeSession) {\r\n traineeSession.Competences = setTraineeCompetences(dayCompetences, traineeSession);\r\n });\r\n\r\n // Set Release Grading\r\n var releaseCompetences = phase.ReleaseGrading.Competences;\r\n releaseCompetences.forEach(function (competence) { \r\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences); \r\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences);\r\n\r\n //Filter out from optional the ones common with mandatory\r\n competence.OptionalSub = competence.OptionalSub.filter(c => !competence.MandatorySub.includes(c));\r\n });\r\n \r\n var releaseGradingSessions = scope.trainees.map(x => x.Session.ReleaseGrading);\r\n releaseGradingSessions.forEach(function (traineeSession) {\r\n traineeSession.Competences = setTraineeCompetences(releaseCompetences, traineeSession);\r\n });\r\n\r\n // Set Syllabus\r\n if (scope.selectedPhase.Syllabus) setSyllabus();\r\n\r\n //Check if all are absent\r\n if(scope.trainees && scope.trainees.length && !scope.trainees.some(x => !x.Session.Absent)){\r\n scope.allAbsent = true;\r\n }\r\n }\r\n\r\n function setSyllabus() {\r\n var traineeSyllabi = [];\r\n \r\n if (!scope.selectedPhase.Syllabus.IsGradable && !scope.selectedPhase.InFlight) { //Non Gradable syllabus & Ground: All trainees share the same syllabus\r\n var traineeSyllabus = {\r\n TraineeIds: scope.trainees.filter(x => !x.Session.Absent).map(x => x.CrewId),\r\n Items: []\r\n };\r\n traineeSyllabi.push(traineeSyllabus);\r\n }\r\n else { //Gradable syllabus || flight: each trainee will have its own\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function (trainee) {\r\n var traineeSyllabus = {\r\n TraineeIds: [trainee.CrewId],\r\n Items: []\r\n };\r\n traineeSyllabi.push(traineeSyllabus);\r\n });\r\n }\r\n\r\n //Set syllabus item sub competences \r\n scope.selectedPhase.Syllabus.SyllabusItems.forEach(function (item) {\r\n item.Competences.forEach(function (competence) { \r\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences); \r\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences);\r\n\r\n //Filter out from optional the ones common with mandatory\r\n competence.OptionalSub = competence.OptionalSub.filter(c => !competence.MandatorySub.includes(c));\r\n });\r\n });\r\n\r\n\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function (trainee) {\r\n var traineeSessionItems = [];\r\n scope.selectedPhase.Syllabus.SyllabusItems.forEach(function (item) {\r\n var syllabusItem = JSON.parse(JSON.stringify(item));\r\n\r\n //Get any history tries\r\n var historyTries = [];\r\n if (syllabusItem.History && syllabusItem.History.length) {\r\n var itemsHistory = syllabusItem.History.filter(x => x.CrewId == trainee.CrewId);\r\n if (itemsHistory.length) {\r\n var allHistoryTries = [];\r\n itemsHistory.forEach(function(item){\r\n allHistoryTries = allHistoryTries.concat(item.Tries);\r\n });\r\n allHistoryTries.forEach(function (historyTry) {\r\n var performedTry = { Comments: null, ActionNo: 0 };\r\n performedTry.ActionNo = historyTry.ActionNo;\r\n performedTry.isReadOnly = true;\r\n performedTry.Comments = historyTry.Comments;\r\n performedTry.InstructorName = historyTry.InstructorName;\r\n performedTry.SubmissionDate = historyTry.SubmissionDate;\r\n performedTry.Grade = historyTry.TryGrading.Grade;\r\n performedTry.AcTypes = historyTry.AcTypes;\r\n performedTry.Sectors = historyTry.Sectors;\r\n historyTries.push(performedTry);\r\n })\r\n }\r\n }\r\n\r\n var relatedSessionItem = trainee.Session.Items.find(x => x.Id == syllabusItem.Id);\r\n\r\n //Pending tries\r\n var pendingTriesLeft = syllabusItem.MandatoryCount - historyTries.length;\r\n\r\n if(syllabusItem.MandatoryCount == 0 && historyTries.length == 0){ //for non-mandatory items: add 1 attempt if not already performed\r\n pendingTriesLeft = 1;\r\n }\r\n\r\n var pendingTries = [];\r\n for (var i = 0; i < pendingTriesLeft; i++) {\r\n pendingTries.push({\r\n Comments: null,\r\n ActionNo: (historyTries.length) + i + 1,\r\n isFirstTry: i == 0,\r\n TryGrading: { \r\n Grade: syllabusItem.DefaultGrade? syllabusItem.DefaultGrade : null, \r\n Competences: [], \r\n GradeType: syllabusItem.GradeType \r\n }\r\n });\r\n }\r\n\r\n //Add pending tries to history tries\r\n var tries = historyTries.concat(pendingTries);\r\n\r\n //Create syllabus item depending on existing values\r\n if (!relatedSessionItem) {\r\n tries.filter(x => !x.isReadOnly).forEach(function (attempt) {\r\n attempt.TryGrading.Competences = setTraineeCompetences(syllabusItem.Competences, attempt.TryGrading);\r\n });\r\n\r\n var newItem = {\r\n RepeatRequired: false,\r\n Selected: false,\r\n Tries: tries,\r\n PhaseId: scope.selectedPhase.PhaseId,\r\n Id: syllabusItem.Id\r\n };\r\n traineeSessionItems.push(newItem);\r\n mergeSyllabusItemWithSession(syllabusItem, newItem);\r\n }\r\n else {\r\n var sessionTries = [];\r\n tries.forEach(function (tryItem) {\r\n var relatedSessionTry = relatedSessionItem.Tries.find(x => x.ActionNo == tryItem.ActionNo);\r\n if (relatedSessionTry && !tryItem.isReadOnly) {\r\n sessionTries.push(deepCopy(relatedSessionTry));\r\n }\r\n else {\r\n sessionTries.push(deepCopy(tryItem));\r\n }\r\n });\r\n\r\n //Add any Extra tries\r\n if(syllabusItem.MandatoryCount>0){\r\n var extraTries = relatedSessionItem.Tries.filter(x => x.ActionNo > syllabusItem.MandatoryCount && !x.isReadOnly);\r\n sessionTries = sessionTries.concat(extraTries);\r\n }\r\n\r\n sessionTries.filter(x => !x.isReadOnly).forEach(function (attempt) {\r\n attempt.TryGrading.Competences = setTraineeCompetences(syllabusItem.Competences, attempt.TryGrading);\r\n });\r\n\r\n var existingItem = {\r\n RepeatRequired: relatedSessionItem.RepeatRequired,\r\n Selected: relatedSessionItem.Selected,\r\n Tries: sessionTries,\r\n PhaseId: scope.selectedPhase.PhaseId,\r\n Id: syllabusItem.Id\r\n };\r\n\r\n \r\n traineeSessionItems.push(existingItem);\r\n mergeSyllabusItemWithSession(syllabusItem, existingItem);\r\n }\r\n\r\n var traineeSyllabus = traineeSyllabi.find(x => x.TraineeIds.includes(trainee.CrewId));\r\n if (!traineeSyllabus.Items.some(x => x.Id == syllabusItem.Id)) { \r\n traineeSyllabus.Items.push(syllabusItem); \r\n }\r\n });\r\n\r\n trainee.Session.Items = traineeSessionItems;\r\n });\r\n\r\n\r\n\r\n traineeSyllabi.forEach(function(syllabus){\r\n SyllabusGrouping(syllabus);\r\n })\r\n scope.traineeSyllabi = traineeSyllabi;\r\n }\r\n\r\n function mergeSyllabusItemWithSession(syllabusItem, sessionItem) {\r\n syllabusItem.RepeatRequired = sessionItem.RepeatRequired;\r\n syllabusItem.Selected = sessionItem.Selected;\r\n syllabusItem.Tries = sessionItem.Tries;\r\n }\r\n\r\n function leftScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\r\n }\r\n \r\n function rightScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\r\n }\r\n\r\n function deepCopy(originalObject) {\r\n return JSON.parse(JSON.stringify(originalObject));\r\n }\r\n\r\n function SyllabusGrouping(syllabus) {\r\n //Syllabus Items Group By 'GroupId'\r\n var syllabusGroups = [];\r\n syllabus.Items.forEach(function (item) {\r\n if (!syllabusGroups.some(x => x.Id == item.SelectedGroup.Id)) {\r\n if (!item.SelectedGroup) {\r\n item.SelectedGroup = {\r\n Id: 0,\r\n Title: 'General'\r\n };\r\n }\r\n\r\n var syllabusGroup = {\r\n Id: item.SelectedGroup.Id,\r\n Title: item.SelectedGroup.Title ? item.SelectedGroup.Title : 'General',\r\n Items: []\r\n };\r\n\r\n syllabusGroup.Items.push(item);\r\n syllabusGroups.push(syllabusGroup);\r\n }\r\n else {\r\n syllabusGroups.filter(x => x.Id == item.SelectedGroup.Id)[0].Items.push(item);\r\n }\r\n });\r\n\r\n syllabus.ItemsGrouped = syllabusGroups;\r\n }\r\n\r\n function setTraineeCompetences(competences, sessionItem) {\r\n var traineeCompetences = [];\r\n competences.forEach(function (competence) {\r\n var traineeCompetence = JSON.parse(JSON.stringify(competence));\r\n var existingCompetence = sessionItem.Competences.find(x => x.Id == traineeCompetence.Id);\r\n //Get saved values\r\n traineeCompetence.Grading = existingCompetence ? existingCompetence.Grading : null;\r\n traineeCompetence.Comments = existingCompetence ? existingCompetence.Comments : null;\r\n if (existingCompetence) {\r\n traineeCompetence.SubCompetences.filter(x => existingCompetence.SubCompetences.some(y => y.Id == x.Id)).forEach(function (commonSub) {\r\n commonSub.Selected = existingCompetence.SubCompetences.find(s => s.Id == commonSub.Id).Selected;\r\n });\r\n traineeCompetence.hasMandatory = traineeCompetence.MandatorySub.includes(Number(traineeCompetence.Grading));\r\n traineeCompetence.hasOptional = traineeCompetence.OptionalSub.includes(Number(traineeCompetence.Grading));\r\n }\r\n traineeCompetences.push(traineeCompetence);\r\n });\r\n return traineeCompetences;\r\n }\r\n\r\n function setSubCompetenceValues(current) {\r\n var updated = [];\r\n var first = parseInt(current[0], 10);\r\n var last = current[current.length - 1];\r\n\r\n if (first) {\r\n for (var i = first; i <= last; i++) {\r\n updated.push(i);\r\n }\r\n }\r\n return updated;\r\n }\r\n\r\n\r\n\r\n /***************************************************************** Submit ********************************************************************************/\r\n function SubmitSession() {\r\n setReleaseStatus();\r\n\r\n if (!isValidForm()) {\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgSubmitValidation.html',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'lg'\r\n });\r\n }\r\n else {\r\n\r\n if(isGround){\r\n //Last save before submission\r\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, function () {\r\n // Get all trainees found for this session (filter by course and date)\r\n TrainingSessionFactory.getSessionTrainees(courseId, date, dutyId, function (Trainees) {\r\n manageSubmission(Trainees);\r\n });\r\n });\r\n }\r\n else{\r\n //Last save before submission\r\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, function () {\r\n // Get all trainees found for this session (filter by course and date)\r\n FlightSessionFactory.getSessionTrainees(courseId, date, dutyNo, dutyDay, function (Trainees) {\r\n manageSubmission(Trainees);\r\n });\r\n });\r\n }\r\n }\r\n }\r\n\r\n\r\n function manageSubmission(Trainees){\r\n PrepareSessionForSubmission(Trainees);\r\n setReleaseStatus();\r\n \r\n var requiresInstructorSignature = RequiresInstructorSignature();\r\n\r\n var confirmationMsg = scope.selectedPhase.ReleaseGrading.ConfirmationMessage;\r\n \r\n // submit now\r\n var releaseGrading = (scope.selectedPhase.ReleaseGrading.Comments || \r\n scope.selectedPhase.ReleaseGrading.GradeType == 'Numeric' || \r\n scope.selectedPhase.ReleaseGrading.GradeType == 'Outcome' ||\r\n scope.selectedPhase.ReleaseGrading.Competences.length) &&\r\n scope.selectedPhase.ReleaseGrading.GradeType != 'CertificateExam';\r\n\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgSign.html',\r\n controller: 'SignatureModalCtrl',\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n courseId: function () { return courseId; },\r\n date: function () { return date; },\r\n dutyId: function () { return dutyId; },\r\n dutyNo: function () { return dutyNo; },\r\n dutyDay: function () { return dutyDay; },\r\n confirmationMsg: function () { return confirmationMsg; },\r\n requiresInstructorSignature: function () { return requiresInstructorSignature },\r\n trainees: function () { return scope.trainees },\r\n submitSession: function () { return SaveSession; },\r\n releaseGrading: function () { return releaseGrading;} ,\r\n isReleased: function () { return scope.course.ReleasedPhase;}\r\n }\r\n });\r\n\r\n scope.modalInstance.result.then(function (result) {\r\n if(result.success){\r\n $location.path(\"/\");\r\n }\r\n });\r\n }\r\n\r\n function RequiresTraineeSignature(){\r\n // End of session signature\r\n var endOfSessionSignature = scope.selectedPhase.DayGrading.TraineeSignature;\r\n\r\n // End of module signature\r\n var endOfModuleSignature = scope.course.ReleasedPhase && scope.selectedPhase.ReleaseGrading.TraineeSignature;\r\n\r\n return endOfSessionSignature || endOfModuleSignature;\r\n }\r\n\r\n function RequiresInstructorSignature(){\r\n /* Instructor signature needed if\r\n 1. Syllabus attached needs signature\r\n 2. Completed syllabus items need signature\r\n 3. End of session needs signature\r\n 4. Module is released and end of module needs signature\r\n */\r\n\r\n // 1. Check if syllabus exists and needs signature\r\n var syllabusSignature = scope.selectedPhase.Syllabus && scope.selectedPhase.Syllabus.SignatureRequired;\r\n\r\n // 2. Filter selected syllabus items & check if they need signature\r\n var selectedItems = [];\r\n scope.trainees.forEach(function(trainee){\r\n var traineeSelectedItems = trainee.Session.Items.filter(x => x.Selected).map(x => x.Id);\r\n selectedItems = selectedItems.concat(traineeSelectedItems);\r\n })\r\n selectedItems = [...new Set(selectedItems)];\r\n\r\n var syllabusItemSignature = scope.selectedPhase.Syllabus && scope.selectedPhase.Syllabus.SyllabusItems.filter(x => selectedItems.includes(x.Id)).some(x => x.SignatureRequired);\r\n\r\n // 3. End of session signature\r\n var endOfSessionSignature = scope.selectedPhase.DayGrading.InstructorSignature;\r\n\r\n // 4. End of module signature\r\n var endOfModuleSignature = scope.course.AvailableRelease && scope.course.ReleasedPhase && scope.selectedPhase.ReleaseGrading.InstructorSignature;\r\n\r\n return syllabusSignature || syllabusItemSignature || endOfSessionSignature || endOfModuleSignature;\r\n }\r\n \r\n\r\n /**\r\n * Check if Release requirements are met\r\n * @param {object} group \r\n */\r\n function checkReleaseAvailability() {\r\n //Available Release if No pending mandatory items\r\n //Calculate item status for each trainee\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function(sessionTrainee){\r\n\r\n if(scope.selectedPhase.Syllabus){\r\n var syllabusItems = scope.selectedPhase.Syllabus.SyllabusItems;\r\n sessionTrainee.Session.Items.forEach(function(sessionItem){\r\n var performedTries = sessionItem.Tries.filter(x => x.isReadOnly || x.Selected).length; // history & current session\r\n var mandatoryCount = syllabusItems.find(x => x.Id == sessionItem.Id).MandatoryCount;\r\n\r\n sessionItem.Status = (mandatoryCount>0 && performedTries < mandatoryCount) ? \"Pending\" : \"Completed\";\r\n });\r\n \r\n sessionTrainee.AvailableRelease = !sessionTrainee.Session.Items.some(x => x.Status == \"Pending\");\r\n }\r\n else{\r\n sessionTrainee.AvailableRelease = true;\r\n }\r\n \r\n });\r\n \r\n if(scope.selectedPhase.ModuleType == \"Training\"){\r\n scope.trainees.filter(x => !x.Session.Absent && !x.AvailableRelease).forEach(function(trainee){\r\n trainee.Session.Released = false;\r\n });\r\n\r\n if(scope.trainees.filter(x => !x.Session.Absent).some(x => !x.AvailableRelease)){\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function(trainee){\r\n trainee.Session.Released = false;\r\n })\r\n }\r\n }\r\n\r\n scope.course.ReleasedPhase = scope.trainees.filter(x => !x.Absent).some(x => x.Session.Released);\r\n return !scope.trainees.filter(x => !x.Session.Absent).some(x => !x.AvailableRelease); \r\n \r\n }\r\n\r\n function SaveSession(password, withRelease) {\r\n scope.submittedSession.SignaturePassword = password;\r\n \r\n if(withRelease){\r\n scope.submittedSession.ReleasedPhase = true;\r\n scope.submittedSession.TraineeSessions.filter(x => !x.Absent).forEach(function(trainee){\r\n trainee.Released = true;\r\n });\r\n }\r\n\r\n if(isGround){\r\n return TrainingSessionFactory.submitSession(scope.submittedSession);\r\n }\r\n else{\r\n return FlightSessionFactory.submitSession(scope.submittedSession);\r\n }\r\n }\r\n\r\n function PrepareSessionForSubmission(Trainees) {\r\n // Filter Trainee Sessions\r\n var trainees = Trainees.filter(x => x.EligibilityStatus);\r\n trainees.forEach(function (trainee) {\r\n trainee.Session.Items = trainee.Session.Items.filter(x => x.Selected);\r\n \r\n // Empty absent trainee sessions\r\n if (trainee.Session.Absent) {\r\n trainee.Session.Items = [];\r\n trainee.Session.DayGrading.Comments = null;\r\n trainee.Session.DayGrading.Competences = [];\r\n trainee.Session.DayGrading.Grade = null;\r\n trainee.Session.ReleaseGrading.Comments = null;\r\n trainee.Session.ReleaseGrading.Competences = [];\r\n trainee.Session.ReleaseGrading.Grade = null;\r\n }\r\n });\r\n\r\n var sessionSectors = [];\r\n if(!isGround){\r\n //Collect session sectors for flight\r\n trainingFlightIds.forEach(function(flightId){\r\n var sector = {\r\n FlightId : flightId,\r\n PM: null,\r\n PF: null,\r\n SessionSectorSeats : []\r\n };\r\n\r\n if(scope.course.PilotFunctions){\r\n\r\n // Set PM/PF values\r\n var sectors = [];\r\n scope.course.PilotFunctions.forEach(function(pilot){\r\n sectors = sectors.concat(pilot.Sectors.filter(x => x.FlightId == flightId && !x.NonApplicable));\r\n });\r\n \r\n var PMsector = sectors.find(sec => sec.isPM);\r\n var PFsector = sectors.find(sec => !sec.isPM)\r\n \r\n if(PMsector) sector.PM = PMsector.CrewId;\r\n if(PFsector) sector.PF = PFsector.CrewId;\r\n\r\n // Set seat values\r\n scope.course.PilotFunctions.forEach(function(pilot){\r\n var isInstructor = pilot.IsInstructor;\r\n var relevantSector = pilot.Sectors.find(x => x.FlightId == flightId && (isInstructor || !x.NonApplicable));\r\n if(relevantSector){\r\n var seat = {\r\n CrewId: relevantSector.CrewId,\r\n Seat : relevantSector.Seat\r\n };\r\n\r\n sector.SessionSectorSeats.push(seat);\r\n }\r\n });\r\n \r\n }\r\n sessionSectors.push(sector);\r\n });\r\n }\r\n\r\n // Create Session\r\n scope.submittedSession = {\r\n SessionDate: date,\r\n CourseId: courseId,\r\n GroundDutyIds: isGround ? [dutyId] : [],\r\n Sectors: sessionSectors,\r\n AircraftVisits: scope.course.Media && scope.course.Media.radioModel == \"Aircraft\" ? scope.course.Media.inputAircrafts : [],\r\n SelectedMedia: scope.course.Media ? scope.course.Media.radioModel : \"\",\r\n SyntheticDeviceId: scope.course.Media && scope.course.Media.radioModel == \"Simulator\" ? scope.course.Media.selectedDevice.selection : null,\r\n ReleasedPhase: scope.course.ReleasedPhase,\r\n GradeType: scope.selectedPhase.DayGrading.GradeType,\r\n ReleaseGradeType: scope.selectedPhase.ReleaseGrading.GradeType,\r\n TraineeSessions: trainees.map(x => x.Session),\r\n SyllabusVersionId: scope.selectedPhase.Syllabus ? scope.selectedPhase.Syllabus.SyllabusVersionId : null,\r\n PhaseId: scope.selectedPhase.PhaseId\r\n };\r\n\r\n }\r\n\r\n\r\n function isValidForm() {\r\n /*Requirements before submitting a session\r\n 1. OnLine Mode\r\n 2. Date Allowed\r\n 3. Pending syllabus items\r\n 4. Pending syllabus items for different trainee\r\n 5. Media Validation\r\n 6. Day Grading\r\n 7. Release Grading\r\n 8. Certificate Exam Grading\r\n 9. Trainee Signature\r\n */\r\n\r\n var isValid = false;\r\n var info = {\r\n border: \"\",\r\n icon: \"\",\r\n msg: \"\",\r\n scrollToTop: false\r\n };\r\n\r\n if (!window.navigator.onLine) {\r\n info = {\r\n border: \"border-left-red\",\r\n icon: \"fa-warning text-red\",\r\n msg: \" Online mode is required in order to submit a training.

Check your connection and try again!

\",\r\n scrollToTop: false\r\n };\r\n }\r\n else if (!dateAllowed()) {\r\n info = {\r\n border: \"border-left-red\",\r\n icon: \"fa-calendar-times-o text-red\",\r\n msg: \"You can not submit a session earlier than its duty date!\",\r\n scrollToTop: false\r\n };\r\n }\r\n else if (!isSeatValid()) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-plane text-orange\",\r\n msg: \"You need to select different seats for each pilot!\",\r\n scrollToTop: true\r\n };\r\n }\r\n else if (!isPilotFunctionValid()) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-plane text-orange\",\r\n msg: \" Each sector should have a different PM/PF value for each pilot!\",\r\n scrollToTop: true\r\n };\r\n }\r\n else if (syllabusPending()) {\r\n var traineeDetailsMsg = \"\";\r\n if(scope.selectedTrainee && (scope.selectedPhase.Syllabus.IsGradable || scope.selectedPhase.InFlight)) {\r\n traineeDetailsMsg = \" for \" + scope.selectedTrainee.Name + \"\"\r\n }\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-calendar-times-o text-orange\",\r\n msg: \"Form cannot be submitted!

Please complete all mandatory syllabus items\" + traineeDetailsMsg +\"

\",\r\n scrollToTop:false\r\n };\r\n }\r\n else if(traineesPending()){\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-calendar-times-o text-orange\",\r\n msg: \"Form cannot be submitted!

Please complete all trainee forms.

\",\r\n scrollToTop:true\r\n };\r\n }\r\n else if (!isMediaValid()) {\r\n if (scope.hasNoAircraft) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-plane text-orange\",\r\n msg: \"You need to provide an aircraft type!\",\r\n scrollToTop:true\r\n };\r\n }\r\n else if (scope.hasNoDevice) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-plane text-orange\",\r\n msg: \"You need to select a synthetic device!\",\r\n scrollToTop:true\r\n };\r\n\r\n }\r\n }\r\n else if(!isSyllabusGradingValid()){\r\n var invalidTrainees = scope.trainees.filter(t => t.Session.SyllabusValidationErrors && t.Session.SyllabusValidationErrors.Items.length);\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"Some of the selected syllabus items require a grading\",\r\n SyllabusErrors : invalidTrainees.map(t => t.Session.SyllabusValidationErrors),\r\n scrollToTop:false\r\n };\r\n }\r\n else if (!isGradingValid()) {\r\n if (!scope.gradingValidationInfo.isDayCompetencesValid || !scope.gradingValidationInfo.isReleaseCompetencesValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"You need to grade all competences before submitting!\",\r\n scrollToTop:false\r\n };\r\n }\r\n else if (!scope.gradingValidationInfo.isDayGradingValid || !scope.gradingValidationInfo.isReleaseGradingValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"You need to grade all trainees!\",\r\n scrollToTop:false\r\n };\r\n }\r\n else if (!scope.gradingValidationInfo.isCertificateGradingValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"You need to grade all certificate exams!\",\r\n scrollToTop:false\r\n };\r\n }\r\n }\r\n else if(scope.requiresTraineeSignature && !scope.allSignaturesComplete){\r\n\r\n if(scope.selectedTrainee && !scope.selectedTrainee.Session.Authorized){\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-pencil-square-o text-orange\",\r\n msg: \"\" + scope.selectedTrainee.Name + \" needs to sign the form!\",\r\n scrollToTop:false\r\n };\r\n }\r\n else{\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"All trainees need to sign their forms!\",\r\n scrollToTop:true\r\n };\r\n }\r\n }\r\n else {\r\n isValid = true;\r\n }\r\n\r\n scope.info = info;\r\n return isValid;\r\n }\r\n\r\n \r\n function dateAllowed() {\r\n var dateAllowed = false;\r\n\r\n //Submission is allowed only on the day of the training and after\r\n var trainingDay = moment.utc(date).valueOf();\r\n var today = moment.utc().valueOf();\r\n\r\n if (today >= trainingDay) {\r\n dateAllowed = true;\r\n }\r\n\r\n return dateAllowed;\r\n }\r\n\r\n function isSeatValid(){\r\n var isValid = true;\r\n if(!isGround){\r\n for (var i = 0; i < trainingFlightIds.length; i++) {\r\n var selectedSeats = [];\r\n scope.course.PilotFunctions.forEach(function(pilot){\r\n selectedSeats = selectedSeats.concat(pilot.Sectors.filter(x => !x.NonApplicable && x.FlightId == trainingFlightIds[i]).map(x => x.Seat))\r\n });\r\n isValid = (new Set(selectedSeats)).size == selectedSeats.length;\r\n if(!isValid) break;\r\n }\r\n }\r\n return isValid;\r\n }\r\n\r\n function isPilotFunctionValid(){\r\n var isValid = true;\r\n if(!isGround){\r\n for (var i = 0; i < trainingFlightIds.length; i++) {\r\n var sectors = [];\r\n \r\n scope.course.PilotFunctions.forEach(function(pilot){\r\n sectors = sectors.concat(pilot.Sectors.filter(x => !x.NonApplicable && x.FlightId == trainingFlightIds[i]))\r\n });\r\n\r\n isValid = sectors.filter(x => x.isPM).length == 1;\r\n if(!isValid) break;\r\n }\r\n }\r\n return isValid;\r\n }\r\n\r\n function syllabusPending(){\r\n var syllabus = scope.selectedPhase.Syllabus;\r\n var type = scope.selectedPhase.ModuleType;\r\n\r\n return syllabus && type == 'Check' && ( (scope.selectedTrainee && !scope.selectedTrainee.AvailableRelease) || ((!scope.selectedTrainee && scope.trainees.filter(x => !x.Session.Absent).some(x => !x.AvailableRelease))) );\r\n }\r\n\r\n function traineesPending(){\r\n var syllabus = scope.selectedPhase.Syllabus;\r\n var type = scope.selectedPhase.ModuleType;\r\n\r\n return syllabus && type == 'Check' && scope.selectedTrainee && scope.trainees.filter(x => !x.Session.Absent).some(x => !x.AvailableRelease);\r\n }\r\n\r\n function isSyllabusGradingValid(){\r\n var syllabus = scope.selectedPhase.Syllabus;\r\n if(syllabus && syllabus.IsGradable){\r\n \r\n var gradableSyllabusItems = syllabus.SyllabusItems.filter(x => x.IsGradable);\r\n var gradableSyllabusItemIds = gradableSyllabusItems.map(x => x.Id);\r\n\r\n //foreach trainee get selected tries that need grading\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function(trainee){\r\n var invalidItems = [];\r\n trainee.Session.Items.filter(x => x.Selected && gradableSyllabusItemIds.includes(x.Id)).forEach(function(selectedItem){\r\n var syllabusItem = gradableSyllabusItems.find(x => x.Id == selectedItem.Id);\r\n var gradingType = syllabusItem.GradeType; //Numeric or Outcome or Competences\r\n var traineeSelectedTries = selectedItem.Tries.filter(x => x.Selected);\r\n\r\n traineeSelectedTries.forEach(function(selectedTry){\r\n\r\n var invalidGrading = gradingType != \"Competences\" && !selectedTry.TryGrading.Grade;\r\n var invalidCompetences = gradingType == \"Competences\" && !selectedTry.TryGrading.isCompetenceValid;\r\n \r\n if(invalidGrading || invalidCompetences){\r\n invalidItems.push(syllabusItem.Title);\r\n }\r\n });\r\n });\r\n trainee.Session.SyllabusValidationErrors = {\r\n Name : trainee.Name,\r\n Items : invalidItems\r\n };\r\n }); \r\n }\r\n\r\n return !scope.trainees.some(t => t.Session.SyllabusValidationErrors && t.Session.SyllabusValidationErrors.Items.length);\r\n }\r\n\r\n function isGradingValid() {\r\n var isDayGradingValid = scope.selectedPhase.DayGrading.GradeType == \"NotSet\";\r\n var isReleaseGradingValid = scope.selectedPhase.ReleaseGrading.GradeType == \"NotSet\" || scope.selectedPhase.ReleaseGrading.GradeType == \"CertificateExam\" || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\r\n var isCertificateGradingValid = scope.selectedPhase.ReleaseGrading.GradeType != \"CertificateExam\" || !scope.course.ReleasedPhase;\r\n var isDayCompetencesValid = scope.selectedPhase.DayGrading.Competences.length == 0;\r\n var isReleaseCompetencesValid = scope.selectedPhase.ReleaseGrading.Competences.length == 0 || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\r\n\r\n if (!isDayGradingValid) isDayGradingValid = !scope.trainees.filter(x => !x.Session.Absent).some(x => !x.Session.DayGrading.isGradeValid);\r\n if (!isReleaseGradingValid) isReleaseGradingValid = !scope.trainees.filter(x => !x.Session.Absent && x.Session.Released).some(x => !x.Session.ReleaseGrading.isGradeValid);\r\n if (!isCertificateGradingValid) isCertificateGradingValid = !scope.trainees.filter(x => !x.Session.Absent && x.AvailableRelease).some(x => !x.Session.ReleaseGrading.isCertificateValid);\r\n\r\n\r\n if (!isDayCompetencesValid) isDayCompetencesValid = !scope.trainees.filter(x => !x.Session.Absent).some(x => !x.Session.DayGrading.isCompetenceValid);\r\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !scope.trainees.filter(x => !x.Session.Absent && x.Session.Released).some(x => !x.Session.ReleaseGrading.isCompetenceValid);\r\n\r\n scope.gradingValidationInfo = {\r\n isDayGradingValid: isDayGradingValid,\r\n isReleaseGradingValid: isReleaseGradingValid,\r\n isDayCompetencesValid: isDayCompetencesValid,\r\n isReleaseCompetencesValid: isReleaseCompetencesValid,\r\n isCertificateGradingValid: isCertificateGradingValid\r\n };\r\n\r\n return isDayGradingValid && isReleaseGradingValid && isDayCompetencesValid && isReleaseCompetencesValid && isCertificateGradingValid;\r\n }\r\n\r\n function isTraineeGradingValid(trainee) {\r\n var isDayGradingValid = scope.selectedPhase.DayGrading.GradeType == \"NotSet\";\r\n var isReleaseGradingValid = scope.selectedPhase.ReleaseGrading.GradeType == \"NotSet\" || scope.selectedPhase.ReleaseGrading.GradeType == \"CertificateExam\" || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\r\n var isCertificateGradingValid = scope.selectedPhase.ReleaseGrading.GradeType != \"CertificateExam\" || !scope.course.ReleasedPhase;\r\n var isDayCompetencesValid = scope.selectedPhase.DayGrading.Competences.length == 0;\r\n var isReleaseCompetencesValid = scope.selectedPhase.ReleaseGrading.Competences.length == 0 || !scope.course.AvailableRelease || !scope.course.ReleasedPhase;\r\n\r\n if (!isDayGradingValid) isDayGradingValid = trainee.Session.DayGrading.isGradeValid;\r\n if (!isReleaseGradingValid) isReleaseGradingValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isGradeValid;\r\n if (!isCertificateGradingValid) isCertificateGradingValid = !trainee.AvailableRelease || trainee.Session.ReleaseGrading.isCertificateValid;\r\n\r\n\r\n if (!isDayCompetencesValid) isDayCompetencesValid = trainee.Session.DayGrading.isCompetenceValid;\r\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isCompetenceValid;\r\n\r\n trainee.Session.gradingValidationInfo = {\r\n isDayGradingValid: isDayGradingValid,\r\n isReleaseGradingValid: isReleaseGradingValid,\r\n isDayCompetencesValid: isDayCompetencesValid,\r\n isReleaseCompetencesValid: isReleaseCompetencesValid,\r\n isCertificateGradingValid: isCertificateGradingValid\r\n };\r\n\r\n return isDayGradingValid && isReleaseGradingValid && isDayCompetencesValid && isReleaseCompetencesValid && isCertificateGradingValid;\r\n }\r\n\r\n function isMediaValid() {\r\n scope.hasNoAircraft = scope.course.Media && scope.course.Media.radioModel == \"Aircraft\" && !scope.course.Media.inputAircrafts.length;\r\n scope.hasNoDevice = scope.course.Media && scope.course.Media.radioModel == \"Simulator\" && !scope.course.Media.selectedDevice.selection;\r\n return !scope.hasNoAircraft && !scope.hasNoDevice;\r\n }\r\n\r\n /**\r\n * Triggered after a trainee has successfully signed\r\n */\r\n function updateTraineeSignatures(){\r\n updateSession();\r\n scope.allSignaturesComplete = !scope.trainees.filter(x => !x.Session.Absent).some(x => !x.Session.Authorized);\r\n scope.someSignaturesComplete = scope.trainees.filter(x => !x.Session.Absent).some(x => x.Session.Authorized);\r\n }\r\n\r\n function close() {\r\n scope.modalInstance.close();\r\n\r\n if(scope.info && scope.info.scrollToTop){\r\n $window.scrollTo(0, 0);\r\n }\r\n }\r\n\r\n function showReleasePanel(syllabus){\r\n var retVal = false;\r\n var phase = scope.selectedPhase;\r\n \r\n var availableCourse = scope.availableCourse && scope.trainees.length;\r\n var isCheck = phase.ModuleType=='Check';\r\n var releaseGrading = (phase.ReleaseGrading.Comments || \r\n phase.ReleaseGrading.GradeType == 'Numeric' || \r\n phase.ReleaseGrading.GradeType == 'Outcome' ||\r\n phase.ReleaseGrading.Competences.length) &&\r\n phase.ReleaseGrading.GradeType != 'CertificateExam';\r\n\r\n if(isCheck){\r\n retVal = availableCourse && releaseGrading;\r\n }\r\n else if(scope.traineeSyllabi.length > 1){\r\n var crewId = syllabus.TraineeIds[0];\r\n var trainee = scope.trainees.find(x => x.CrewId == crewId);\r\n retVal = scope.reloadRelease && trainee.AvailableRelease && trainee.Session.Released && availableCourse && releaseGrading;\r\n }\r\n else{\r\n retVal = scope.reloadRelease && scope.course.AvailableRelease && scope.course.ReleasedPhase && availableCourse && releaseGrading;\r\n }\r\n return retVal;\r\n }\r\n\r\n function releaseTrainee(syllabus){\r\n\r\n var crewIds = syllabus.TraineeIds;\r\n var trainees = scope.trainees.filter(x => crewIds.includes(x.CrewId));\r\n\r\n trainees.forEach(function(trainee){\r\n trainee.Session.Released = !trainee.Session.Released;\r\n });\r\n\r\n scope.course.ReleasedPhase = scope.trainees.filter(x => !x.Absent).some(x => x.Session.Released);\r\n }\r\n\r\n function releaseGroup(){\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function(trainee){\r\n trainee.Session.Released = !trainee.Session.Released;\r\n });\r\n\r\n scope.course.ReleasedPhase = scope.trainees.filter(x => !x.Absent).some(x => x.Session.Released);\r\n setReleaseStatus();\r\n \r\n }\r\n\r\n function showReleaseBtn(syllabus){\r\n var retVal = false;\r\n\r\n var availableCourse = scope.availableCourse && scope.trainees.length;\r\n var isCheck = scope.selectedPhase.ModuleType=='Check';\r\n \r\n\r\n if(isCheck){\r\n retVal = false;\r\n }\r\n else if(scope.traineeSyllabi.length > 1){\r\n var crewId = syllabus.TraineeIds[0];\r\n var trainee = scope.trainees.find(x => x.CrewId == crewId);\r\n retVal = scope.reloadRelease && availableCourse && trainee.AvailableRelease;\r\n }\r\n else{\r\n retVal = scope.reloadRelease && availableCourse && scope.course.AvailableRelease;\r\n }\r\n\r\n return retVal;\r\n }\r\n\r\n function showGroupReleaseBtn(){\r\n var retVal = false;\r\n\r\n var availableCourse = scope.availableCourse && scope.trainees.length>0;\r\n var isCheck = scope.selectedPhase.ModuleType=='Check';\r\n var releaseGrading = (scope.selectedPhase.ReleaseGrading.Comments || \r\n scope.selectedPhase.ReleaseGrading.GradeType == 'Numeric' || \r\n scope.selectedPhase.ReleaseGrading.GradeType == 'Outcome' ||\r\n scope.selectedPhase.ReleaseGrading.Competences.length) &&\r\n scope.selectedPhase.ReleaseGrading.GradeType != 'CertificateExam';\r\n \r\n\r\n if(isCheck){\r\n retVal = false;\r\n }\r\n else{\r\n retVal = scope.reloadRelease && availableCourse && releaseGrading && !scope.trainees.filter(x => !x.Session.Absent).some(x => !x.AvailableRelease);\r\n }\r\n\r\n return retVal;\r\n }\r\n\r\n function getTraineeClass(crewId){\r\n\r\n isSyllabusGradingValid();\r\n\r\n var textClass=\"\";\r\n\r\n var trainee = scope.trainees.find(x => x.CrewId == crewId);\r\n var syllabus = scope.selectedPhase.Syllabus;\r\n var type = scope.selectedPhase.ModuleType;\r\n \r\n var allSyllabusCompleted = trainee.AvailableRelease;\r\n\r\n //Draft status\r\n var selectedItems = trainee.Session.Items.some(i => i.Tries.filter(t => !t.isReadOnly).some(t => t.Selected));\r\n\r\n //Validate syllabus\r\n var validSyllabusGrading = !trainee.Session.SyllabusValidationErrors || !trainee.Session.SyllabusValidationErrors.Items.length;\r\n \r\n //Validate Day grading\r\n var isDayGradingValid = scope.selectedPhase.DayGrading.GradeType == \"NotSet\";\r\n var isDayCompetencesValid = scope.selectedPhase.DayGrading.Competences.length == 0;\r\n if (!isDayGradingValid) isDayGradingValid = trainee.Session.DayGrading.isGradeValid;\r\n if (!isDayCompetencesValid) isDayCompetencesValid = trainee.Session.DayGrading.isCompetenceValid;\r\n\r\n\r\n //Validate Release grading\r\n var isReleaseGradingValid = scope.selectedPhase.ReleaseGrading.GradeType == \"NotSet\" || scope.selectedPhase.ReleaseGrading.GradeType == \"CertificateExam\" \r\n || (scope.selectedPhase.ModuleType == \"Training\" && (!trainee.AvailableRelease || !trainee.Session.Released));\r\n\r\n var isReleaseCompetencesValid = scope.selectedPhase.ReleaseGrading.Competences.length == 0 \r\n || (scope.selectedPhase.ModuleType == \"Training\" && (!trainee.AvailableRelease || !trainee.Session.Released));\r\n if (!isReleaseGradingValid) isReleaseGradingValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isGradeValid;\r\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !trainee.Session.Released || trainee.Session.ReleaseGrading.isCompetenceValid;\r\n\r\n\r\n\r\n if(selectedItems){\r\n textClass = \"bg-amber text-white\";\r\n if(validSyllabusGrading && isDayGradingValid && isDayCompetencesValid && isReleaseGradingValid && isReleaseCompetencesValid\r\n && (type =='Training' || allSyllabusCompleted)){\r\n textClass = \"bg-green text-white\";\r\n }\r\n }\r\n \r\n return textClass;\r\n }\r\n\r\n function togglePanel(panelId) {\r\n $('#' + panelId).toggle();\r\n }\r\n\r\n /**\r\n * Toggle signature panel while trainee hasn't signed yet\r\n * @param {object} trainee \r\n */\r\n function openTraineeSignature(trainee){\r\n //Enter signature mode : trainee form becomes read-only\r\n if(!trainee.Session.Authorized){\r\n setReleaseStatus();\r\n //Trainee can sign only if his form is valid\r\n if (!validateTraineeForm(trainee)) {\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgSubmitValidation.html',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'lg'\r\n });\r\n }\r\n else{\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgTraineeSignature.html',\r\n controller: 'TraineeSignatureModalCtrl',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n trainee: function () { return trainee; },\r\n signatureSuccess: function () { return updateTraineeSignatures; }\r\n }\r\n });\r\n }\r\n }\r\n\r\n scope.someSignaturesComplete = scope.trainees.filter(x => !x.Session.Absent).some(x => x.Session.Authorized);\r\n }\r\n \r\n function validateTraineeForm(trainee) {\r\n var trainee = scope.selectedTrainee;\r\n\r\n var isValid = false;\r\n var info = {\r\n border: \"\",\r\n icon: \"\",\r\n msg: \"\",\r\n scrollToTop: false\r\n };\r\n\r\n if (!window.navigator.onLine) {\r\n info = {\r\n border: \"border-left-red\",\r\n icon: \"fa-warning text-red\",\r\n msg: \" Online mode is required in order to sign.

Check your connection and try again!

\",\r\n scrollToTop: false\r\n };\r\n }\r\n else if (syllabusPending()) {\r\n var traineeDetailsMsg = \"\";\r\n if(trainee && (scope.selectedPhase.Syllabus.IsGradable || scope.selectedPhase.InFlight)) {\r\n traineeDetailsMsg = \" for \" + trainee.Name + \"\"\r\n }\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-calendar-times-o text-orange\",\r\n msg: \"Form cannot be submitted!

Please complete all mandatory syllabus items\" + traineeDetailsMsg +\"

\",\r\n scrollToTop:false\r\n };\r\n }\r\n else if(!isSyllabusGradingValid() && trainee.Session.SyllabusValidationErrors && trainee.Session.SyllabusValidationErrors.Items.length){\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"Some of the selected syllabus items require a grading\",\r\n SyllabusErrors : trainee.Session.SyllabusValidationErrors,\r\n scrollToTop:false\r\n };\r\n }\r\n else if (!isTraineeGradingValid(trainee)) {\r\n if (!trainee.Session.gradingValidationInfo.isDayCompetencesValid || !trainee.Session.gradingValidationInfo.isReleaseCompetencesValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"You need to grade all competences!\",\r\n scrollToTop:false\r\n };\r\n }\r\n else if (!trainee.Session.isDayGradingValid || !trainee.Session.isReleaseGradingValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"You need to select an overall grade !\",\r\n scrollToTop:false\r\n };\r\n }\r\n else if (!trainee.Session.isCertificateGradingValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"You need to grade all certificate exams!\",\r\n scrollToTop:false\r\n };\r\n }\r\n }\r\n else {\r\n isValid = true;\r\n }\r\n\r\n scope.info = info;\r\n \r\n \r\n return isValid;\r\n }\r\n\r\n\r\n function resetSignature(trainee){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgResetSignature.html',\r\n controller: 'TraineeSignatureModalCtrl',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n trainee: function () { return trainee; },\r\n signatureSuccess: function () { return updateTraineeSignatures; }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (confirm) {\r\n if(confirm){\r\n trainee.Session.Authorized = false;\r\n scope.trainees.find(x => x.CrewId == trainee.CrewId).Session.Authorized = false;\r\n updateTraineeSignatures();\r\n }\r\n \r\n });\r\n }\r\n }\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/course.html',\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('CourseFactory', CourseFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name CourseFactory\r\n * @description \r\n * Add, Update, Delete and Get Training Courses.\r\n * @ngInject\r\n */\r\n function CourseFactory(IndexedDBService, GroundDutyFactory, $http,apiUrl) {\r\n\r\n /**\r\n * Initialize Course\r\n * @memberof CourseFactory\r\n */\r\n function Course() {\r\n this.Id = null;\r\n }\r\n\r\n var objType = 'Courses';\r\n var objCallback = Course;\r\n\r\n var service = {\r\n setCoursesFromServer: setCoursesFromServer,\r\n setCoursesToStorage : setCoursesToStorage, //save all courses\r\n addCourseToStorage : addCourseToStorage, //update course\r\n saveOneCourseToStorage : saveOneCourseToStorage, //save course\r\n getCoursesFromStorage : getCoursesFromStorage, //get all\r\n getCourseFromStorage : getCourseFromStorage, //getById\r\n updateCourseInfo : updateCourseInfo,\r\n updateFlightCourseInfo : updateFlightCourseInfo,\r\n getCoursesFromStorageByIds : getCoursesFromStorageByIds,\r\n setCourseOutdated: setCourseOutdated,\r\n upsertCourse : upsertCourse\r\n };\r\n\r\n /**\r\n * Get Course By Id\r\n * @memberof CourseFactory\r\n * @param {function} callback \r\n */\r\n function getCourseFromStorage(courseId, callback,errorCallback) {\r\n IndexedDBService.getById(objType, courseId).then(function (result) {\r\n\t\t\t\tcallback(result);\r\n\t\t\t}).catch(errorCallback);\r\n };\r\n \r\n /**\r\n * Get Courses\r\n * @memberof CourseFactory\r\n * @param {function} callback \r\n */\r\n function getCoursesFromStorage( callback,errorCallback) {\r\n IndexedDBService.getAll(objType).then(function (results) {\r\n\t\t\t\tcallback(results);\r\n\t\t\t}).catch(errorCallback);\r\n };\r\n\r\n \r\n /**\r\n * Get Course By Ids\r\n * @memberof CourseFactory\r\n * @param {function} callback \r\n */\r\n function getCoursesFromStorageByIds(courseIds, callback,errorCallback) {\r\n IndexedDBService.getAll(objType).then(function (results) {\r\n var selectedResults = [];\r\n results.forEach(function(result){\r\n if(courseIds.includes(result.Id) && selectedResults.filter(x=>x.Id == result.Id).length == 0)\r\n {\r\n selectedResults.push(result); \r\n }\r\n })\r\n\t\t\t\tcallback(selectedResults);\r\n\t\t\t}).catch(errorCallback);\r\n };\r\n\r\n \r\n\r\n function updateCourseInfo(courseId, dutyId, callback, errorOnSaveCallback, errorOnNetwork){\r\n var traingingApiURL = apiUrl + '/Training?courseId=' + courseId + '&dutyId=' + dutyId;\r\n $http.get(traingingApiURL, { 'Content-Type': 'application/json' })\r\n .then(function(data){\r\n var course = data.data;\r\n \r\n course.FetchedTime = moment.utc().toJSON();\r\n var duty = GroundDutyFactory.getGroundDutyFromStorage(dutyId);\r\n course.FetchedDutyCodes = duty.RelatedGroundDuties.filter(x => !x.IsInstructor).map(x => String(x.GroundDutyNo));\r\n course.LastFetchedDutyId = dutyId;\r\n\r\n //Upsert course in IndexDB \r\n upsertCourse(course, function(course){\r\n callback(course);\r\n }, errorOnSaveCallback);\r\n })\r\n .catch(errorOnNetwork)\r\n }\r\n \r\n function updateFlightCourseInfo(crewRouteCourse, date, dutyNo, dutyDay, callback, errorOnSaveCallback, errorOnNetwork){\r\n var traingingApiURL = apiUrl + '/Training/GetCrewRouteTraining';\r\n $http.post(traingingApiURL, crewRouteCourse, {'Content-Type' : 'application/json' })\r\n .then(function(data){\r\n var course = data.data;\r\n \r\n course.FetchedTime = moment.utc().toJSON();\r\n \r\n course.FetchedCrewRoute = {\r\n date: date, \r\n dutyNo: dutyNo,\r\n dutyDay: dutyDay\r\n };\r\n \r\n //Upsert course in IndexDB \r\n upsertCourse(course, function(course){\r\n callback(course);\r\n }, errorOnSaveCallback);\r\n })\r\n .catch(errorOnNetwork)\r\n }\r\n\r\n function upsertCourse(course, callback, errorOnSaveCallback){\r\n getCourseFromStorage(course.Id, function(localCourse) {\r\n if (localCourse) {\r\n saveOneCourseToStorage(course);\r\n } else {\r\n addCourseToStorage(course);\r\n }\r\n callback(course);\r\n }, errorOnSaveCallback);\r\n }\r\n\r\n\r\n function setCourseOutdated(courseId,callback,errorCallback){\r\n getCourseFromStorage(courseId,function(localCourse){ \r\n if(localCourse){\r\n localCourse.NeedsRefresh = true;\r\n saveOneCourseToStorage(localCourse);\r\n }\r\n\r\n if(callback){\r\n callback();\r\n }\r\n }, errorCallback)\r\n }\r\n \r\n\r\n \r\n /**\r\n * Set Courses from server API \r\n * @memberof CourseFactory\r\n * @param {array} courses Courses Object\r\n * @param {array} courseIdsToSend Current courses of the storage\r\n * @param {string} lastSyncDate Last Sync Date \r\n */\r\n function setCoursesFromServer(courses,callback,errorCallback) {\r\n \r\n getCoursesFromStorage(function(localCourses){\r\n // No courses found - Save All Incoming\r\n if (!localCourses || localCourses.length == 0) {\r\n setCoursesToStorage(courses);\r\n } \r\n else \r\n {\r\n for (var j = 0; j < courses.length; j++) {\r\n var IsCourseIncluded = false;\r\n\r\n for (var h = 0; h < localCourses.length; h++) {\r\n if (courses[j].Id == localCourses[h].Id) {\r\n IsCourseIncluded = true;\r\n break; \r\n }\r\n } \r\n \r\n //Update existing course\r\n if (IsCourseIncluded) {\r\n localCourses[h].Title = courses[j].Title; //Update title from sync\r\n saveOneCourseToStorage(localCourses[h]);\r\n } \r\n //Add a new Course\r\n else {\r\n addCourseToStorage(courses[j]);\r\n }\r\n }\r\n \r\n localCourses.filter(x=> !courses.some(z=>z.Id == x.Id)).forEach(function(course){\r\n IndexedDBService.remove(objType,course.Id)\r\n })\r\n } \r\n })\r\n \r\n }\r\n\r\n /**\r\n * Set Courses\r\n * @memberof CourseFactory\r\n * @param {array} Courses A list of courses to set to indexedDB\r\n */\r\n function setCoursesToStorage(Courses,callback,errorCallback) {\r\n IndexedDBService.addAll(objType, Courses).then(callback).catch(errorCallback);;\r\n };\r\n\r\n /**\r\n * Add Course to Storage\r\n * @memberof CourseFactory\r\n * @param {object} Course\r\n */\r\n function addCourseToStorage(Course,callback,errorCallback) {\r\n IndexedDBService.add(objType, Course).then(callback).catch(errorCallback);;\r\n };\r\n\r\n /**\r\n * Update Course to Storage\r\n * @memberof CourseFactory\r\n * @param {object} Course\r\n */\r\n function saveOneCourseToStorage(Course,callback,errorCallback) {\r\n IndexedDBService.put(objType, Course).then(callback).catch(errorCallback);\r\n };\r\n\r\n return service;\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('FlightSessionFactory', FlightSessionFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name FlightSessionFactory\r\n * @description \r\n * Add, Update, Delete and Flight Sessions.\r\n * @ngInject\r\n */\r\n function FlightSessionFactory(IndexedDBService, CrewRouteFactory, FlightFactory, CourseFactory, $http, apiUrl, $filter) {\r\n\r\n /**\r\n * Initialize Session\r\n * @memberof FlightSessionFactory\r\n */\r\n function Session() {\r\n this.Id = null;\r\n }\r\n\r\n var objType = 'FlightSessions';\r\n var objCallback = Session;\r\n\r\n var service = {\r\n getAll: getAll,\r\n getSession: getSession,\r\n setSession: setSession,\r\n updateSession: updateSession,\r\n getSessionTrainees: getSessionTrainees,\r\n submitSession: submitSession,\r\n remove: remove,\r\n getCrewRouteFlightTrainees : getCrewRouteFlightTrainees,\r\n applyTraineeInfoToSession : applyTraineeInfoToSession\r\n };\r\n\r\n /**\r\n * Get all flight training sessions\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\r\n function getAll(callback) {\r\n IndexedDBService.getAll(objType).then(function(results){\r\n callback(results);\r\n });\r\n };\r\n\r\n /**\r\n * Get session By day and courseId\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\r\n function getSession(courseId, day, dutyNo, dutyDay, trainingFlightIds, afterRefresh, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay]).then(function (session) {\r\n CourseFactory.getCourseFromStorage(courseId, function (course) {\r\n if (course && !course.HasLimitedInfo && course.CrewCoursePhases && course.CourseTrainees) {\r\n mergeCourseWithSession(course, session, dutyNo, dutyDay, trainingFlightIds, afterRefresh);\r\n }\r\n callback(course);\r\n }, errorCallback);\r\n })\r\n .catch(errorCallback);\r\n }\r\n\r\n\r\n /**\r\n * Remove session By day, dutyNo, dutyDay and courseId\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\r\n function remove(courseId, day, dutyNo, dutyDay, callback, errorCallback) {\r\n IndexedDBService.remove(objType, [day, courseId, dutyNo, dutyDay])\r\n .then(callback)\r\n .catch(errorCallback);\r\n };\r\n\r\n /**\r\n * Get session Trainees By day and courseId\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\r\n function getSessionTrainees(courseId, day, dutyNo, dutyDay, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay]).then(function (session) {\r\n var trainees = session && session.trainees ? session.trainees : [];\r\n callback(trainees);\r\n })\r\n .catch(errorCallback);\r\n };\r\n\r\n /**\r\n * Set session\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\r\n function setSession(session, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [session.day, session.courseId, session.dutyNo, session.dutyDay]).then(function (result) {\r\n if (result) {\r\n saveSessionToStorage(session).then(callback).catch(errorCallback);;\r\n } else {\r\n addSessionToStorage(session).then(callback).catch(errorCallback);\r\n }\r\n }).catch(errorCallback);\r\n };\r\n\r\n /**\r\n * Set session\r\n * @memberof FlightSessionFactory\r\n * @param {function} callback \r\n */\r\n function updateSession(trainees, session, courseId, day, dutyNo, dutyDay, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay])\r\n .then(function (localSession) {\r\n var isNewSession = false;\r\n if (!localSession) {\r\n localSession = { courseId: courseId, day: day, dutyNo: dutyNo, dutyDay: dutyDay, trainees: [] }\r\n isNewSession = true;\r\n } else {\r\n localSession.trainees = [];\r\n }\r\n\r\n if (session) {\r\n localSession.Media = session.Media;\r\n localSession.ReleasedPhase = session.ReleasedPhase;\r\n localSession.PilotFunctions = session.PilotFunctions;\r\n localSession.TraineeEligibilty = session.TraineeEligibilty;\r\n }\r\n\r\n trainees.forEach(function (trainee) {\r\n localSession.trainees.push(trainee);\r\n });\r\n\r\n if (isNewSession) {\r\n addSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n } else {\r\n saveSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n }\r\n }).catch(errorCallback);\r\n }\r\n\r\n function mergeCourseWithSession(course, session, dutyNo, dutyDay, trainingFlightIds, afterRefresh) {\r\n course.HasLimitedSession = session == undefined;\r\n\r\n var hasPreviousSessions = mergeSyllabusWithHistory(course.CourseTrainees, course.CrewCoursePhases);\r\n filterTraineesByEligibility(dutyNo, dutyDay, course, trainingFlightIds, session, afterRefresh);\r\n \r\n course.CrewCoursePhases.forEach(function (phase) {\r\n calculatePhaseStatus(phase, course);\r\n });\r\n course.selectedPhase = getSelectedPhase(course);\r\n\r\n\r\n // Calculate eligible trainees phase status\r\n course.CourseTrainees.forEach(function (trainee) {\r\n var traineePhase = trainee.Phases.find(x => x.PhaseId == course.selectedPhase.PhaseId);\r\n if (traineePhase) {\r\n trainee.ActivePhaseStatus = traineePhase.PhaseStatus;\r\n }\r\n else {\r\n trainee.ActivePhaseStatus = \"Pending\";\r\n }\r\n trainee.Selectable = trainee.ActivePhaseStatus == \"InProgress\";\r\n });\r\n\r\n // Non InProgress trainees will be marked as NonEligible (remove further ahead trainees on multiple InProgress phases)\r\n course.CourseTrainees.filter(x => !x.Selectable).forEach(function(invalidPhaseTrainee){\r\n invalidPhaseTrainee.EligibilityStatus = false;\r\n invalidPhaseTrainee.EligibilityDesc = \"AlreadySubmitted\";\r\n course.NonEligibleTrainees.push(invalidPhaseTrainee);\r\n });\r\n course.CourseTrainees = course.CourseTrainees.filter(x => x.EligibilityStatus);\r\n \r\n // Get trainee sessions\r\n course.CourseTrainees.forEach(function (trainee) {\r\n var sessionTrainee = session ? session.trainees.find(x => x.CrewId == trainee.CrewId) : null;\r\n if (sessionTrainee) {\r\n trainee.Session = sessionTrainee.Session;\r\n } else {\r\n trainee.Session = {\r\n Released: course.selectedPhase.ModuleType == \"Training\" ? false : true,\r\n CrewId: trainee.CrewId,\r\n Items: [],\r\n Absent: false,\r\n DayGrading: {\r\n Comments: null,\r\n Grade: null,\r\n Competences: []\r\n },\r\n ReleaseGrading: {\r\n Comments: null,\r\n Grade: null,\r\n Competences: []\r\n }\r\n }\r\n }\r\n });\r\n\r\n /* Set default values for release option\r\n Training Modules: 'No' release as default\r\n Check Module: 'Yes' release as default\r\n */\r\n course.ReleasedPhase = course.selectedPhase.ModuleType == \"Training\" ? false : true;\r\n\r\n if (session){\r\n course.Media = session.Media;\r\n course.ReleasedPhase = session.ReleasedPhase;\r\n course.PilotFunctions = session.PilotFunctions;\r\n course.TraineeEligibilty = session.TraineeEligibilty;\r\n }\r\n }\r\n\r\n function getSelectedPhase(course){\r\n var hasSelectedPhase = false;\r\n var phases = course.CrewCoursePhases;\r\n\r\n phases.forEach(function (phase, index, array) {\r\n phase.isFirst = index == 0;\r\n phase.isLast = (index + 1 == array.length);\r\n // Select the first InProgress & selected phase\r\n if (!hasSelectedPhase && phase.Status == \"InProgress\" && phase.isSelected) {\r\n phase.Selected = true;\r\n hasSelectedPhase = true;\r\n }\r\n });\r\n \r\n // Select the first InProgress phase\r\n if (!hasSelectedPhase && phases.some(x => x.Status == \"InProgress\")) {\r\n phases.find(x => x.Status == \"InProgress\").Selected = true;\r\n hasSelectedPhase = true;\r\n }\r\n\r\n if (!hasSelectedPhase) {\r\n phases.find(x => x.isFirst).Selected = true;\r\n }\r\n\r\n var selectedPhase = phases.find(x => x.Selected);\r\n\r\n return selectedPhase;\r\n }\r\n\r\n\r\n function filterTraineesByEligibility(dutyNo, dutyDay, course, trainingFlightIds, session, afterRefresh){\r\n // Trainee Eligiblity cases\r\n // 1. After refresh - Save newly fetched eligibility in session\r\n // 2. No refresh & Session exists - Get last fetched eligibility from session\r\n // 3. No refresh & No session exists - Rely on previously fetched eligibility (different duty - same course)\r\n\r\n var traineeEligibility = course.TraineeEligibilty;\r\n if(!afterRefresh && session && session.TraineeEligibilty){ \r\n traineeEligibility = session.TraineeEligibilty;\r\n }\r\n if(session) session.TraineeEligibilty = traineeEligibility; //update session eligibility\r\n \r\n // Get crew route trainees without any training records\r\n var trainees = getCrewRouteFlightTrainees(dutyNo, dutyDay, trainingFlightIds);\r\n \r\n var inactiveTrainees = trainees.filter(x => !course.CourseTrainees.some(z => z.CrewId == x.CrewId));\r\n\r\n //Exclude Non valid trainees\r\n var eligibleTraineeIds = Object.keys(traineeEligibility).filter(x => traineeEligibility[x] == \"NotStarted\" || traineeEligibility[x] == \"ValidPhase\" || traineeEligibility[x] == \"FailedCertificate\").map(Number);\r\n var eligibleTrainees = inactiveTrainees.filter(x => eligibleTraineeIds.includes(x.CrewId));\r\n eligibleTrainees.forEach(function (trainee) { trainee.EligibilityStatus = true });\r\n createNewPhaseTrainees(dutyNo, dutyDay, trainingFlightIds, course, eligibleTrainees);\r\n \r\n // Merge eligibleTrainees (inactive) with CourseTrainees (eligible & active)\r\n course.CourseTrainees.forEach(function (trainee) { trainee.EligibilityStatus = true });\r\n course.CourseTrainees.push(...eligibleTrainees);\r\n \r\n // Non eligible trainees\r\n var nonEligibleTrainees = inactiveTrainees.filter(x => !eligibleTraineeIds.includes(x.CrewId));\r\n course.NonEligibleTrainees = nonEligibleTrainees;\r\n\r\n nonEligibleTrainees.forEach(function (trainee) {\r\n trainee.EligibilityStatus = false;\r\n trainee.EligibilityDesc = traineeEligibility[trainee.CrewId];\r\n });\r\n \r\n // Result:\r\n // CourseTrainees = eligible trainees (active or new)\r\n // Non EligibleTrainees\r\n }\r\n\r\n /**\r\n * Create first phase foreach trainee\r\n * @param {object} groundDuty\r\n * @param {object} course\r\n * @param {array} trainees Eligible trainees that haven't yet started training\r\n */\r\n function createNewPhaseTrainees(dutyNo, dutyDay, trainingFlightIds, course, trainees) {\r\n var flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay).filter(f => trainingFlightIds.some(z => z == f.FlightId));\r\n //Match TrainingIndicators with PhaseDutyNos\r\n var crewCoursePhaseDutyNos = [];\r\n var crewrouteTrainingIndicators = [];\r\n course.CrewCoursePhases.forEach(function(coursePhase){\r\n crewCoursePhaseDutyNos = crewCoursePhaseDutyNos.concat(coursePhase.FlightTrainingIndicators);\r\n });\r\n flights.forEach(function(flight){\r\n crewrouteTrainingIndicators.push(flight.TrainingIndicatorId.toString());\r\n });\r\n\r\n var relatedDutyNos = crewCoursePhaseDutyNos.filter(x => crewrouteTrainingIndicators.includes(x));\r\n var relatedPhases = course.CrewCoursePhases.filter(x => x.FlightTrainingIndicators.some(fti => relatedDutyNos.includes(fti)));\r\n\r\n //From related phases, select first in order\r\n relatedPhases = $filter('orderBy')(relatedPhases, 'OrderNo');\r\n var firstPhase = relatedPhases[0];\r\n\r\n trainees.forEach(function (trainee) {\r\n trainee.Phases = [{\r\n PhaseId: firstPhase.PhaseId,\r\n PhaseStatus: \"InProgress\",\r\n RepeatRequestedItems: [],\r\n isSelected: true //selectedPhase\r\n }];\r\n })\r\n }\r\n \r\n function getCrewRouteFlightTrainees(dutyNo, dutyDay, trainingFlightIds) {\r\n var flights = FlightFactory.getFlightsByDutyNo(dutyNo, dutyDay).filter(f => trainingFlightIds.some(z => z == f.FlightId));\r\n\r\n var trainees = [];\r\n flights.forEach(function(flight){\r\n flight.crew.filter(x => x.IsTrainee && !x.isDHC).forEach(function(trainee){\r\n if(!trainees.some(x => x.id == trainee.id)){ //do not push duplicates : trainees that are in multiple flights\r\n trainees.push(trainee);\r\n }\r\n });\r\n });\r\n\r\n trainees.forEach(function(trainee){\r\n trainee.CrewId = trainee.id;\r\n trainee.Id = trainee.id;\r\n trainee.Name = trainee.name;\r\n trainee.AimsId = trainee.aimsId;\r\n\r\n });\r\n return trainees;\r\n }\r\n\r\n function calculatePhaseStatus(phase, course) {\r\n course.CourseTrainees.forEach(function (trainee) {\r\n var traineePhase = trainee.Phases.find(x => x.PhaseId == phase.PhaseId);\r\n if (traineePhase && traineePhase.PhaseStatus == \"InProgress\") {\r\n phase.Status = \"InProgress\";\r\n } else if (!traineePhase && phase.Status != \"InProgress\") {\r\n phase.Status = \"Pending\";\r\n } else if (traineePhase && traineePhase.PhaseStatus == \"Completed\" && phase.Status != \"InProgress\") {\r\n phase.Status = \"Completed\";\r\n }\r\n //Selected phase, If at least one trainee has it selected\r\n if(traineePhase && !phase.isSelected){\r\n phase.isSelected = traineePhase.isSelected;\r\n }\r\n });\r\n\r\n }\r\n \r\n function mergeSyllabusWithHistory(trainees, phases) {\r\n var flatSullabusItems = [];\r\n trainees.forEach(function (trainee) {\r\n trainee.Phases.forEach(function (phase) {\r\n phase.Sessions.forEach(function (session) {\r\n session.Items.forEach(function (item) {\r\n var flatItem = createFlatHistorySullabusItem(trainee, phase, session, item);\r\n flatSullabusItems.push(flatItem);\r\n });\r\n });\r\n });\r\n });\r\n\r\n\r\n phases.filter(x => x.Syllabus).forEach(function (phase, index, array) {\r\n phase.Syllabus.SyllabusItems.forEach(function (syllabusItem) {\r\n syllabusItem.History = flatSullabusItems.filter(item => item.ItemId == syllabusItem.Id);\r\n })\r\n });\r\n var hasPreviousSessions = flatSullabusItems.length > 0;\r\n\r\n return hasPreviousSessions;\r\n }\r\n\r\n function createFlatHistorySullabusItem(trainee, phase, session, item) {\r\n var flatItem =\r\n {\r\n CrewId: trainee.CrewId,\r\n PhaseId: phase.PhaseId,\r\n SessionId: session.SessionId,\r\n SessionComments: session.SessionComments,\r\n SubmissionDate: item.SubmissionDate,\r\n RepeatRequired: item.RepeatRequired,\r\n Tries: item.Tries,\r\n ItemId: item.SyllabusItemId,\r\n Grade: session.Grade,\r\n GradeType: session.GradeType,\r\n InstructorName: session.InstructorName,\r\n InstructorAimsId: session.InstructorAimsId\r\n };\r\n return flatItem;\r\n }\r\n\r\n /**\r\n * Add Session to Storage\r\n * @memberof FlightSessionFactory\r\n * @param {object} Session\r\n */\r\n function addSessionToStorage(session) {\r\n return IndexedDBService.add(objType, session);\r\n };\r\n\r\n /**\r\n * Update Session to Storage\r\n * @memberof FlightSessionFactory\r\n * @param {object} Session\r\n */\r\n function saveSessionToStorage(session) {\r\n return IndexedDBService.put(objType, session);\r\n };\r\n\r\n function submitSession(submittedSession, callback) {\r\n var traingingApiURL = apiUrl + '/Training/SubmitTraining';\r\n return $http.post(traingingApiURL, submittedSession, { 'Content-Type': 'application/json' })\r\n .then(callback);\r\n } \r\n\r\n function applyTraineeInfoToSession(course, courseId, day, dutyNo, dutyDay, callback, errorCallback){\r\n IndexedDBService.getById(objType, [day, courseId, dutyNo, dutyDay])\r\n .then(function (localSession) {\r\n var isNewSession = false;\r\n if (!localSession) {\r\n localSession = { \r\n courseId: courseId, \r\n day: day, \r\n dutyNo: dutyNo, \r\n dutyDay: dutyDay, \r\n trainees: [],\r\n TraineeEligibilty : course.TraineeEligibilty,\r\n CourseTrainees : course.CourseTrainees\r\n };\r\n isNewSession = true;\r\n } else {\r\n localSession.CourseTrainees = course.CourseTrainees;\r\n localSession.TraineeEligibilty = course.TraineeEligibilty;\r\n }\r\n\r\n if (isNewSession) {\r\n addSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n } else {\r\n saveSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n }\r\n }).catch(errorCallback);\r\n }\r\n return service;\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('grading', grading);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name grading\r\n * @restrict E\r\n * @description\r\n * Implementation of overall grading\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function grading() {\r\n function link(scope, element, attrs) {\r\n\r\n scope.getRemainingCharacters = getRemainingCharacters;\r\n scope.validateGrading = validateGrading;\r\n scope.filterValidTrainees = filterValidTrainees;\r\n scope.filterTrainee = filterTrainee;\r\n scope.saveComment = saveComment;\r\n \r\n scope.isDayGrading = scope.type == \"day\";\r\n scope.hasCertificateExam = scope.type == \"certificate\";\r\n\r\n scope.isCheck = scope.phase == \"Check\";\r\n\r\n //Separate DayGrading and ReleaseGrading \r\n scope.sessions = [];\r\n scope.trainees.filter(x => !x.Session.Absent).forEach(function(trainee){\r\n var session = scope.isDayGrading ? trainee.Session.DayGrading : trainee.Session.ReleaseGrading;\r\n session.Name = trainee.Name;\r\n session.AimsId = trainee.AimsId;\r\n session.CrewId = trainee.CrewId;\r\n\r\n if(scope.isDayGrading || (!scope.isDayGrading && !scope.isCheck && trainee.AvailableRelease) || (!scope.isDayGrading && scope.isCheck)){\r\n scope.sessions.push(session);\r\n }\r\n });\r\n\r\n \r\n\r\n scope.sessions.forEach(function(traineeSession){\r\n validateGrading(traineeSession);\r\n });\r\n filterValidTrainees();\r\n \r\n\r\n /**\r\n * Calculate remaining characters for comment input\r\n * @param {string} text \r\n * @param {number} max \r\n */\r\n function getRemainingCharacters(text, max) {\r\n if (typeof (text) === \"undefined\" || text === null) return '';\r\n if (typeof (max) === \"undefined\" || max === null || max < 0 || !max) max = 4000;\r\n var length = text.length;\r\n\r\n return 'characters left: ' + (max - length);\r\n }\r\n \r\n function validateGrading(trainee){\r\n trainee.isGradeValid = trainee.Grade != null && trainee.Grade != undefined;\r\n }\r\n\r\n function filterValidTrainees(){\r\n scope.sessions.forEach(function(traineeSession){\r\n traineeSession.isValid = traineeSession.isGradeValid && (!scope.settings.Competences.length || traineeSession.isCompetenceValid); \r\n });\r\n }\r\n\r\n function filterTrainee(){\r\n return function( trainee ) {\r\n var showTrainee = true;\r\n if(scope.selected){ //individual grading view: filter selected\r\n showTrainee = scope.selected.CrewId == trainee.CrewId\r\n }\r\n return showTrainee;\r\n };\r\n }\r\n\r\n function saveComment(){\r\n scope.commentInput();\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/grading.tpl.html',\r\n scope: {trainees:\"=\", settings:\"=\", type:\"@\", phase:\"=\", selected:\"=\", commentInput: \"&onCommentInput\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('GroundCourseCtrl', GroundCourseCtrl);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name GroundCourseCtrl\r\n * @description \r\n *\r\n * @ngInject\r\n */\r\n function GroundCourseCtrl($route, $filter, $timeout, TrainingSessionFactory, CrewRouteFactory, FlightFactory, GroundDutyFactory, CourseFactory, $scope, $location, $routeParams) {\r\n $scope.gotoCourse = gotoCourse;\r\n $scope.gotoGroundDuty = gotoGroundDuty;\r\n $scope.stickySelectedTrainee = stickySelectedTrainee;\r\n $scope.toggleView = toggleView;\r\n\r\n $scope.refreshCourse = refresh;\r\n $scope.courseTrainees = [];\r\n\r\n var courseId = Number($routeParams.courseId);\r\n var groundDutyId = Number($routeParams.dutyId);\r\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(groundDutyId);\r\n\r\n $scope.isEdit = false;\r\n $scope.loading = false;\r\n $scope.allAbsent = false;\r\n $scope.refreshSuccess = true; //show refresh icon\r\n\r\n if (!groundDuty) {\r\n // go to dashboard if no groundDuty\r\n $location.path(\"/\");\r\n } else {\r\n var date = groundDuty.DutyDateS;\r\n\r\n if (groundDuty.RelatedGroundDuties) {\r\n var courses = GroundDutyFactory.getGroundDutyActiveCourses(groundDutyId);\r\n if (courses.length) {\r\n CourseFactory.getCourseFromStorage(courseId, function(dutyCourse) {\r\n $scope.dutyCourse = dutyCourse;\r\n initCourse(false);\r\n });\r\n }\r\n }\r\n $scope.groundDuty = groundDuty;\r\n $scope.groundDutyId = groundDutyId;\r\n }\r\n\r\n\r\n function initCourse(afterRefresh) {\r\n var courseId = $scope.dutyCourse.Id;\r\n TrainingSessionFactory.getSession(courseId, date, groundDutyId, afterRefresh, function(course) {\r\n if (course && !course.HasLimitedInfo) {\r\n $scope.availableCourse = true;\r\n\r\n $scope.selectedPhase = course.selectedPhase;\r\n $scope.trainees = course.CourseTrainees;\r\n course.SequenceWarning = false;\r\n }\r\n\r\n $scope.course = course;\r\n manageCourseStatus($scope.dutyCourse, course, afterRefresh);\r\n toggleView('History'); //default\r\n\r\n\r\n if ($scope.trainees) {\r\n applyAttendanceFromGroundDuty(groundDuty, $scope.trainees);\r\n stickySelectedTrainee();\r\n if($scope.trainees.length && !$scope.trainees.some(x => !x.Session.Absent)){\r\n $scope.allAbsent = true;\r\n }\r\n\r\n //Check for status change (new trainees found on a submitted session (reset) || failed certificate trainees want to retake the test)\r\n if (afterRefresh && $scope.isCourseComplete && $scope.trainees.length) {\r\n GroundDutyFactory.setCoursePending(groundDutyId, courseId);\r\n $scope.isCourseComplete = false;\r\n $route.reload();\r\n }\r\n }\r\n\r\n $scope.reload = false;\r\n $timeout(function() {\r\n $scope.reload = true;\r\n }, 100);\r\n\r\n });\r\n }\r\n\r\n function applyAttendanceFromGroundDuty(groundDuty, trainees){\r\n groundDuty.Trainees.forEach(function(related){\r\n related.CrewMembers.forEach(function(crew){\r\n var trainee = trainees.find(x => x.CrewId == crew.Id);\r\n if(trainee){\r\n trainee.Session.Absent = crew.Absent;\r\n }\r\n });\r\n });\r\n }\r\n\r\n function gotoCourse(course) {\r\n $location.path('/course/' + course.Id + '/' + groundDuty.DutyDateS + \"/\" + groundDuty.Id);\r\n }\r\n\r\n function refresh() {\r\n $scope.loading = true;\r\n\r\n if ($scope.isOffline) {\r\n $timeout(function() {\r\n $scope.loading = false;\r\n }, 100);\r\n $scope.refreshSuccess = false;\r\n $scope.availableCourseInfo = false;\r\n $scope.refreshErrorMsg = \"Online mode is required in order to get course. Please connect to the internet and try again.\";\r\n } else {\r\n CourseFactory.updateCourseInfo($scope.dutyCourse.Id, groundDutyId, function() {\r\n $scope.loading = false;\r\n $scope.refreshSuccess = true;\r\n $scope.availableCourseInfo = true;\r\n\r\n initCourse(true);\r\n $scope.reload = false;\r\n $timeout(function() {\r\n $scope.reload = true;\r\n }, 100);\r\n\r\n },\r\n function() {\r\n $scope.loading = false;\r\n $scope.refreshSuccess = false;\r\n $scope.availableCourseInfo = false;\r\n $scope.refreshErrorMsg = \"Something went wrong! Please Try again.\";\r\n },\r\n function(error) {\r\n console.log(error);\r\n $scope.loading = false;\r\n $scope.refreshSuccess = false;\r\n $scope.availableCourseInfo = false;\r\n\r\n $scope.refreshErrorMsg = \"Oops! Something went wrong!\";\r\n\r\n if (error.data.errorMessage) {\r\n $scope.refreshErrorMsg = error.data.errorMessage;\r\n }\r\n }\r\n )\r\n }\r\n }\r\n\r\n\r\n function manageCourseStatus(dutyCourse, course, afterRefresh) {\r\n // COMPLETED : has been submitted\r\n var isCourseComplete = courses.find(x => x.CourseId == dutyCourse.Id && x.Status == \"Completed\") != null;\r\n\r\n // NEEDS SUBMIT : 1 hour has passed since the end of the course\r\n var now = moment.utc();\r\n if (!dutyCourse.IsCompleted) {\r\n var needsSubmit = false;\r\n var fetched = moment.utc(groundDuty.DutyEnd);\r\n var duration = moment.duration(now.diff(fetched)).asHours();\r\n if (duration > 1) {\r\n needsSubmit = true;\r\n }\r\n }\r\n\r\n // LIMITED : no info available\r\n var isCourseLimited = !course || course.HasLimitedInfo || (course.HasLimitedSession && !afterRefresh);\r\n\r\n // OUTDATED : NeedsRefresh || 18 hours since last refresh\r\n var isCourseOutdated = false;\r\n if (course && course.FetchedTime) {\r\n var now = moment.utc();\r\n var fetched = moment.utc(course.FetchedTime);\r\n var duration = moment.duration(now.diff(fetched)).asHours();\r\n \r\n if (duration > 18 || course.NeedsRefresh ) {\r\n isCourseOutdated = true;\r\n }\r\n }\r\n\r\n $scope.headerMsg = \"Refresh Course\";\r\n if (isCourseLimited) $scope.headerMsg = \"Fetch Course\";\r\n\r\n\r\n $scope.hasPendingTraining = !isCourseComplete;\r\n $scope.hasUnsetTraining = needsSubmit;\r\n $scope.isCourseLimited = isCourseLimited;\r\n $scope.isCourseComplete = isCourseComplete;\r\n $scope.isCourseOutdated = isCourseOutdated;\r\n $scope.hasNotifications = isCourseLimited || isCourseOutdated || isCourseComplete;\r\n }\r\n\r\n function gotoGroundDuty() {\r\n $location.path('/groundDuty/' + groundDutyId);\r\n }\r\n\r\n function stickySelectedTrainee(){\r\n var availableRelease = $scope.selectedPhase.ModuleType==\"Check\" || !$scope.trainees.filter(x => !x.Session.Absent).some(tr => tr.Session.Items.some(i => i.Status == \"Pending\"));\r\n var individualGrading = $scope.trainees && $scope.trainees.filter(x => !x.Session.Absent).length && $scope.selectedPhase && \r\n ( ($scope.selectedPhase.Syllabus && $scope.selectedPhase.Syllabus.IsGradable) \r\n || $scope.selectedPhase.HasDayGrading \r\n || ($scope.selectedPhase.HasReleaseGrading && availableRelease)\r\n || RequiresTraineeSignature());\r\n\r\n if(individualGrading){\r\n if($scope.trainees.filter(x => !x.Session.Absent).find(x => x.Session.selected)){\r\n $scope.selectedTrainee = $scope.trainees.filter(x => !x.Session.Absent).find(x => x.Session.selected);\r\n }\r\n else{\r\n $scope.selectedTrainee = $scope.trainees.filter(x => !x.Session.Absent)[0];\r\n }\r\n }\r\n else{\r\n $scope.selectedTrainee = null;\r\n }\r\n\r\n if($scope.selectedTrainee) $scope.selectedTraineeBadge = {CrewId:$scope.selectedTrainee.CrewId};\r\n }\r\n\r\n function RequiresTraineeSignature(){\r\n // End of session signature\r\n var endOfSessionSignature = $scope.selectedPhase.DayGrading.TraineeSignature;\r\n\r\n // End of module signature\r\n var endOfModuleSignature = $scope.course.ReleasedPhase && $scope.selectedPhase.ReleaseGrading.TraineeSignature;\r\n\r\n return endOfSessionSignature || endOfModuleSignature;\r\n }\r\n\r\n function toggleView(mode){\r\n $scope.viewMode = mode;\r\n }\r\n\r\n }\r\n})();","(function () {\r\n\r\n a3_pilot_reports.directive('media', media);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name ground Media\r\n * @restrict E\r\n * @description\r\n * Initialize panel with media of training selection, aircraft types & synthetic devices\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function media($location, CourseFactory) {\r\n function link(scope, attrs) {\r\n\r\n scope.addAircraftRow = addAircraftRow;\r\n scope.removeAircraftRow = removeAircraftRow;\r\n \r\n scope.isObjectEmpty = isObjectEmpty;\r\n\r\n initializeMedia();\r\n\r\n function isObjectEmpty(obj){\r\n return Object.keys(obj).length === 0;\r\n }\r\n\r\n function initializeMedia(){\r\n if (scope.course) {\r\n if(!scope.course.Media){\r\n // Create Media object\r\n scope.course.Media = {\r\n inputAircrafts: [],\r\n selectedAircraft: {\r\n selection: undefined\r\n },\r\n selectedDevice: {\r\n selection: undefined\r\n },\r\n radioModel: \"\",\r\n };\r\n \r\n }\r\n \r\n if(scope.course.Media.radioModel == \"\" || mediaRemoved()){\r\n //Auto select media on init or if selection was removed in admin settings\r\n if(scope.selectedPhase.InSimulator) scope.course.Media.radioModel = \"Simulator\";\r\n if(scope.selectedPhase.InAircraft) scope.course.Media.radioModel = \"Aircraft\";\r\n if(scope.selectedPhase.InClassroom) scope.course.Media.radioModel = \"Classroom\";\r\n }\r\n\r\n if(scope.selectedPhase.InSimulator){\r\n //Auto select device on init\r\n if(!scope.course.Media.selectedDevice.selection && scope.course.SyntheticDevices && !isObjectEmpty(scope.course.SyntheticDevices)){\r\n scope.course.Media.selectedDevice.selection = Object.keys(scope.course.SyntheticDevices)[0];\r\n }\r\n\r\n //Remove selection if no devices\r\n if(!scope.course.SyntheticDevices || isObjectEmpty(scope.course.SyntheticDevices)){\r\n scope.course.Media.selectedDevice.selection = undefined;\r\n }\r\n }\r\n }\r\n }\r\n \r\n function mediaRemoved(){\r\n return (scope.course.Media.radioModel == \"Simulator\" && !scope.selectedPhase.InSimulator) ||\r\n (scope.course.Media.radioModel == \"Aircraft\" && !scope.selectedPhase.InAircraft) ||\r\n (scope.course.Media.radioModel == \"Classroom\" && !scope.selectedPhase.InClassroom);\r\n }\r\n\r\n function addAircraftRow(){\r\n var aircraftTypes = scope.course.AircraftTypes;\r\n if(scope.course.Media.selectedAircraft.selection != undefined && aircraftTypes && aircraftTypes.includes(scope.course.Media.selectedAircraft.selection) && (!scope.course.Media.inputAircrafts || !scope.course.Media.inputAircrafts.includes(scope.course.Media.selectedAircraft.selection))){\r\n //Add to selected\r\n if(!scope.course.Media.inputAircrafts){\r\n scope.course.Media.inputAircrafts = [];\r\n }\r\n scope.course.Media.inputAircrafts.push(scope.course.Media.selectedAircraft.selection);\r\n \r\n //Remove from options\r\n scope.course.AircraftTypes = aircraftTypes.filter(function(aircraft){\r\n return aircraft != scope.course.Media.selectedAircraft.selection;\r\n });\r\n \r\n //Clear \r\n scope.course.Media.selectedAircraft.selection = undefined;\r\n\r\n }\r\n }\r\n \r\n function removeAircraftRow(aircraft){\r\n //Remove from selected\r\n var acIndex = scope.course.Media.inputAircrafts.indexOf(aircraft);\r\n scope.course.Media.inputAircrafts.splice(acIndex, 1);\r\n \r\n //Add back to options\r\n scope.course.AircraftTypes.push(aircraft);\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/Training/media.tpl.html\",\r\n scope : false,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('ModuleHistoryCtrl', ModuleHistoryCtrl);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ModuleHistoryCtrl\r\n * @description \r\n *\r\n * @ngInject\r\n */\r\n function ModuleHistoryCtrl($scope, $routeParams, TrainingSessionFactory, CourseFactory, FlightSessionFactory, $location) {\r\n $scope.rightScroll = rightScroll;\r\n $scope.leftScroll = leftScroll;\r\n $scope.selectedTrainee = selectedTrainee;\r\n $scope.selectedSession = selectedSession;\r\n $scope.gotoCourse = gotoCourse; \r\n\r\n var isGround = false;\r\n if($routeParams.dutyId) {\r\n isGround = true;\r\n var courseId = Number($routeParams.courseId);\r\n var dutyId = Number($routeParams.dutyId);\r\n var date = $routeParams.date;\r\n var phaseId = Number($routeParams.phaseId);\r\n }\r\n else {\r\n var courseId = Number($routeParams.courseId);\r\n var dutyNo = Number($routeParams.dutyNo);\r\n var dutyDay = Number($routeParams.dutyDay);\r\n var date = $routeParams.date;\r\n var phaseId = Number($routeParams.phaseId);\r\n }\r\n\r\n CourseFactory.getCourseFromStorage(courseId, function (course) {\r\n $scope.phase = course.CrewCoursePhases.find(x => x.PhaseId == phaseId);\r\n $scope.course = course; \r\n if(isGround) {\r\n TrainingSessionFactory.getSessionTrainees(courseId, date, dutyId, function (trainees) { \r\n initHistory(trainees); \r\n });\r\n }\r\n else {\r\n FlightSessionFactory.getSessionTrainees(courseId, date, dutyNo, dutyDay, function (trainees) { \r\n initHistory(trainees); \r\n });\r\n }\r\n });\r\n \r\n function initHistory(trainees) {\r\n if (trainees && trainees.length) {\r\n trainees.forEach(function (trainee) {\r\n trainee.HistoryPhase = trainee.Phases.find(x => x.PhaseId == phaseId);\r\n });\r\n $scope.historyTrainees = setHistoryTrainees(trainees);\r\n\r\n $scope.selectedTraineeBadge = {\r\n crewId: trainees[0].CrewId,\r\n traineeSessionId: trainees[0].HistoryPhase.Sessions[0].Id\r\n };\r\n\r\n $scope.selectedSubmittedSessionBadge = {\r\n sessionId: trainees[0].HistoryPhase.Sessions[0].SessionId\r\n };\r\n }\r\n }\r\n\r\n function setHistoryTrainees(trainees){\r\n var historyTrainees = trainees.filter(x => x.HistoryPhase && x.HistoryPhase.Sessions && !x.Session.Absent);\r\n\r\n historyTrainees.forEach(function(trainee){\r\n\r\n trainee.HistoryPhase.hasSectors = trainee.HistoryPhase.Sessions.some(x => x.Sectors && x.Sectors.length>0);\r\n trainee.HistoryPhase.Sessions.forEach(function(session){\r\n session.hasDayGrading = session.DayGrading.Comments || (session.DayGrading.GradeType != 'NotSet' && session.DayGrading.Grade) || session.DayGrading.Competences.length>0;\r\n session.hasReleaseGrading = session.ReleaseGrading.Comments || (session.ReleaseGrading.GradeType != 'NotSet' && session.ReleaseGrading.Grade) || session.ReleaseGrading.Competences.length>0;\r\n session.AcTypes = [...new Set(session.Sectors.map(ses => ses.AcType))];\r\n\r\n //GroupBy AcType\r\n session.SectorsByAcType = [];\r\n session.AcTypes.forEach(function(acType){\r\n var group = {\r\n AcType: acType,\r\n Sectors: session.Sectors.filter(x => x.AcType == acType)\r\n };\r\n session.SectorsByAcType.push(group);\r\n });\r\n });\r\n\r\n setTraineeSummary(trainee.HistoryPhase);\r\n \r\n });\r\n\r\n return historyTrainees;\r\n }\r\n\r\n function setTraineeSummary(phase){\r\n var sectorSummary = [];\r\n var totalSectors = 0;\r\n\r\n //Unique ac types of all sessions\r\n var allAcTypes = [];\r\n phase.Sessions.forEach(function(session){\r\n allAcTypes = allAcTypes.concat(session.AcTypes);\r\n });\r\n\r\n allAcTypes = [...new Set(allAcTypes)];\r\n\r\n //Group by ac type\r\n allAcTypes.forEach(function(acType){\r\n var sectors = [];\r\n phase.Sessions.forEach(function(session){\r\n sectors = sectors.concat(session.Sectors.filter(x => x.AcType == acType));\r\n });\r\n\r\n var sectorGroup = {\r\n AcType: acType,\r\n Sectors: sectors\r\n };\r\n\r\n totalSectors = totalSectors + sectors.length;\r\n sectorSummary.push(sectorGroup);\r\n });\r\n\r\n\r\n phase.SectorSummary = sectorSummary;\r\n phase.TotalSectors = totalSectors;\r\n\r\n }\r\n\r\n function selectedTrainee() { \r\n return function( trainee ) {\r\n var showSession = false;\r\n if (trainee.CrewId === $scope.selectedTraineeBadge.crewId){\r\n showSession = true;\r\n }\r\n return showSession;\r\n };\r\n }\r\n\r\n function selectedSession() { \r\n return function( historyTrainee ) {\r\n var showSession = false;\r\n if (historyTrainee.SessionId === $scope.selectedSubmittedSessionBadge.sessionId){\r\n showSession = true;\r\n }\r\n return showSession;\r\n };\r\n } \r\n\r\n function leftScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\r\n }\r\n \r\n function rightScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\r\n }\r\n\r\n function gotoCourse() {\r\n if(isGround) {\r\n $location.path('/groundcourse/' + Number($routeParams.courseId) + '/' + Number($routeParams.dutyId) + '/' + $routeParams.date);\r\n }\r\n else {\r\n $location.path('/flightcourse/' + Number($routeParams.courseId) + '/' + Number($routeParams.dutyNo) + '/' + Number($routeParams.dutyDay) + '/' + $routeParams.date);\r\n }\r\n \r\n }\r\n\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('nonEligibleTrainees', nonEligibleTrainees);\r\n\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name nonEligibleTrainees\r\n * @restrict E\r\n * @description\r\n * Show trainees that are not eligible for this training session\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject \r\n */\r\n function nonEligibleTrainees(FlightSessionFactory, $routeParams) {\r\n function link(scope) {\r\n\r\n scope.categories = setCategories();\r\n\r\n //Collect duty trainees\r\n var dutyTrainees = [];\r\n if(scope.groundDuty){\r\n scope.groundDuty.Trainees.forEach(function(related) {\r\n related.CrewMembers.forEach(function(trainee) {\r\n dutyTrainees.push(trainee);\r\n });\r\n });\r\n } \r\n else{\r\n var date = $routeParams.date;\r\n var dutyNo = Number($routeParams.dutyNo);\r\n var dutyDay = Number($routeParams.dutyDay);\r\n var crewRouteCourse = scope.crewRouteDuty.Courses.find(x => x.CourseId == scope.course.Id && new moment(x.Date).isSame(date));\r\n var dutyTrainees = FlightSessionFactory.getCrewRouteFlightTrainees(dutyNo, dutyDay, crewRouteCourse.TrainingFlightIds)\r\n }\r\n\r\n if(scope.course && scope.course.CourseTrainees){\r\n categorizeTrainee(dutyTrainees);\r\n }\r\n\r\n \r\n scope.dutyTrainees = dutyTrainees;\r\n\r\n function setCategories() {\r\n var parallelMessage = \"Trainees may have already completed this module\";\r\n var sequentialMessage = \"Trainees have either completed this module or are not yet ready to start it\";\r\n\r\n return [\r\n {\r\n title:\"InvalidPhase\",\r\n msg: scope.course.isParallel ? parallelMessage : sequentialMessage,\r\n trainees:[],\r\n all:false\r\n },\r\n {\r\n title:\"Submitted\",\r\n msg:\"Trainees have already been submitted\",\r\n trainees:[],\r\n all:false\r\n },\r\n {\r\n title:\"RecurrentPeriod\",\r\n msg:\"Trainees have completed the course earlier\",\r\n trainees:[],\r\n all:false\r\n },\r\n {\r\n title:\"InvalidRole\",\r\n msg: \"For this training, cabin crew trainees can only be assessed by a cabin crew instructor\",\r\n trainees:[],\r\n all:false\r\n }\r\n ];\r\n \r\n }\r\n \r\n function categorizeTrainee(dutyTrainees){\r\n var allEligibilityTrainees = scope.course.CourseTrainees.concat(scope.course.NonEligibleTrainees);\r\n dutyTrainees.forEach(function(dutyTrainee) {\r\n var courseTrainee = allEligibilityTrainees.find(x => x.CrewId == dutyTrainee.Id);\r\n if(courseTrainee){\r\n // if (courseTrainee.ActivePhaseStatus == 'Completed') {\r\n // scope.categories.find(x => x.title==\"Completed\").trainees.push(dutyTrainee);\r\n // }\r\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc=='AlreadySubmitted') {\r\n scope.categories.find(x => x.title ==\"Submitted\").trainees.push(dutyTrainee);\r\n }\r\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc=='InvalidPhase') {\r\n scope.categories.find(x => x.title==\"InvalidPhase\").trainees.push(dutyTrainee);\r\n }\r\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc=='CooldownPending') {\r\n scope.categories.find(x => x.title ==\"RecurrentPeriod\").trainees.push(dutyTrainee);\r\n }\r\n if (!courseTrainee.EligibilityStatus && courseTrainee.EligibilityDesc=='InvalidRole') {\r\n scope.categories.find(x => x.title ==\"InvalidRole\").trainees.push(dutyTrainee);\r\n }\r\n }\r\n }); \r\n\r\n var allCategory = scope.categories.find(x => x.trainees.length == dutyTrainees.length); //all trainees in same category\r\n if(allCategory){\r\n allCategory.all = true;\r\n }\r\n }\r\n\r\n\r\n \r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: true,\r\n templateUrl: \"views/Training/non-eligible-trainees.tpl.html\",\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('NotificationModalCtrl', NotificationModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name NotificationModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\r\n\r\n function NotificationModalCtrl($scope, $uibModalInstance){\r\n $scope.close = close;\r\n \r\n /**\r\n * Close the modal\r\n * @memberof NotificationModalCtrl\r\n */\r\n function close(){\r\n $uibModalInstance.close( $scope.success);\r\n }\r\n }\r\n})();","(function () {\r\n\r\n a3_pilot_reports.directive('notifications', notifications);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name notifications\r\n * @restrict E\r\n * @description\r\n * Initialize panel with information messages about session's status and necessary actions\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function notifications($routeParams) {\r\n function link(scope) {\r\n var info = {\r\n msg: \"\",\r\n border: \"\",\r\n text: \"\",\r\n showHistory: false\r\n };\r\n\r\n var date = $routeParams.date;\r\n scope.filterSession = filterSession;\r\n scope.selectSession = selectSession;\r\n scope.historyAvailable = false;\r\n\r\n //If already submitted : show submitted sessions menu and select first\r\n if(scope.course.SubmittedSessions && scope.course.SubmittedSessions.length){\r\n var submittedDay = scope.course.SubmittedSessions[0].DutyDay;\r\n var isSame = moment(date).isSame(submittedDay);\r\n if(isSame){\r\n scope.course.historyAvailable = true;\r\n scope.historyAvailable = true;\r\n scope.selectedSubmittedSession = { \r\n sessionId: scope.course.SubmittedSessions[0].SessionId\r\n }; \r\n }\r\n }\r\n\r\n // 1. Check if session has been already submitted \r\n var isCourseComplete = scope.isCourseComplete\r\n if(isCourseComplete){\r\n\r\n info = {\r\n msg : \"Training form already submitted for this day.\",\r\n border : \"border-left-orange\",\r\n text : \"text-orange\",\r\n showHistory: true //show what was submitted in read-only view\r\n };\r\n }\r\n\r\n // 2. Check if course is Outdated\r\n var isCourseOutdated = scope.isCourseOutdated;\r\n if (isCourseOutdated) {\r\n info = {\r\n msg : \"You have an outdated version of this course. Please Refresh Course.\",\r\n border : \"border-left-orange\",\r\n text : \"text-orange\",\r\n showHistory: false\r\n }\r\n }\r\n\r\n // 3. Check if course needs an initial fetch\r\n var isCourseLimited = scope.isCourseLimited;\r\n if (isCourseLimited && !isCourseComplete) {\r\n isCourseLimited = true;\r\n info = {\r\n msg : \"You need to perform an initial fetch to receive all available information.\",\r\n border : \"border-left-blue\",\r\n text : \"text-blue\",\r\n showHistory: false\r\n }\r\n }\r\n\r\n // Result\r\n scope.info = info;\r\n\r\n /**\r\n * Filter submitted sessions based on selected from the top menu\r\n * @returns if session is currently selected\r\n */\r\n function filterSession() { \r\n return function( traineeSession ) {\r\n var showSessionTrainees = false;\r\n if (traineeSession.SessionId === scope.selectedSubmittedSession.sessionId){\r\n showSessionTrainees = true;\r\n }\r\n return showSessionTrainees;\r\n };\r\n }\r\n\r\n function selectSession(sessionId){\r\n scope.selectedSubmittedSession.sessionId = sessionId;\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/Training/notifications.tpl.html\",\r\n scope : false,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function () {\r\n\r\n a3_pilot_reports.directive('pilotFunction', pilotFunction);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name pilotFunction\r\n * @restrict E\r\n * @description\r\n * Initialize panel with pm/pf and seating info : Only for pilots in flight courses\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function pilotFunction(FlightFactory, UserFactory, $timeout) {\r\n function link(scope, attrs, $routeParams) {\r\n\r\n scope.selectSeat = selectSeat;\r\n scope.selectFunction = selectFunction;\r\n scope.reloadPilotFunction = false;\r\n\r\n var date = scope.crewRouteDuty.date;\r\n var courseId = scope.dutyCourse.Id;\r\n var crewRouteCourse = scope.crewRouteDuty.Courses.find(x => x.CourseId == courseId && new moment(x.Date).isSame(date));\r\n\r\n var trainingFlightIds = crewRouteCourse.TrainingFlightIds;\r\n\r\n var trainingFlights = [];\r\n trainingFlightIds.forEach(function(flightId){\r\n trainingFlights.push(FlightFactory.getFlightFromStorage(flightId));\r\n });\r\n \r\n \r\n var instructor = UserFactory.getUser();\r\n var instructorTrainingIndicator = trainingFlights[0].crew.find(x => x.id == instructor.id).TrainingIndicatorCode;\r\n var traineeTrainingIndicator = instructorTrainingIndicator.toLowerCase();\r\n\r\n scope.flights = trainingFlights;\r\n \r\n trainingFlights.forEach(function(flight){\r\n flight.hasMultipleTrainees = flight.crew.filter(x => x.TrainingIndicatorCode && x.TrainingIndicatorCode == traineeTrainingIndicator && !x.isDHC && x.IsTrainee).length>1;\r\n });\r\n\r\n initializePilotFunctions();\r\n\r\n //Operating pilots can change in each sector\r\n //When multiple trainees, instructor is not operating\r\n trainingFlights.forEach(function(flight){\r\n //Assign operatingPilots on each flight\r\n flight.operatingPilots = flight.hasMultipleTrainees ? scope.course.PilotFunctions.filter(x => !x.IsInstructor)\r\n : scope.course.PilotFunctions.filter(x => !x.Sectors.find(sec => sec.FlightId == flight.FlightId).NonApplicable);\r\n });\r\n \r\n \r\n\r\n function initializePilotFunctions(){\r\n var PilotFunctions = [];\r\n if(scope.course && scope.trainees.length){\r\n //Create trainee info\r\n scope.trainees.forEach(function(trainee){\r\n nameArray = trainee.Name.split(/[ ]+/);\r\n var pilot = {\r\n CrewId : trainee.CrewId,\r\n AimsId : trainee.AimsId,\r\n Name : trainee.Name,\r\n FirstName: nameArray[1],\r\n LastName: nameArray[0],\r\n IsInstructor: false,\r\n Sectors: createLegInfo(trainee.CrewId, trainee)\r\n };\r\n\r\n PilotFunctions.push(pilot);\r\n });\r\n\r\n //Create instructor info\r\n var nameArray = instructor.name.split(/[ ]+/);\r\n\r\n var pilot = {\r\n CrewId : instructor.id,\r\n AimsId : instructor.aimsId,\r\n Name : instructor.name,\r\n FirstName: nameArray[1],\r\n LastName: nameArray[0],\r\n IsInstructor: true,\r\n Sectors : createLegInfo(instructor.id) \r\n };\r\n \r\n PilotFunctions.push(pilot);\r\n\r\n //make only one pilot flying\r\n trainingFlights.forEach(function(flight){\r\n var sectors = [];\r\n PilotFunctions.forEach(function(pilot){\r\n var pilotSector = pilot.Sectors.find(sec => sec.FlightId == flight.FlightId);\r\n if(pilotSector && !pilotSector.NonApplicable){\r\n sectors.push(pilotSector); \r\n }\r\n })\r\n sectors[0].isPM = true;\r\n });\r\n\r\n //Apply existing saved info\r\n if(scope.course.PilotFunctions){\r\n PilotFunctions.forEach(function(pilot){\r\n var existingInfo = scope.course.PilotFunctions.find(x => x.CrewId == pilot.CrewId);\r\n if(existingInfo){\r\n\r\n pilot.Seat = existingInfo.Seat;\r\n\r\n var sectors = [];\r\n pilot.Sectors.forEach(function(incomingSector){\r\n var existingSector = existingInfo.Sectors.find(x => x.FlightId == incomingSector.FlightId && x.Arrival == incomingSector.Arrival && x.Departure == incomingSector.Departure);\r\n \r\n if(existingSector){\r\n var sector = deepCopy(existingSector);\r\n sector.NonApplicable = incomingSector.NonApplicable;\r\n sector.SeatOptions = incomingSector.SeatOptions;\r\n\r\n if(!incomingSector.SeatOptions.includes(sector.Seat)){\r\n sector.Seat = incomingSector.Seat;\r\n }\r\n\r\n sectors.push(sector);\r\n }\r\n else{\r\n sectors.push(incomingSector); \r\n }\r\n });\r\n\r\n pilot.Sectors = sectors;\r\n }\r\n })\r\n }\r\n \r\n scope.reloadPilotFunction = true;\r\n }\r\n scope.course.PilotFunctions = PilotFunctions;\r\n }\r\n \r\n\r\n scope.instructor = instructor;\r\n\r\n function deepCopy(originalObject) {\r\n return JSON.parse(JSON.stringify(originalObject));\r\n }\r\n\r\n function createLegInfo(crewId, trainee){\r\n var legs = [];\r\n\r\n var traineeSeatOptions = ['Right', 'Left'];\r\n var instructorSeatOptions = ['Right', 'Left', 'Jumpseat'];\r\n\r\n\r\n trainingFlights.forEach(function(flight){\r\n\r\n var leg = {\r\n CrewId : crewId,\r\n FlightId : flight.FlightId,\r\n Departure: flight.Departure,\r\n Arrival: flight.Arrival,\r\n isPM: false,\r\n NonApplicable : trainee ? false : flight.hasMultipleTrainees,\r\n SeatOptions: trainee ? traineeSeatOptions : instructorSeatOptions\r\n };\r\n\r\n if(trainee){\r\n leg.Seat = flight.hasMultipleTrainees ? undefined : 'Right';\r\n }\r\n else{\r\n leg.Seat = flight.hasMultipleTrainees ? 'Jumpseat' : 'Left'; \r\n }\r\n\r\n legs.push(leg);\r\n });\r\n\r\n if(trainee){\r\n // Get only the flights trainee is a participant of\r\n var traineeFlightIds = [];\r\n trainingFlights.forEach(function(flight){\r\n var crewMember = flight.crew.find(x => x.id == trainee.CrewId);\r\n if(crewMember && crewMember.TrainingIndicatorCode && crewMember.TrainingIndicatorCode == traineeTrainingIndicator){\r\n traineeFlightIds.push(flight.FlightId);\r\n }\r\n });\r\n\r\n var nonActiveLegs = legs.filter(l => !traineeFlightIds.includes(l.FlightId));\r\n nonActiveLegs.forEach(function(nonActiveLeg){\r\n nonActiveLeg.NonApplicable = true;\r\n });\r\n }\r\n\r\n return legs;\r\n }\r\n\r\n function selectSeat(flight, pilot, leg){\r\n if(flight.hasMultipleTrainees){\r\n var otherPilotId = flight.operatingPilots.find(x => x.CrewId != pilot.CrewId).CrewId;\r\n var otherPilot = scope.course.PilotFunctions.find(x => x.CrewId == otherPilotId);\r\n var otherSector = otherPilot.Sectors.find(x => x.FlightId == leg.FlightId);\r\n if(leg.Seat == 'Left'){otherSector.Seat = 'Right'}\r\n else{otherSector.Seat = 'Left'}\r\n }\r\n }\r\n\r\n function selectFunction(flight, pilot, leg){\r\n var otherPilotId = flight.operatingPilots.find(x => x.CrewId != pilot.CrewId).CrewId;\r\n var otherPilot = scope.course.PilotFunctions.find(x => x.CrewId == otherPilotId);\r\n var otherSector = otherPilot.Sectors.find(x => x.FlightId == leg.FlightId);\r\n\r\n if(leg.isPM){otherSector.isPM = false;}\r\n else{ otherSector.isPM = true;}\r\n }\r\n\r\n \r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/Training/pilotFunctionPanel.tpl.html\",\r\n scope : false,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('releasableModule', releasableModule);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name releasableModule\r\n * @restrict E\r\n * @description\r\n * Implementation of releasable Module\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function releasableModule(TrainingSessionFactory, $uibModal, $location) {\r\n function link(scope) {\r\n scope.Submit = Submit;\r\n scope.selectedTrainee = selectedTrainee;\r\n scope.toggleTrainee = toggleTrainee;\r\n scope.getRemainingCharacters = getRemainingCharacters;\r\n scope.leftScroll = leftScroll;\r\n scope.rightScroll = rightScroll;\r\n scope.validateGrading = validateGrading;\r\n scope.getTraineeClass = getTraineeClass;\r\n scope.openTraineeSignature = openTraineeSignature;\r\n scope.resetSignature = resetSignature;\r\n scope.close = close;\r\n\r\n var isGround = scope.groundDuty != null && scope.groundDuty != null;\r\n \r\n var phaseId = scope.course.SubmittedSessions[0].PhaseId;\r\n var phase = scope.course.CrewCoursePhases.find(x => x.PhaseId == phaseId);\r\n scope.settings = phase.ReleaseGrading;\r\n \r\n //Collect all trainee sessions that could be released\r\n var trainees = [];\r\n scope.course.SubmittedSessions.forEach(function (session) {\r\n session.TraineesSessions.filter(x => x.CouldBeReleased).forEach(function (traineeSession) {\r\n traineeSession.RadioModel = true; //set default realease option true\r\n trainees.push(traineeSession);\r\n });\r\n });\r\n\r\n if(trainees.length){\r\n initializeTrainees(trainees, phase);\r\n }\r\n\r\n scope.phase = phase;\r\n scope.trainees = trainees;\r\n\r\n function initializeTrainees(trainees, phase){\r\n scope.selectedTraineeBadge = {\r\n crewId: trainees[0].CrewId\r\n }; \r\n\r\n // Set Release Grading\r\n var releaseCompetences = phase.ReleaseGrading.Competences;\r\n releaseCompetences.forEach(function (competence) { \r\n competence.MandatorySub = setSubCompetenceValues(competence.MandatorySubCompetences); \r\n competence.OptionalSub = setSubCompetenceValues(competence.OptionalSubCompetences);\r\n\r\n //Filter out from optional the ones common with mandatory\r\n competence.OptionalSub = competence.OptionalSub.filter(c => !competence.MandatorySub.includes(c));\r\n });\r\n\r\n //Set Trainee Competences\r\n trainees.forEach(function (traineeSession) {\r\n var competences = [];\r\n \r\n releaseCompetences.forEach(function (competence) {\r\n competences.push(JSON.parse(JSON.stringify(competence)));\r\n });\r\n traineeSession.ReleaseGrading.Competences = competences;\r\n });\r\n\r\n //Initialize validation\r\n trainees.forEach(function (traineeSession) {\r\n traineeSession.ReleaseGrading.isGradeValid = scope.settings.GradeType == \"NotSet\";\r\n traineeSession.ReleaseGrading.isReleaseGradingValid = scope.settings.Competences.length == 0;\r\n });\r\n\r\n //For ground: check aircraft visits\r\n if(isGround && phase.AircraftTypes.length){\r\n trainees.forEach(function(trainee){\r\n var visitedAircrafts = trainee.AllVisitedAcTypes;\r\n \r\n var pendingAircrafts = [];\r\n phase.AircraftTypes.forEach(function(type){\r\n var array = type.split(',');\r\n\r\n //if arvi requirement is not met\r\n if (!array.some(x => visitedAircrafts.includes(x))) {\r\n var pendingArviList = [];\r\n if (array.length > 1) \r\n {\r\n array.forEach(function(arvi){\r\n pendingArviList.push(arvi);\r\n });\r\n }\r\n else\r\n {\r\n pendingArviList.push(array[0]);\r\n }\r\n pendingAircrafts.push(pendingArviList);\r\n }\r\n });\r\n\r\n trainee.pendingAircrafts = pendingAircrafts;\r\n trainee.ShowReleaseWarning = trainee.pendingAircrafts.length>0;\r\n });\r\n }\r\n scope.showReleaseWarning = trainees.some(x => x.ShowReleaseWarning);\r\n }\r\n\r\n function selectedTrainee() { \r\n \r\n return function( trainee ) {\r\n var showTrainee = false;\r\n if (trainee.CrewId === scope.selectedTraineeBadge.crewId){\r\n showTrainee = true;\r\n }\r\n return showTrainee;\r\n };\r\n }\r\n\r\n function close() {\r\n scope.modalInstance.close();\r\n }\r\n\r\n function toggleTrainee(){\r\n if(!scope.selectedTraineeBadge.crewId){\r\n scope.selectedTraineeBadge.crewId = scope.trainees.find(x => x.RadioModel).CrewId;\r\n }\r\n\r\n var selectedCrewId = scope.selectedTraineeBadge.crewId;\r\n var selectedTrainee = scope.trainees.find(x => x.CrewId == selectedCrewId);\r\n if(selectedTrainee && !selectedTrainee.RadioModel){\r\n if(scope.trainees.find(x => x.RadioModel)){\r\n scope.selectedTraineeBadge.crewId = scope.trainees.find(x => x.RadioModel).CrewId;\r\n }\r\n else{\r\n scope.selectedTraineeBadge.crewId = null;\r\n }\r\n }\r\n }\r\n\r\n function getTraineeClass(crewId){\r\n var textClass=\"\";\r\n\r\n var trainee = scope.trainees.find(x => x.CrewId == crewId);\r\n \r\n //Validate Release grading\r\n var isReleaseGradingValid = trainee.ReleaseGrading.isGradeValid;\r\n var isReleaseCompetencesValid = trainee.ReleaseGrading.isCompetenceValid;\r\n\r\n if(isReleaseGradingValid && isReleaseCompetencesValid){\r\n textClass = \"bg-green text-white\";\r\n }\r\n else{\r\n textClass = \"bg-amber text-white\";\r\n }\r\n \r\n return textClass;\r\n }\r\n\r\n\r\n function Submit() {\r\n if (!isValidForm()) {\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgSubmitValidation.html',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'lg'\r\n });\r\n }\r\n else {\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgSign.html',\r\n controller: 'ReleaseSignatureModalCtrl',\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n courseId: function () { return scope.course.Id; },\r\n isGround: function () { return isGround; },\r\n confirmationMsg: function () { return scope.settings.ConfirmationMessage; },\r\n requiresInstructorSignature: function () { return scope.settings.InstructorSignature },\r\n trainees: function () { return scope.trainees.filter(x => x.RadioModel) },\r\n submitRelease: function () { return SubmitRelease; }\r\n }\r\n });\r\n \r\n scope.modalInstance.result.then(function (result) {\r\n if(result.success){\r\n $location.path(\"/\");\r\n }\r\n });\r\n } \r\n }\r\n\r\n function SubmitRelease(password) {\r\n var submittedSessions = {\r\n SignaturePassword : password,\r\n TraineesSessions : trainees.filter(x => x.RadioModel)\r\n };\r\n\r\n return TrainingSessionFactory.releaseSession(submittedSessions);\r\n }\r\n\r\n function validateGrading(trainee){\r\n trainee.ReleaseGrading.isGradeValid = trainee.ReleaseGrading.Grade != null && trainee.ReleaseGrading.Grade != undefined;\r\n }\r\n\r\n /**\r\n * Calculate remaining characters for comment input\r\n * @param {string} text \r\n * @param {number} max \r\n */\r\n function getRemainingCharacters(text, max) {\r\n if (typeof (text) === \"undefined\" || text === null) return '';\r\n if (typeof (max) === \"undefined\" || max === null || max < 0 || !max) max = 4000;\r\n var length = text.length;\r\n\r\n return 'characters left: ' + (max - length);\r\n }\r\n\r\n function setSubCompetenceValues(current) {\r\n var updated = [];\r\n var first = parseInt(current[0], 10);\r\n var last = current[current.length - 1];\r\n\r\n if (first) {\r\n for (var i = first; i <= last; i++) {\r\n updated.push(i);\r\n }\r\n }\r\n return updated;\r\n }\r\n\r\n function leftScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft -= 500;\r\n }\r\n \r\n function rightScroll() {\r\n document.querySelector('.horizontal-scroll').scrollLeft += 500;\r\n }\r\n\r\n \r\n function isValidForm() {\r\n /*Requirements before split release\r\n 1. OnLine Mode\r\n 2. Valid Release Grading\r\n 3. Trainee Signature\r\n */\r\n\r\n var selectedTrainee = scope.trainees.find(x => x.CrewId == scope.selectedTraineeBadge.crewId);\r\n\r\n var isValid = false;\r\n var info = {\r\n border: \"\",\r\n icon: \"\",\r\n msg: \"\"\r\n };\r\n\r\n if (!window.navigator.onLine) {\r\n info = {\r\n border: \"border-left-red\",\r\n icon: \"fa-warning text-red\",\r\n msg: \" Online mode is required in order to submit a training.

Check your connection and try again!

\",\r\n };\r\n }\r\n else if(scope.settings.TraineeSignature && scope.trainees.filter(x => x.RadioModel).some(x => !x.Authorized)){\r\n\r\n if(selectedTrainee && !selectedTrainee.Authorized){\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-pencil-square-o text-orange\",\r\n msg: \"\" + selectedTrainee.TraineeName + \" needs to sign the form!\",\r\n scrollToTop:false\r\n };\r\n }\r\n else{\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg: \"All trainees need to sign their forms!\",\r\n scrollToTop:true\r\n };\r\n }\r\n }\r\n else if (!isGradingValid()) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg : \"\"\r\n };\r\n if(selectedTrainee && !selectedTrainee.ReleaseGrading.isCompetenceValid) {\r\n info.msg = \"You need to grade all competences for \" + selectedTrainee.TraineeName + \" before submitting!\"\r\n }\r\n else if(selectedTrainee && !selectedTrainee.ReleaseGrading.isGradeValid){\r\n info.msg = \"You need to grade \" + selectedTrainee.TraineeName + \" before submitting!\"\r\n }\r\n else if(!scope.gradingValidationInfo.isReleaseCompetencesValid || !scope.gradingValidationInfo.isReleaseGradingValid){\r\n info.msg = \"You need to grade all trainees before submitting!\"\r\n }\r\n }\r\n else {\r\n isValid = true;\r\n }\r\n\r\n scope.info = info;\r\n return isValid;\r\n }\r\n\r\n function validateTraineeForm(trainee) {\r\n /*Requirements before trainee signature\r\n 1. OnLine Mode\r\n 2. Valid Trainee Release Grading\r\n */\r\n\r\n var isValid = false;\r\n var info = {\r\n border: \"\",\r\n icon: \"\",\r\n msg: \"\"\r\n };\r\n\r\n if (!window.navigator.onLine) {\r\n info = {\r\n border: \"border-left-red\",\r\n icon: \"fa-warning text-red\",\r\n msg: \" Online mode is required in order to submit a training.

Check your connection and try again!

\",\r\n };\r\n }\r\n else if (!trainee.ReleaseGrading.isCompetenceValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg : \"You need to grade all competences!\"\r\n };\r\n }\r\n else if (!trainee.ReleaseGrading.isGradeValid) {\r\n info = {\r\n border: \"border-left-orange\",\r\n icon: \"fa-warning text-orange\",\r\n msg : \"You need to select an overall grade!\"\r\n };\r\n }\r\n else {\r\n isValid = true;\r\n }\r\n\r\n scope.info = info;\r\n return isValid;\r\n }\r\n\r\n function isGradingValid() {\r\n var isReleaseGradingValid = scope.settings.GradeType == \"NotSet\";\r\n var isReleaseCompetencesValid = scope.settings.Competences.length == 0;\r\n\r\n if (!isReleaseGradingValid) isReleaseGradingValid = !scope.trainees.filter(x => x.RadioModel).some(x => !x.ReleaseGrading.isGradeValid);\r\n\r\n if (!isReleaseCompetencesValid) isReleaseCompetencesValid = !scope.trainees.filter(x => x.RadioModel).some(x => !x.ReleaseGrading.isCompetenceValid);\r\n\r\n scope.gradingValidationInfo = {\r\n isReleaseGradingValid: isReleaseGradingValid,\r\n isReleaseCompetencesValid: isReleaseCompetencesValid,\r\n };\r\n\r\n return isReleaseGradingValid && isReleaseCompetencesValid;\r\n }\r\n\r\n\r\n function openTraineeSignature(trainee){\r\n //Enter signature mode : trainee form becomes read-only\r\n if(!trainee.Authorized){\r\n //Trainee can sign only if his form is valid\r\n if (!validateTraineeForm(trainee)) {\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgSubmitValidation.html',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'lg'\r\n });\r\n }\r\n else{\r\n trainee.Session = {Authorized:false};\r\n trainee.Name = trainee.TraineeName;\r\n scope.modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgTraineeSignature.html',\r\n controller: 'TraineeSignatureModalCtrl',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n trainee: function () { return trainee; },\r\n signatureSuccess: function () { return function(){trainee.Authorized = true}; }\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n function resetSignature(trainee){\r\n var modalInstance = $uibModal.open({\r\n templateUrl: 'views/Training/dlgResetSignature.html',\r\n controller: 'TraineeSignatureModalCtrl',\r\n scope: scope,\r\n backdrop: 'static',\r\n keyboard: false,\r\n size: 'md',\r\n resolve: {\r\n trainee: function () { return trainee; },\r\n signatureSuccess: function () { return function(){}; }\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (confirm) {\r\n if(confirm){\r\n trainee.Authorized = false;\r\n trainee.Session.Authorized = false;\r\n }\r\n \r\n });\r\n }\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/releasable-module.tpl.html',\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n\r\n a3_pilot_reports.directive('releaseWarning', releaseWarning);\r\n\r\n /**\r\n * @memberof CabinReports\r\n * @ngdoc directive\r\n * @name releaseWarning\r\n * @restrict E\r\n * @description\r\n * Soft rules alert in release\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n\r\n function releaseWarning() {\r\n function link(scope, attrs) {\r\n\r\n scope.warningTrainees = scope.trainees.filter(x => !x.Session.Absent && x.ShowReleaseWarning);\r\n scope.filterSelectedTrainee = filterSelectedTrainee;\r\n\r\n function filterSelectedTrainee(){\r\n return function( trainee ) {\r\n var showTrainee = false;\r\n if(scope.selectedTrainee){\r\n showTrainee = trainee.CrewId == scope.selectedTrainee.CrewId;\r\n }\r\n return showTrainee;\r\n };\r\n }\r\n\r\n\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n templateUrl: \"views/Training/releaseWarning.tpl.html\",\r\n scope : false,\r\n terminal: true,\r\n link: link\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('ReleaseSignatureModalCtrl', ReleaseSignatureModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SignatureModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\r\n\r\n function ReleaseSignatureModalCtrl($scope, $routeParams, CourseFactory, $uibModalInstance, courseId, isGround, confirmationMsg, requiresInstructorSignature, trainees, submitRelease){\r\n $scope.close = close;\r\n $scope.submit = submit;\r\n $scope.confirm = confirm;\r\n $scope.confirmAircraft = confirmAircraft;\r\n\r\n $scope.errorMessage = \"\";\r\n $scope.successMessage = \"\";\r\n $scope.responseText = null;\r\n $scope.responseHasErrors = null;\r\n $scope.success = false;\r\n $scope.isLoading = false;\r\n\r\n $scope.formData = {};\r\n \r\n $scope.requiredSignature = requiresInstructorSignature;\r\n\r\n $scope.isConfirmed = true;\r\n $scope.finalPendigArVis = [];\r\n \r\n if(isGround && hasPendingAircraftVisits()) {\r\n $scope.aircraftVisits = true;\r\n }\r\n else if(confirmationMsg){\r\n $scope.confirmationMsg = confirmationMsg;\r\n $scope.isConfirmed = false;\r\n }\r\n else{\r\n if(!requiresInstructorSignature){ //if signature isn't required continue with submit \r\n $scope.isLoading = true;\r\n submit();\r\n }\r\n }\r\n\r\n function hasPendingAircraftVisits() {\r\n var released = trainees.filter(x => x.RadioModel)\r\n var pendingVisits = released.some(x => x.pendingAircrafts && x.pendingAircrafts.length > 0);\r\n\r\n if(pendingVisits){ \r\n var maxLength = 0;\r\n released.forEach(function(trainee){\r\n if(trainee.pendingAircrafts.length > maxLength){\r\n var maxList = trainee.pendingAircrafts;\r\n maxLength = maxList.length; \r\n $scope.finalPendigArVis = trainee.pendingAircrafts; \r\n } \r\n });\r\n }\r\n return pendingVisits;\r\n }\r\n\r\n function confirm(){\r\n $scope.isConfirmed = true;\r\n if(!requiresInstructorSignature){ //if signature isn't required continue with submit \r\n $scope.isLoading = true;\r\n submit();\r\n }\r\n }\r\n\r\n function confirmAircraft() {\r\n $scope.aircraftVisits = false;\r\n if(confirmationMsg){\r\n $scope.confirmationMsg = confirmationMsg;\r\n $scope.isConfirmed = false;\r\n } \r\n }\r\n\r\n function submit(){\r\n $scope.errorMessage = \"\";\r\n $scope.successMessage = \"\";\r\n \r\n $scope.isLoading = true;\r\n $scope.success = false;\r\n\r\n var signaturePassword = $scope.formData.password;\r\n if(!signaturePassword && requiresInstructorSignature){\r\n $scope.isLoading = false;\r\n $scope.errorMessage = \"Signature is required. Please enter your password.\";\r\n }else{\r\n\r\n submitRelease(signaturePassword).then(function(data){\r\n $scope.isLoading = false;\r\n var errorMessage = data.data.errorMessage;\r\n\r\n $scope.successMessage = \"Training has been submitted.\"\r\n\r\n //always show errorMessage even if success is true\r\n if(errorMessage && errorMessage.length > 0){\r\n $scope.errorMessage = errorMessage;\r\n\r\n //not Release Trainees\r\n var responseTrainees = data.data.data.data;\r\n var responseTraineeCrewIds = responseTrainees.map(function(trainee){return trainee.CrewId});\r\n $scope.traineeInfo = trainees.filter(x => responseTraineeCrewIds.includes(x.CrewId));\r\n }\r\n else{\r\n $scope.errorMessage = null;\r\n }\r\n\r\n CourseFactory.setCourseOutdated(courseId);\r\n $scope.success = true;\r\n }).catch(function(data){\r\n $scope.isLoading = false;\r\n if(data.data && data.data.errorMessage){\r\n $scope.errorMessage = data.data.errorMessage;\r\n }\r\n else{\r\n $scope.errorMessage = \"Failed to save Training Session\";\r\n }\r\n }); \r\n }\r\n\r\n // clear password\r\n\t\t $scope.formData.password = \"\";\r\n }\r\n\r\n /**\r\n * Close the modal\r\n * @memberof SignModalCtrl\r\n */\r\n function close(){\r\n var result = {\r\n \"success\" : $scope.success\r\n };\r\n $uibModalInstance.close(result);\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('SignatureModalCtrl', SignatureModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name SignatureModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\r\n\r\n function SignatureModalCtrl($scope, $routeParams, $uibModalInstance, TrainingSessionFactory, FlightSessionFactory, GroundDutyFactory, CrewRouteFactory, CourseFactory, courseId, date, dutyId, dutyNo, dutyDay, confirmationMsg, requiresInstructorSignature, trainees, submitSession, releaseGrading, isReleased){\r\n $scope.close = close;\r\n $scope.submit = submit;\r\n $scope.confirm = confirm;\r\n $scope.confirmSubmit = confirmSubmit;\r\n $scope.releaseSubmit = releaseSubmit;\r\n $scope.confirmAircraft = confirmAircraft;\r\n\r\n $scope.errorMessage = \"\";\r\n $scope.successMessage = \"\";\r\n $scope.responseText = null;\r\n $scope.responseHasErrors = null;\r\n $scope.success = false;\r\n $scope.isLoading = false;\r\n $scope.withGrading = false;\r\n\r\n $scope.formData = {};\r\n \r\n var requiredSignature = requiresInstructorSignature;\r\n $scope.requiredSignature = requiredSignature;\r\n\r\n $scope.releaseWarning = false;\r\n $scope.isConfirmed = true;\r\n $scope.releaseGrading = releaseGrading;\r\n $scope.finalPendigArVis = [];\r\n\r\n var isGroundDuty = false;\r\n if(dutyId) {\r\n isGroundDuty = true;\r\n }\r\n\r\n if(releaseNotSelected()){\r\n $scope.releaseWarning = true; \r\n }\r\n else if(isGroundDuty && hasPendingAircraftVisits()) {\r\n $scope.aircraftVisits = true;\r\n }\r\n else if(confirmationMsg && isReleased){\r\n $scope.confirmationMsg = confirmationMsg;\r\n $scope.isConfirmed = false;\r\n }\r\n else{\r\n if(!requiresInstructorSignature){ //if signature isn't required continue with submit \r\n $scope.isLoading = true;\r\n submit();\r\n }\r\n }\r\n\r\n function releaseNotSelected(){\r\n var allAvailable = !trainees.filter(x => !x.Session.Absent).some(x => !x.AvailableRelease);\r\n var notReleased = trainees.filter(x =>!x.Session.Absent).some(x => !x.Session.Released);\r\n return allAvailable && notReleased;\r\n }\r\n\r\n function hasPendingAircraftVisits() {\r\n var released = !trainees.filter(x =>!x.Session.Absent).some(x => !x.Session.Released) || $scope.withGrading;\r\n var pendingVisits = released && trainees.filter(x => !x.Session.Absent).some(x => x.pendingAircrafts && x.pendingAircrafts.length > 0);\r\n\r\n if(pendingVisits){ \r\n var maxLength = 0;\r\n trainees.filter(x => !x.Session.Absent).forEach(function(trainee){\r\n if(trainee.pendingAircrafts.length > maxLength){\r\n var maxList = trainee.pendingAircrafts;\r\n maxLength = maxList.length; \r\n $scope.finalPendigArVis = trainee.pendingAircrafts; \r\n } \r\n });\r\n }\r\n return pendingVisits;\r\n }\r\n\r\n function confirm(){\r\n $scope.isConfirmed = true;\r\n if(!requiresInstructorSignature){ //if signature isn't required continue with submit \r\n $scope.isLoading = true;\r\n submit();\r\n }\r\n }\r\n\r\n function confirmSubmit(){\r\n $scope.releaseWarning = false;\r\n if(isGroundDuty && hasPendingAircraftVisits()){\r\n $scope.aircraftVisits = true;\r\n } \r\n }\r\n\r\n function confirmAircraft() {\r\n $scope.aircraftVisits = false;\r\n if(confirmationMsg){\r\n $scope.confirmationMsg = confirmationMsg;\r\n $scope.isConfirmed = false;\r\n } \r\n }\r\n\r\n function releaseSubmit(){\r\n $scope.withGrading = true;\r\n $scope.releaseWarning = false;\r\n if(hasPendingAircraftVisits()){\r\n $scope.aircraftVisits = true;\r\n } \r\n else if(confirmationMsg){\r\n $scope.confirmationMsg = confirmationMsg;\r\n $scope.isConfirmed = false;\r\n } \r\n }\r\n\r\n function submit(){\r\n $scope.errorMessage = \"\";\r\n $scope.successMessage = \"\";\r\n \r\n $scope.isLoading = true;\r\n $scope.success = false;\r\n\r\n var signaturePassword = $scope.formData.password;\r\n if(!signaturePassword && requiredSignature){\r\n $scope.isLoading = false;\r\n $scope.errorMessage = \"Signature is required. Please enter your password.\";\r\n }else{\r\n\r\n submitSession(signaturePassword, $scope.withGrading).then(function(data){\r\n $scope.isLoading = false;\r\n var errorMessage = data.data.errorMessage;\r\n\r\n $scope.successMessage = \"Training has been submitted.\"\r\n\r\n //always show errorMessage even if success is true\r\n if(errorMessage && errorMessage.length > 0){\r\n $scope.errorMessage = errorMessage;\r\n\r\n //not Release Trainees\r\n var responseTrainees = data.data.data.data;\r\n var responseTraineeCrewIds = responseTrainees.map(function(trainee){return trainee.CrewId});\r\n $scope.traineeInfo = trainees.filter(x => responseTraineeCrewIds.includes(x.CrewId));\r\n }\r\n else{\r\n $scope.errorMessage = null;\r\n }\r\n\r\n if(dutyId){ //isGround\r\n TrainingSessionFactory.remove(courseId,date,dutyId);\r\n GroundDutyFactory.setCourseCompleted(dutyId,courseId);\r\n }\r\n else{ //isFlight\r\n FlightSessionFactory.remove(courseId, date, dutyNo, dutyDay);\r\n CrewRouteFactory.setCourseCompleted(dutyNo, dutyDay, courseId, date)\r\n }\r\n\r\n CourseFactory.setCourseOutdated(courseId);\r\n $scope.success = true;\r\n }).catch(function(data){\r\n $scope.isLoading = false;\r\n if(data.data && data.data.errorMessage){\r\n $scope.errorMessage = data.data.errorMessage;\r\n }\r\n else{\r\n $scope.errorMessage = \"Failed to save Training Session\";\r\n }\r\n }); \r\n }\r\n\r\n // clear password\r\n\t\t $scope.formData.password = \"\";\r\n }\r\n\r\n /**\r\n * Close the modal\r\n * @memberof SignModalCtrl\r\n */\r\n function close(){\r\n var result = {\r\n \"success\" : $scope.success\r\n };\r\n $uibModalInstance.close(result);\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('syllabusItemHeader', syllabusItemHeader);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name syllabusItemHeader\r\n * @restrict E\r\n * @description\r\n * Panel heading for syllabus items\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function syllabusItemHeader() {\r\n function link(scope, element, attrs) {\r\n scope.selectTry = selectTry;\r\n scope.selectGrading = selectGrading;\r\n\r\n //find first not ReadOnly try\r\n scope.pendingAttempt = scope.item.Tries.find(x => x.isFirstTry);\r\n scope.firstTry = scope.item.Tries[0];\r\n\r\n\r\n function selectTry(){\r\n if(scope.pendingAttempt){\r\n scope.itemSelection();\r\n }\r\n }\r\n \r\n function selectGrading(){\r\n scope.gradingSelection();\r\n }\r\n\r\n }\r\n\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/syllabus-item-header.tpl.html',\r\n scope: {item:\"=\", itemSelection: \"&onItemSelection\", gradingSelection: \"&onGradingSelection\"},\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.directive('syllabus', syllabus);\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc directive\r\n * @name certificates\r\n * @restrict E\r\n * @description\r\n * Implementation of syllabus\r\n * @example\r\n * Usage:\r\n * \r\n * @ngInject\r\n */\r\n function syllabus(TrainingSessionFactory, FlightSessionFactory, $timeout) {\r\n function link(scope, element, attrs) {\r\n\r\n var isGround = false;\r\n var courseId = scope.dutyCourse.Id;\r\n\r\n if(scope.groundDuty){\r\n isGround = true;\r\n var date = scope.groundDuty.DutyDateS;\r\n var dutyId = scope.groundDuty.Id;\r\n }\r\n else{\r\n var date = scope.crewRouteDuty.date;\r\n var dutyNo = scope.crewRouteDuty.DutyNo;\r\n var dutyDay = scope.crewRouteDuty.DutyDay;\r\n } \r\n\r\n scope.updateTraineesSyllabus = updateTraineesSyllabus;\r\n scope.selectTry = selectTry;\r\n scope.updateTry = updateTry;\r\n scope.oneAtATime = true;\r\n scope.addTry = addTry;\r\n scope.removeTry = removeTry;\r\n scope.setPanelStyle = setPanelStyle;\r\n scope.selectTryFromHeader = selectTryFromHeader;\r\n scope.gradeFromHeader = gradeFromHeader;\r\n\r\n scope.traineeSyllabi.forEach(function(traineeSyllabus){\r\n traineeSyllabus.Items.forEach(function(syllabusItem){\r\n syllabusItem.Tries.forEach(function(attempt){\r\n //Check if default grade exists & set status\r\n if(syllabusItem.IsGradable && !attempt.isReadOnly){\r\n itemAutoSelection(syllabusItem, attempt); //select item depending on grade existence\r\n }\r\n });\r\n setPanelStyle(syllabusItem); //ui depending on validation & status\r\n updateTraineesSyllabus(syllabusItem, traineeSyllabus); //copy values to all trainee syllabi \r\n });\r\n });\r\n\r\n //Multiple syllabi - Get session to store competence grading\r\n if(scope.traineeSyllabi.length > 1){\r\n scope.traineeSyllabi.forEach(function(traineeSyllabus){\r\n var crewId = traineeSyllabus.TraineeIds[0];\r\n var trainee = scope.trainees.find(x => x.CrewId == crewId);\r\n traineeSyllabus.TraineeName = trainee.Name;\r\n traineeSyllabus.TraineeAimsId = trainee.AimsId;\r\n });\r\n }\r\n\r\n \r\n function gradeFromHeader(syllabus, syllabusItem){\r\n var firstPendingTry = syllabusItem.Tries.filter(x => !x.isReadOnly)[0];\r\n updateTry(syllabus, syllabusItem, firstPendingTry);\r\n setPanelStyle(syllabusItem);\r\n updateTraineesSyllabus(syllabusItem, syllabus);\r\n \r\n triggerSyllabusClick();\r\n }\r\n\r\n function selectTryFromHeader(syllabus, syllabusItem){\r\n var firstPendingTry = syllabusItem.Tries.filter(x => !x.isReadOnly)[0];\r\n selectTry(syllabus, syllabusItem, firstPendingTry);\r\n\r\n if(isGround){\r\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) { console.log(e) })\r\n }\r\n else{\r\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) { console.log(e) })\r\n }\r\n\r\n triggerSyllabusClick();\r\n }\r\n\r\n function triggerSyllabusClick(){\r\n //preventDefault() and stopPropagation() prevents setReleaseStatus() to be triggered\r\n $timeout(function() {\r\n var el = document.getElementById('syllabus');\r\n angular.element(el).triggerHandler('click');\r\n }, 0);\r\n }\r\n\r\n function selectTry(syllabus, syllabusItem, attempt){\r\n attempt.Selected = !attempt.Selected;\r\n syllabusItem.Selected = syllabusItem.Tries.filter(t => !t.isReadOnly).some(t => t.Selected);\r\n \r\n setPanelStyle(syllabusItem);\r\n updateTraineesSyllabus(syllabusItem, syllabus);\r\n }\r\n\r\n function updateTry(syllabus, syllabusItem, attempt){\r\n if(syllabusItem.IsGradable){\r\n itemAutoSelection(syllabusItem, attempt); //select item depending on grade existence\r\n } \r\n setPanelStyle(syllabusItem); //ui depending on validation & status\r\n updateTraineesSyllabus(syllabusItem, syllabus); //copy values to all trainee syllabi \r\n updateSession(); //save in IndexDb\r\n }\r\n\r\n function itemAutoSelection(syllabusItem, attempt){\r\n var hasCompetencesGrading = attempt.TryGrading.Competences.some(x => x.Grading);\r\n if( attempt.TryGrading.Grade || hasCompetencesGrading){\r\n attempt.Selected = true;\r\n syllabusItem.Selected = true;\r\n }\r\n else{\r\n attempt.Selected = false;\r\n syllabusItem.Selected = false;\r\n \r\n //Check if any of the tries has grading - If not, deselect item\r\n var pendingTries = syllabusItem.Tries.filter(x => !x.isReadOnly); //filter out history tries\r\n for(var i = 0; i < pendingTries.length; i++){\r\n var itemTry = pendingTries[i];\r\n var tryCompetenceGrading = itemTry.TryGrading.Competences.some(x => x.Grading);\r\n if( itemTry.TryGrading.Grade || tryCompetenceGrading){\r\n syllabusItem.Selected = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function setPanelStyle(item){\r\n var historyTriesCount = item.Tries.filter(x => x.isReadOnly).length;\r\n var newTriesCount = item.Tries.filter(x => !x.isReadOnly && x.Selected).length;\r\n item.TriesPerformedCount = historyTriesCount + newTriesCount;\r\n\r\n var completedItem = item.TriesPerformedCount >= item.MandatoryCount;\r\n\r\n\r\n if(item.MandatoryCount == 0){ //non-mandatory items are considered completed if performed at least once\r\n completedItem = item.TriesPerformedCount>=1;\r\n }\r\n\r\n var invalidItem = false;\r\n if(item.IsGradable && item.Selected){\r\n var gradingType = item.GradeType; //Numeric or Outcome or Competences\r\n var traineeSelectedTries = item.Tries.filter(x => x.Selected);\r\n\r\n traineeSelectedTries.forEach(function(selectedTry){\r\n\r\n var invalidGrading = gradingType != \"Competences\" && !selectedTry.TryGrading.Grade;\r\n var invalidCompetences = gradingType == \"Competences\" && !selectedTry.TryGrading.isCompetenceValid;\r\n \r\n if(invalidGrading || invalidCompetences){\r\n invalidItem = true;\r\n }\r\n });\r\n }\r\n\r\n if(completedItem){\r\n item.PanelClass = 'panel-green panel-border-left-green ';\r\n }\r\n else{\r\n item.PanelClass = 'panel-border-left-blue ';\r\n }\r\n\r\n if(invalidItem){\r\n item.PanelClass = 'panel-border-left-orange ';\r\n }\r\n }\r\n\r\n function updateTraineesSyllabus(item, syllabus) {\r\n var crewIds = syllabus.TraineeIds;\r\n\r\n scope.trainees.filter(x => crewIds.includes(x.CrewId)).forEach(function (trainee) {\r\n var sessionItem = trainee.Session.Items.find(sessionItem => item.Id == sessionItem.Id);\r\n sessionItem.RepeatRequired = item.RepeatRequired;\r\n sessionItem.Selected = item.Selected;\r\n sessionItem.PhaseId = item.PhaseId;\r\n sessionItem.Tries = deepCopy(item.Tries);\r\n sessionItem.SyllabusItemId = item.Id;\r\n sessionItem.TriesPerformedCount = item.TriesPerformedCount;\r\n });\r\n }\r\n\r\n function deepCopy(originalObject){\r\n return JSON.parse(JSON.stringify( originalObject ));\r\n }\r\n\r\n function addTry(item, syllabus) {\r\n var competences = deepCopy(item.Competences);\r\n\r\n var newTry = {\r\n Comments: null,\r\n ActionNo : item.Tries.length + 1,\r\n Selected : true,\r\n TryGrading: { Grade: null, Competences: competences, GradeType: item.GradeType },\r\n };\r\n\r\n item.Selected = true;\r\n item.Tries.push(newTry);\r\n setPanelStyle(item);\r\n updateTraineesSyllabus(item, syllabus)\r\n }\r\n \r\n function removeTry(item, syllabus) {\r\n item.Tries.pop();\r\n\r\n if(!item.Tries.filter(x => !x.isReadOnly).length){\r\n item.Selected = false;\r\n }\r\n setPanelStyle(item);\r\n updateTraineesSyllabus(item, syllabus)\r\n }\r\n\r\n function updateSession(){\r\n if(isGround){\r\n TrainingSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyId, console.log, function (e) { console.log(e) })\r\n }\r\n else{\r\n FlightSessionFactory.updateSession(scope.trainees, scope.course, courseId, date, dutyNo, dutyDay, console.log, function (e) { console.log(e) })\r\n }\r\n }\r\n }\r\n return {\r\n restrict: 'E',\r\n terminal: false,\r\n templateUrl: 'views/Training/syllabus.tpl.html',\r\n scope: false,\r\n link: link\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n a3_pilot_reports.controller('TraineeSignatureModalCtrl', TraineeSignatureModalCtrl)\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name TraineeSignatureModalCtrl\r\n * @description \r\n * Shows Show Signature \r\n * @ngInject\r\n */\r\n\r\n function TraineeSignatureModalCtrl($scope, $timeout, $uibModalInstance, trainee, TrainingSessionFactory, signatureSuccess){\r\n $scope.close = close;\r\n $scope.confirmReset = confirmReset;\r\n $scope.traineeSign = traineeSign;\r\n $scope.continue = continueWarning;\r\n $scope.confirmation = false;\r\n\r\n initialiazeTrainee(trainee);\r\n function initialiazeTrainee(trainee){\r\n var signatureTrainee = deepCopy(trainee);\r\n\r\n signatureTrainee.Session.Authorized = trainee.Session.Authorized ? trainee.Session.Authorized : false;\r\n signatureTrainee.errorMessage = \"\";\r\n signatureTrainee.successMessage = \"\";\r\n signatureTrainee.responseText = null;\r\n signatureTrainee.responseHasErrors = null;\r\n signatureTrainee.success = false;\r\n signatureTrainee.isLoading = false;\r\n signatureTrainee.password = \"\";\r\n signatureTrainee.username = trainee.AimsId;\r\n signatureTrainee.PositionCode = trainee.position ? trainee.position : trainee.PositionCode;\r\n\r\n $scope.signatureTrainee = signatureTrainee;\r\n }\r\n\r\n function deepCopy(originalObject) {\r\n return JSON.parse(JSON.stringify(originalObject));\r\n }\r\n\r\n function traineeSign(signatureTrainee){\r\n\r\n if(!signatureTrainee.password || !signatureTrainee.username){\r\n signatureTrainee.errorMessage = \"Signature is required. Please enter your username and password.\";\r\n }\r\n else{\r\n signatureTrainee.isLoading = true;\r\n //Individually authorize trainee\r\n var credentials =\r\n {\r\n CrewId : signatureTrainee.CrewId,\r\n Password : signatureTrainee.password,\r\n Username : signatureTrainee.username,\r\n PositionCode : signatureTrainee.PositionCode\r\n };\r\n\r\n if($scope.isOffline){\r\n $timeout(function () {\r\n signatureTrainee.isLoading = false;\r\n }, 100);\r\n signatureTrainee.errorMessage = \"Online mode is required in order to sign. Please connect to the internet and try again.\";\r\n }\r\n else{\r\n TrainingSessionFactory.authorizeTrainee(credentials, function (responseData) {\r\n signatureTrainee.isLoading = false;\r\n signatureTrainee.success = true;\r\n signatureTrainee.Session.Authorized = true;\r\n\r\n signatureTrainee.Session.Authorized = true;\r\n trainee.Session.Authorized = true;\r\n\r\n signatureSuccess();\r\n\r\n \r\n }).catch(function(data){\r\n signatureTrainee.isLoading = false;\r\n if(data.data && data.data.errorMessage){\r\n signatureTrainee.errorMessage = data.data.errorMessage;\r\n }\r\n else{\r\n signatureTrainee.errorMessage = \"An error occured during your authentication\";\r\n }\r\n });\r\n }\r\n }\r\n // clear credentials\r\n trainee.username = \"\";\r\n trainee.password = \"\";\r\n }\r\n\r\n /**\r\n * Close the modal\r\n */\r\n function close(){\r\n $uibModalInstance.close(false);\r\n }\r\n\r\n /**\r\n * Confirm\r\n */\r\n function confirmReset(){\r\n $uibModalInstance.close(true);\r\n }\r\n\r\n function continueWarning(){\r\n $scope.confirmation = true;\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n a3_pilot_reports.factory('TrainingSessionFactory', TrainingSessionFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name TrainingSessionFactory\r\n * @description \r\n * Add, Update, Delete and Get Training Courses.\r\n * @ngInject\r\n */\r\n function TrainingSessionFactory(IndexedDBService, CourseFactory, $http, apiUrl, GroundDutyFactory, $filter) {\r\n\r\n /**\r\n * Initialize Session\r\n * @memberof TrainingSessionFactory\r\n */\r\n function Session() {\r\n this.Id = null;\r\n }\r\n\r\n var objType = 'TrainingSessions';\r\n var objCallback = Session;\r\n\r\n var service = {\r\n getAll: getAll,\r\n getSession: getSession,\r\n setSession: setSession,\r\n updateSession: updateSession,\r\n getSessionTrainees: getSessionTrainees,\r\n submitSession: submitSession,\r\n remove: remove,\r\n authorizeTrainee: authorizeTrainee,\r\n getDutySessions: getDutySessions,\r\n applyTraineeInfoToSession: applyTraineeInfoToSession,\r\n releaseSession: releaseSession\r\n };\r\n\r\n\r\n /**\r\n * Get all ground training sessions\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\r\n function getAll(callback) {\r\n IndexedDBService.getAll(objType).then(function (results) {\r\n callback(results);\r\n });\r\n };\r\n\r\n /**\r\n * Get session By day and courseId\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\r\n function getSession(courseId, day, dutyId, afterRefresh, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [day, courseId, dutyId]).then(function (session) {\r\n\r\n CourseFactory.getCourseFromStorage(courseId, function (course) {\r\n if (course && !course.HasLimitedInfo && course.CrewCoursePhases && course.CourseTrainees) {\r\n mergeCourseWithSession(course, session, dutyId, afterRefresh);\r\n }\r\n callback(course);\r\n }, errorCallback);\r\n })\r\n .catch(errorCallback);\r\n }\r\n\r\n function applyTraineeInfoToSession(course, courseId, day, dutyId, callback, errorCallback){\r\n IndexedDBService.getById(objType, [day, courseId, dutyId])\r\n .then(function (localSession) {\r\n var isNewSession = false;\r\n if (!localSession) {\r\n localSession = { \r\n courseId: courseId, \r\n day: day, \r\n dutyId: dutyId, \r\n trainees: [],\r\n TraineeEligibilty : course.TraineeEligibilty,\r\n CourseTrainees : course.CourseTrainees\r\n };\r\n isNewSession = true;\r\n } \r\n else{\r\n localSession.TraineeEligibilty = course.TraineeEligibilty;\r\n localSession.CourseTrainees = course.CourseTrainees;\r\n }\r\n\r\n if (isNewSession) {\r\n addSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n } else {\r\n saveSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n }\r\n }).catch(errorCallback);\r\n }\r\n\r\n function getDutySessions(day, dutyId, callback) {\r\n IndexedDBService.getAll(objType).then(function (results) {\r\n results = results.filter(x => x.day == day && x.dutyId == dutyId)\r\n callback(results);\r\n });\r\n }\r\n\r\n /**\r\n * Remove session By day,dutyID (Optional) and courseId\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\r\n function remove(courseId, day, dutyId, callback, errorCallback) {\r\n IndexedDBService.remove(objType, [day, courseId, dutyId])\r\n .then(callback)\r\n .catch(errorCallback);\r\n };\r\n\r\n /**\r\n * Get session Trainees By day and courseId\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\r\n function getSessionTrainees(courseId, day, dutyId, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [day, courseId, dutyId]).then(function (session) {\r\n var trainees = session && session.trainees ? session.trainees : [];\r\n callback(trainees);\r\n })\r\n .catch(errorCallback);\r\n };\r\n\r\n /**\r\n * Set session\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\r\n function setSession(session, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [session.day, session.courseId, session.dutyId]).then(function (result) {\r\n if (result) {\r\n saveSessionToStorage(session).then(callback).catch(errorCallback);;\r\n } else {\r\n addSessionToStorage(session).then(callback).catch(errorCallback);\r\n }\r\n }).catch(errorCallback);\r\n };\r\n\r\n /**\r\n * Set session\r\n * @memberof TrainingSessionFactory\r\n * @param {function} callback \r\n */\r\n function updateSession(trainees, session, courseId, day, dutyId, callback, errorCallback) {\r\n IndexedDBService.getById(objType, [day, courseId, dutyId])\r\n .then(function (localSession) {\r\n var isNewSession = false;\r\n if (!localSession) {\r\n localSession = { courseId: courseId, day: day, dutyId: dutyId, trainees: [] }\r\n isNewSession = true;\r\n } else {\r\n localSession.trainees = [];\r\n }\r\n\r\n if (session) {\r\n localSession.Media = session.Media;\r\n localSession.ReleasedPhase = session.ReleasedPhase;\r\n localSession.TraineeEligibilty = session.TraineeEligibilty;\r\n }\r\n\r\n trainees.forEach(function (trainee) {\r\n localSession.trainees.push(trainee);\r\n });\r\n\r\n if (isNewSession) {\r\n addSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n } else {\r\n saveSessionToStorage(localSession).then(callback).catch(errorCallback);\r\n }\r\n }).catch(errorCallback);\r\n }\r\n\r\n function mergeCourseWithSession(course, session, dutyId, afterRefresh) {\r\n course.HasLimitedSession = session == undefined;\r\n\r\n var hasPreviousSessions = mergeSyllabusWithHistory(course.CourseTrainees, course.CrewCoursePhases);\r\n filterTraineesByEligibility(dutyId, course, session, afterRefresh);\r\n\r\n course.CrewCoursePhases.forEach(function (phase) {\r\n calculatePhaseStatus(phase, course);\r\n });\r\n course.selectedPhase = getSelectedPhase(course);\r\n\r\n\r\n // Calculate eligible trainees phase status\r\n course.CourseTrainees.forEach(function (trainee) {\r\n var traineePhase = trainee.Phases.find(x => x.PhaseId == course.selectedPhase.PhaseId);\r\n if (traineePhase) {\r\n trainee.ActivePhaseStatus = traineePhase.PhaseStatus;\r\n } else {\r\n trainee.ActivePhaseStatus = \"Pending\";\r\n }\r\n trainee.Selectable = trainee.ActivePhaseStatus == \"InProgress\";\r\n });\r\n\r\n //Filter By Role: Filter out trainees that have a flight crew role\r\n if(course.selectedPhase.FilterByRole){\r\n course.CourseTrainees.filter(x => x.Selectable && x.PositionCode!='CP' && x.PositionCode!='FO').forEach(function(flightCrewTrainee){\r\n flightCrewTrainee.EligibilityStatus = false;\r\n flightCrewTrainee.EligibilityDesc = \"InvalidRole\";\r\n course.NonEligibleTrainees.push(flightCrewTrainee);\r\n });\r\n }\r\n \r\n // Non InProgress trainees will be marked as NonEligible (remove further ahead trainees on multiple InProgress phases)\r\n course.CourseTrainees.filter(x => !x.Selectable).forEach(function (invalidPhaseTrainee) {\r\n invalidPhaseTrainee.EligibilityStatus = false;\r\n invalidPhaseTrainee.EligibilityDesc = \"AlreadySubmitted\";\r\n course.NonEligibleTrainees.push(invalidPhaseTrainee);\r\n });\r\n course.CourseTrainees = course.CourseTrainees.filter(x => x.EligibilityStatus);\r\n\r\n // Get trainee sessions\r\n course.CourseTrainees.forEach(function (trainee) {\r\n var sessionTrainee = session ? session.trainees.find(x => x.CrewId == trainee.CrewId) : null;\r\n if (sessionTrainee) {\r\n trainee.Session = sessionTrainee.Session;\r\n } else {\r\n trainee.Session = {\r\n Released: course.selectedPhase.ModuleType == \"Training\" ? false : true,\r\n CrewId: trainee.CrewId,\r\n Items: [],\r\n Absent: false,\r\n DayGrading: {\r\n Comments: null,\r\n Grade: null,\r\n Competences: []\r\n },\r\n ReleaseGrading: {\r\n Comments: null,\r\n Grade: null,\r\n Competences: []\r\n }\r\n }\r\n }\r\n });\r\n\r\n /* Set default values for release option\r\n Training Modules: 'No' release as default\r\n Check Module: 'Yes' release as default\r\n */\r\n course.ReleasedPhase = course.selectedPhase.ModuleType == \"Training\" ? false : true;\r\n\r\n if (session) {\r\n course.Media = session.Media;\r\n course.ReleasedPhase = session.ReleasedPhase;\r\n course.TraineeEligibilty = session.TraineeEligibilty;\r\n }\r\n\r\n }\r\n\r\n function getSelectedPhase(course) {\r\n var hasSelectedPhase = false;\r\n var phases = course.CrewCoursePhases;\r\n\r\n phases.forEach(function (phase, index, array) {\r\n phase.isFirst = index == 0;\r\n phase.isLast = (index + 1 == array.length);\r\n // Select the first InProgress & selected phase\r\n if (!hasSelectedPhase && phase.Status == \"InProgress\" && phase.isSelected) {\r\n phase.Selected = true;\r\n hasSelectedPhase = true;\r\n }\r\n });\r\n \r\n // Select the first InProgress phase\r\n if (!hasSelectedPhase && phases.some(x => x.Status == \"InProgress\")) {\r\n phases.find(x => x.Status == \"InProgress\").Selected = true;\r\n hasSelectedPhase = true;\r\n }\r\n\r\n if (!hasSelectedPhase) {\r\n phases.find(x => x.isFirst).Selected = true;\r\n }\r\n\r\n var selectedPhase = phases.find(x => x.Selected);\r\n return selectedPhase;\r\n }\r\n\r\n\r\n function filterTraineesByEligibility(dutyId, course, session, afterRefresh) {\r\n var groundDuty = GroundDutyFactory.getGroundDutyFromStorage(dutyId);\r\n // Trainee Eligiblity cases\r\n // 1. After refresh - Save newly fetched eligibility in session\r\n // 2. No refresh & Session exists - Get last fetched eligibility from session\r\n // 3. No refresh & No session exists - Rely on previously fetched eligibility (different duty - same course)\r\n\r\n var traineeEligibility = course.TraineeEligibilty;\r\n if(!afterRefresh && session && session.TraineeEligibilty){ \r\n traineeEligibility = session.TraineeEligibilty;\r\n }\r\n if(session) session.TraineeEligibilty = traineeEligibility; //update session eligibility\r\n\r\n\r\n\r\n // Get ground duty trainees without any training records\r\n var trainees = getGroundCourseTrainees(groundDuty, course.Id);\r\n var inactiveTrainees = trainees.filter(x => !course.CourseTrainees.some(z => z.CrewId == x.CrewId));\r\n\r\n //Exclude Non valid trainees\r\n var eligibleTraineeIds = Object.keys(traineeEligibility).filter(x => traineeEligibility[x] == \"NotStarted\" || traineeEligibility[x] == \"ValidPhase\" || traineeEligibility[x] == \"FailedCertificate\").map(Number);\r\n var eligibleTrainees = inactiveTrainees.filter(x => eligibleTraineeIds.includes(x.CrewId));\r\n eligibleTrainees.forEach(function (trainee) { trainee.EligibilityStatus = true });\r\n createNewPhaseTrainees(groundDuty, course, eligibleTrainees);\r\n\r\n // Merge eligibleTrainees (inactive) with CourseTrainees (eligible & active)\r\n course.CourseTrainees.forEach(function (trainee) { trainee.EligibilityStatus = true });\r\n course.CourseTrainees.push(...eligibleTrainees);\r\n\r\n // Non eligible trainees\r\n var nonEligibleTrainees = inactiveTrainees.filter(x => !eligibleTraineeIds.includes(x.CrewId));\r\n course.NonEligibleTrainees = nonEligibleTrainees;\r\n\r\n nonEligibleTrainees.forEach(function (trainee) {\r\n trainee.EligibilityStatus = false;\r\n trainee.EligibilityDesc = traineeEligibility[trainee.CrewId];\r\n });\r\n\r\n // Result:\r\n // CourseTrainees = eligible trainees (active or new)\r\n // Non EligibleTrainees\r\n }\r\n\r\n /**\r\n * Create first phase foreach trainee\r\n * @param {object} groundDuty \r\n * @param {object} course \r\n * @param {array} trainees Eligible trainees that haven't yet started training\r\n */\r\n function createNewPhaseTrainees(groundDuty, course, trainees) {\r\n //Match GroundDutyNos with PhaseDutyNos\r\n var crewCoursePhaseDutyNos = [];\r\n var groundDutyTraineeDutyNos = [];\r\n course.CrewCoursePhases.forEach(function(coursePhase){\r\n crewCoursePhaseDutyNos = crewCoursePhaseDutyNos.concat(coursePhase.GroundDutyCodes);\r\n });\r\n\r\n groundDuty.Trainees.forEach(function(relatedDuty){\r\n groundDutyTraineeDutyNos.push(relatedDuty.GroundDutyNo.toString());\r\n });\r\n \r\n var relatedDutyNos = crewCoursePhaseDutyNos.filter(x => groundDutyTraineeDutyNos.includes(x));\r\n var relatedPhases = course.CrewCoursePhases.filter(x => x.GroundDutyCodes.some(gdc => relatedDutyNos.includes(gdc)));\r\n\r\n //From related phases, select first in order\r\n relatedPhases = $filter('orderBy')(relatedPhases, 'OrderNo');\r\n var firstPhase = relatedPhases[0];\r\n\r\n trainees.forEach(function (trainee) {\r\n trainee.Phases = [{\r\n PhaseId: firstPhase.PhaseId,\r\n PhaseStatus: \"InProgress\",\r\n RepeatRequestedItems: [],\r\n isSelected: true //selectedPhase\r\n }];\r\n });\r\n }\r\n\r\n function getGroundCourseTrainees(groundDuty, courseId) {\r\n var trainees = [];\r\n groundDuty.RelatedGroundDuties.filter(x => x.Courses && x.Courses.map(function (course) { return course.CourseId }).includes(courseId)).forEach(function (item) {\r\n item.CrewMembers.forEach(function (crewMember) {\r\n var trainee = { AimsId: crewMember.AIMS_ID, CrewId: crewMember.Id, Name: crewMember.Name, PositionCode: crewMember.PositionCode }\r\n trainees.push(trainee);\r\n })\r\n })\r\n return trainees;\r\n }\r\n\r\n function calculatePhaseStatus(phase, course) {\r\n course.CourseTrainees.forEach(function (trainee) {\r\n var traineePhase = trainee.Phases.find(x => x.PhaseId == phase.PhaseId);\r\n if (traineePhase && traineePhase.PhaseStatus == \"InProgress\") {\r\n phase.Status = \"InProgress\";\r\n } else if (!traineePhase && phase.Status != \"InProgress\") {\r\n phase.Status = \"Pending\";\r\n } else if (traineePhase && traineePhase.PhaseStatus == \"Completed\" && phase.Status != \"InProgress\") {\r\n phase.Status = \"Completed\";\r\n }\r\n //Selected phase, If at least one trainee has it selected\r\n if(traineePhase && !phase.isSelected){\r\n phase.isSelected = traineePhase.isSelected;\r\n }\r\n });\r\n }\r\n\r\n function mergeSyllabusWithHistory(trainees, phases) {\r\n var flatSullabusItems = [];\r\n trainees.forEach(function (trainee) {\r\n trainee.Phases.forEach(function (phase) {\r\n phase.Sessions.forEach(function (session) {\r\n session.Items.forEach(function (item) {\r\n var flatItem = createFlatHistorySullabusItem(trainee, phase, session, item);\r\n flatSullabusItems.push(flatItem);\r\n });\r\n });\r\n });\r\n });\r\n\r\n\r\n phases.filter(x => x.Syllabus).forEach(function (phase, index, array) {\r\n phase.Syllabus.SyllabusItems.forEach(function (syllabusItem) {\r\n syllabusItem.History = flatSullabusItems.filter(item => item.ItemId == syllabusItem.Id);\r\n })\r\n });\r\n var hasPreviousSessions = flatSullabusItems.length > 0;\r\n\r\n return hasPreviousSessions;\r\n }\r\n\r\n function createFlatHistorySullabusItem(trainee, phase, session, item) {\r\n var flatItem = {\r\n CrewId: trainee.CrewId,\r\n PhaseId: phase.PhaseId,\r\n SessionId: session.SessionId,\r\n SessionComments: session.SessionComments,\r\n SubmissionDate: item.SubmissionDate,\r\n RepeatRequired: item.RepeatRequired,\r\n Tries: item.Tries,\r\n ItemId: item.SyllabusItemId,\r\n Grade: session.Grade,\r\n GradeType: session.GradeType,\r\n InstructorName: session.InstructorName,\r\n InstructorAimsId: session.InstructorAimsId\r\n };\r\n return flatItem;\r\n }\r\n\r\n /**\r\n * Add Session to Storage\r\n * @memberof TrainingSessionFactory\r\n * @param {object} Session\r\n */\r\n function addSessionToStorage(session) {\r\n return IndexedDBService.add(objType, session);\r\n };\r\n\r\n /**\r\n * Update Session to Storage\r\n * @memberof TrainingSessionFactory\r\n * @param {object} Session\r\n */\r\n function saveSessionToStorage(session) {\r\n return IndexedDBService.put(objType, session);\r\n };\r\n\r\n function submitSession(submittedSession, callback) {\r\n var traingingApiURL = apiUrl + '/Training/SubmitTraining';\r\n return $http.post(traingingApiURL, submittedSession, { 'Content-Type': 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Authorize Trainee for submission\r\n * @param {string} credentials Trainee's password, username, crewId, position\r\n * @param {function} callback \r\n * @param {function} errorCallback \r\n */\r\n function authorizeTrainee(credentials, callback, errorCallback) {\r\n return $http.post(apiUrl + '/Training/AuthorizeTrainee', credentials, { 'Content-Type': 'application/json' })\r\n .then(callback)\r\n .catch(errorCallback);\r\n }\r\n\r\n function releaseSession(submittedSessions, callback, errorCallback) {\r\n var traingingApiURL = apiUrl + '/Training/ReleaseSession';\r\n return $http.post(traingingApiURL, submittedSessions, { 'Content-Type': 'application/json' })\r\n .then(callback)\r\n .catch(errorCallback);\r\n }\r\n return service;\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n \r\n a3_pilot_reports.controller('DebugCtrl', DebugCtrl);\r\n\t\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name DebugCtrl\r\n * @description \r\n * Manage Debug view\r\n * @ngInject\r\n */ \r\n\tfunction DebugCtrl($location, $scope, UserFactory, DebugFactory, localStorageMD5Service) {\r\n\t\t\t\r\n\t\t$scope.isSecure = UserFactory.isSecure();\r\n\t\t$scope.adminkey = \"\";\r\n\t\t$scope.authorized = false;\r\n\r\n\t\t$scope.checkAuthorized = function() {\r\n\t\t\tvar verify = localStorageMD5Service.md5hash($scope.adminkey);\r\n\t\t\tDebugFactory.CheckAuthorized(verify, function(responseData){\r\n\t\t\t\tif ($scope.authorized != responseData.data.data) {\r\n\t\t\t\t\t$scope.authorized = responseData.data.data;\r\n\t\t\t\t\t$scope.refreshStoredValues();\r\n\t\t\t\t}\r\n\t\t\t}).catch(function(error){\r\n\t\t\t\t$scope.authorized = responseData.Data;\r\n\t\t\t\tconsole.error('Wrong Password', error.status, error.statusText);\r\n\t\t\t});\r\n\t\t}\r\n\r\n\r\n\t\t// show logged user info\r\n\t\tvar user = UserFactory.getUser();\r\n\t\t$scope.logged_user_info = \"-user has not logged in-\";\r\n\t\tif (user)\r\n\t\t\t$scope.logged_user_info = user.aimsId + ' - ' + user.name;\r\n\r\n\t\t$scope.storedValues = [];\r\n\t\t$scope.addKeyName = null;\r\n\r\n $scope.updateAll = updateAll;\r\n \r\n $scope.refreshStoredValues = refreshStoredValues;\r\n \r\n $scope.add = add;\r\n \r\n $scope.update = update;\r\n \r\n $scope.delete = deleteItem;\r\n \r\n $scope.exit = exit;\r\n \r\n /**\r\n * Update all the local storage \r\n * @memberof DebugCtrl\r\n */\r\n function updateAll()\r\n {\r\n try {\r\n var items = JSON.parse($scope.updateAllJson); \r\n \r\n for(var i=0; i 0) {\r\n\t\t\t\t\talert('Key exists!');\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tlocalStorageMD5Service.set(key, [\"empty\"])\r\n\t\t\t\t$scope.refreshStoredValues();\r\n\t\t\t\t$scope.addKeyName = null;\r\n\t\t\t} catch (e) {\r\n\t\t\t\talert('Error: ' + e.message || e.errorMessage);\r\n\t\t\t}\r\n\t\t}\r\n \r\n /**\r\n * Update an existing local storage key\r\n * @memberof DebugCtrl\r\n * @param {object} item\r\n */\r\n function update(item) {\r\n\t\t\ttry {\r\n\t\t\t\tvar obj = null;\r\n\t\t\t\tif (item.value != '') obj = angular.fromJson(item.value);\r\n\t\t\t\tlocalStorageMD5Service.set(item.key, obj);\r\n\t\t\t\t$scope.refreshStoredValues();\r\n\t\t\t} catch (e) {\r\n\t\t\t\talert('Error: ' + e.message || e.errorMessage);\r\n\t\t\t}\r\n\t\t}\r\n\r\n /**\r\n * delete an existing local storage key\r\n * @memberof DebugCtrl\r\n * @param {object} item\r\n */\r\n function deleteItem(item) {\r\n\t\t\tif (confirm('Confirm deletion of key ' + item.key)) {\r\n\t\t\t\tlocalStorageMD5Service.remove(item.key);\r\n\t\t\t\t$scope.refreshStoredValues();\r\n\t\t\t}\r\n\t\t}\r\n \r\n /**\r\n * Redirect to main Menu\r\n * @memberof DebugCtrl\r\n */ \r\n function exit() {\r\n\t\t\t$location.path(\"/\");\r\n\t\t}\r\n\r\n\t}\r\n\r\n \r\n })(); ","(function () {\r\n 'use strict';\r\n a3_pilot_reports.factory('DebugFactory', DebugFactory);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc factory\r\n * @name DebugFactory\r\n * @description \r\n * Authorize check from API ...\r\n * @ngInject\r\n */\r\n function DebugFactory(GenericService, $http, $q, apiUrl, LogService){\r\n /**\r\n * Initialize Debug\r\n * @memberof DebugFactory\r\n */\r\n var service = {\r\n CheckAuthorized: CheckAuthorized\r\n }\r\n function CheckAuthorized(value, callback){\r\n return $http.get(apiUrl + '/debug/CheckAuthorized/' + value, { 'Content-Type': 'application/json' })\r\n .then(callback);\r\n }\r\n\r\n return service;\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n \r\na3_pilot_reports.controller('ResetDeviceCtrl', ResetDeviceCtrl);\r\n\r\n /**\r\n * @memberof PilotReports\r\n * @ngdoc controller\r\n * @name ResetDeviceCtrl\r\n * @description \r\n * Manage Reset view\r\n * @ngInject\r\n */ \r\nfunction ResetDeviceCtrl($location,$route,$scope, $log, DataCleanerFactory,UserFactory, localStorageMD5Service) {\r\n\t\t$scope.isSecure = UserFactory.isSecure();\r\n\t\t\r\n\t\t// show logged user info\r\n\t\tvar user = UserFactory.getUser();\r\n\t\t$scope.logged_user_info = \"-user has not logged in-\";\r\n\t\tif (user)\r\n\t\t\t$scope.logged_user_info = user.aimsId + ' - ' + user.name;\r\n\t\t\r\n\t\t$scope.resetDevice = resetDevice;\r\n \r\n $scope.cancelReset = cancelReset;\r\n\r\n /**\r\n * Reset Device storage\r\n * @memberof ResetDeviceCtrl\r\n */\r\n function resetDevice(){\r\n\t\t\tDataCleanerFactory.deleteAllData();\r\n\t\t\tbootbox.alert(\"Your device has been reset.\", function() {\r\n\t\t\t\t$location.path(\"/login\");\r\n\t\t\t\t$scope.$apply();\r\n\t\t\t});\r\n\t\t}\r\n\t\t\r\n /**\r\n * Cancel Reset and go to main page.\r\n * @memberof ResetDeviceCtrl\r\n */\r\n function cancelReset(){\r\n\t\t\t$location.path(\"/\");\r\n\t\t}\r\n}\t\t\t\t\t\t \r\n\r\n })(); "]}