{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/_filters.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/uniquebycoursecode.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/datetime.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/program.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/pattern.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/paging.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/sentencecase.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/day.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/location.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/type.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/filters/time.filter.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/_controllers.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/addedtoplanner.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/classdetail.modal.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/confirmics.modal.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/firstrun.modal.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/planner.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/recentsearches.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/removefromplanner.modal.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/timetable.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/controllers/updatecourseselection.modal.controller.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/directives/_directives.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/directives/classblock.directive.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/directives/plannercoursecard.directive.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/directives/recentsearchcard.directive.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/directives/searchresult.directive.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/directives/searchresultrow.directive.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/_timetable.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/resources/_resources.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/resources/alerts.service.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/resources/planner.factory.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/resources/recentsearches.factory.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/resources/storage.service.js","webpack:///./Usc.Web/scripts/modules/_timetableModule/resources/timetable.factory.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","moduleName","angular","filter","input","result","found","length","push","j","courseCode","type","hourSection","hoursMinutes","split","parseInt","minSection","filters","career","hiddenByProgramFilter","clsNo","classes","classNo","hiddenTitle","currentPage","perPage","start","end","where","el","hiddenByLocationFilter","allClassesClosed","slice","toUpperCase","substr","toLowerCase","charCodeAt","timetableService","validDays","days","dayFilter","meetingDay","indexOf","checkForVisibleChildren","filterVal","locations","isOnline","val","item","room","startsWith","classType","hour","timeFilter","undefined","meetingStartTime","replace","meetingEndTime","controller","$scope","storageService","subscribe","vm","addedToPlanner","getPlanner","e","args","$uibModalInstance","all","class","course","courseDetailHref","close","dismiss","$timeout","$filter","getIcs","icsMsg","blob","downloadLink","icsBody","forEach","dtStamp","day","location","dtStartTime","dtFinishTime","dtEnd","icsEvent","Date","startTime","finishTime","startDate","meetingStartDate","finishDate","meetingEndDate","title","classDesc","getFullYear","getMonth","getDate","getHours","getMinutes","navigator","userAgent","match","Blob","window","msSaveOrOpenBlob","document","createElement","href","escape","download","body","appendChild","click","removeChild","ok","$rootScope","plannerFactory","this","planner","scaffold","onlineClassCount","onlineCourseCount","online","let","hours","concat","getOnline","$watch","newVal","oldVal","getFromLocalStorage","fromSearch","recent","getRecent","arg","validationData","v","index","description","map","termId","getValidatedCourseTerms","then","removalList","y","status","data","splice","storeRecent","cancel","recentSearchesFactory","alertsService","$uibModal","$q","timetableConfig","showFirstRunModal","GODMODE","root","querySelector","overlayInterval","dataset","now","prevSearchTerm","allClassesClosedMessage","allClosedMessage","init","courses","loadingCourses","results","noResults","getClasses","alerts","locationFilters","DAYS","showFilters","showError","DBErrorMsg","noActiveFilters","HAS_LOCALSTORAGE","localStorage","LOCAL_STORE_KEY","lastModalDate","toString","getTime","getTerms","getCampus","resp","terms","term","godsOnly","tempLocations","camp","sort","a","b","unshift","checkParams","id","resetFilters","refresh","filterResults","activeFilters","time","badgeHour","timeFilters","h","countVisibleResults","countTotalPages","showHideActiveFilters","submitSearch","updateFilter","weekend","program","programFilters","typeFilters","selectedfilters","paging","setTerm","setSelectedTerm","selectedTerm","searching","ids","courseId","getClassBySearchTerm","offeredLocations","vv","self","join","filterNewResults","getElementById","childElementCount","visibleResultsCount","allHidden","hiddenByFilter","enrolmentStatus","allClassesHidden","totalPages","Math","ceil","clearSearch","arr","seed","populateTimeFilter","searchTerm","errorMsg","showAll","getSelectedTerm","showAllFrom","clearPlannerUi","submitSearchOnBlur","typeaheadSelect","force","fullDescription","hasVisibleChildren","add","open","templateUrl","backdrop","courseName","current","validClasses","classTypes","currentClassNos","toRemove","buildUniqueList","initial","parsed","uniqueArray","isCurrentClasses","isMultiday","hasMultiday","toAdd","SetSelectedClass","showCurrent","markForRemoval","checked","getNgOption","classSection","classMeetingNo","directive","scope","classData","restrict","template","link","cssClass","clash","red","trim","showClassDetail","response","modal","resolve","meetingDayNo","removeFromPlanner","inPlanner","fromPlanner","updateSelectionModal","k","selectedClassIds","getSelectedClassIds","classToAdd","classesToAdd","addToPlanner","search","remove","$sce","currentSort","reverseSort","sortByColumn","col","sortBy","hasHiddenTitles","some","x","trustAsHtml","noteText","noteSeq","element","classList","hideDayTime","timetableControllers","timetableDirectives","timetableFilters","timetableResources","constant","checkLocalStorage","keyValue","queryString","params","isGodMode","app","uscApp","requires","factory","prefix","msg","service","notify","$emit","addClassToPlanner","checkUnique","checkClashes","exists","existingElement","duration","round","checkDayForClashes","hasClasses","isAdd","q","finishHour","kClassEndDate","kClassStartDate","newEndDate","newStartDate","kClass","kClasses","checkFollowingClasses","addCourseToPlanner","fromModal","uniqueInPlanner","SIDEBAR_MAX","foundOnlineOffering","currentClass","currentClassB","classInstance","hasClash","exactClash","courseFound","classFound","getDay","plannerItem","plannerItemStart","plannerItemEnd","newItemStart","newItemEnd","newItemStartDate","newItemEndDate","plannerItemStartDate","plannerItemEndDate","parseFloat","addAlert","storePlanner","isCourse","doRemoveFromPlanner","size","keys","indexes","courseIds","cls","updateUi","addedItem","scopeItem","serverDs","serverData","serverItem","godMode","temp","findIndex","$new","JSON","stringify","parse","getItem","$http","URL_BASE","currentTerms","getCourses","promise","when","getCourseDetails","event","callback","handler","$on","query","getEmployee","emplId","method","url","courseList","CourseList","f","jClass"],"mappings":"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","file":"timetable-bundle-8670e521721eb5dce6de.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 87);\n","import uniqueByCourseCode from './uniquebycoursecode.filter';\r\nimport dateTime from './datetime.filter';\r\nimport program from './program.filter';\r\nimport pattern from './pattern.filter';\r\nimport paging from './paging.filter';\r\nimport sentenceCase from './sentencecase.filter';\r\nimport day from './day.filter';\r\nimport location from './location.filter';\r\nimport type from './type.filter';\r\nimport time from './time.filter';\r\n\r\nconst moduleName = 'usc.timetable.filters';\r\n\r\nangular.module(moduleName, [])\r\n .filter('uniqueByCourseCode', uniqueByCourseCode)\r\n .filter('dateTime', dateTime)\r\n .filter('program', program)\r\n .filter('pattern', pattern)\r\n .filter('paging', paging)\r\n .filter('sentenceCase', sentenceCase)\r\n .filter('day', ['timetableService', day])\r\n .filter('location', ['timetableService', location])\r\n .filter('type', ['timetableService', type])\r\n .filter('time', ['timetableService', time]);\r\n\r\nexport default moduleName;","export default function () {\r\n return function (input) {\r\n if (input) {\r\n var result = [], found = false;\r\n\r\n if (input.length) {\r\n result.push(input[0]);\r\n }\r\n\r\n for (var i = 0, l = input.length; i < l; i++) {\r\n\r\n for (var j = 0; j < result.length; j++) {\r\n\r\n if (result[j].courseCode === input[i].courseCode) {\r\n found = true;\r\n break;\r\n } else {\r\n found = false;\r\n }\r\n }\r\n\r\n if (!found) {\r\n result.push(input[i]);\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n return null;\r\n };\r\n};","export default function () {\r\n return function (input, type) {\r\n if (input) {\r\n if (type === 'time') {\r\n var hoursMinutes = input.split(/[.:]/);\r\n var hourSection = parseInt(hoursMinutes[0], 10);\r\n var minSection = parseInt(hoursMinutes[1], 10) > 0\r\n ? ':' + parseInt(hoursMinutes[1], 10)\r\n : '';\r\n\r\n if (hourSection > 12) {\r\n input = (hourSection - 12) + minSection + 'pm';\r\n } else if (hourSection === 12 && minSection === '') {\r\n input = hourSection + 'noon';\r\n } else if (hourSection === 12 && minSection !== '') {\r\n input = hourSection + minSection + 'pm';\r\n } else {\r\n input = hourSection + minSection + 'am';\r\n }\r\n return input;\r\n } else {\r\n var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\r\n return days[input - 1];\r\n }\r\n }\r\n return null;\r\n };\r\n};","export default function () {\r\n return function (input, key, filters) {\r\n\r\n for (var i = 0, l = input.length; i < l; i++) {\r\n if (input[i].career === filters[key] || filters[key] === 'Show all') {\r\n input[i].hiddenByProgramFilter = false;\r\n } else {\r\n input[i].hiddenByProgramFilter = true;\r\n }\r\n }\r\n return input;\r\n }\r\n};","export default function () {\r\n return function (input) {\r\n for (var i = 0, l = input.length; i < l; i++) {\r\n for (var j = 1, clsNo = input[i].classes.length; j < clsNo; j++)\r\n if (input[i].classes[j].classNo === input[i].classes[j - 1].classNo) {\r\n input[i].classes[j].hiddenTitle = true;\r\n } else {\r\n input[i].classes[j].hiddenTitle = false;\r\n }\r\n }\r\n }\r\n};","export default function () {\r\n return function (input, currentPage, perPage) {\r\n\r\n var start = (currentPage - 1) * perPage,\r\n end = start + perPage;\r\n\r\n var output = input.where(function (el) {\r\n return !el.hiddenByProgramFilter && !el.hiddenByLocationFilter && !el.allClassesClosed;\r\n });\r\n\r\n return (output || []).slice(start, end);\r\n }\r\n};","export default function () {\r\n return function (input) {\r\n input = input[0].toUpperCase() + input.substr(1).toLowerCase();\r\n if (input.charCodeAt(input.length - 1) === 0) {\r\n input = input.substr(0, input.length - 1) + '.';\r\n }\r\n return input;\r\n }\r\n};","export default timetableService => {\r\n return function (input, key, filters) {\r\n\r\n var validDays = [],\r\n days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\r\n dayFilter = filters[key],\r\n i;\r\n\r\n for (i = 0; i < dayFilter.length; i++) {\r\n if (dayFilter[i] === true) {\r\n validDays.push(days[i]);\r\n }\r\n }\r\n\r\n for (i = 0; i < input.length; i++) {\r\n if (!input[i].classes)\r\n continue;\r\n\r\n for (var j = 0, m = input[i].classes.length; j < m; j++) {\r\n var c = input[i].classes[j];\r\n if (c.meetingDay && validDays.indexOf(c.meetingDay) === -1) {\r\n c[key + 'Filter'] = false;\r\n } else {\r\n c[key + 'Filter'] = true;\r\n }\r\n }\r\n\r\n input[i] = timetableService.checkForVisibleChildren(input[i], filters);\r\n }\r\n return input;\r\n }\r\n};","export default timetableService => {\r\n return function (input, key, filters) {\r\n\r\n var filterVal = filters[key];\r\n\r\n for (var i = 0, l = input.length; i < l; i++) {\r\n for (var j = 0, m = input[i].classes.length; j < m; j++) {\r\n var c = input[i].classes[j];\r\n if (filterVal === 'Show all' || filterVal === c[key]) {\r\n c[key + 'Filter'] = true;\r\n } else {\r\n c[key + 'Filter'] = false;\r\n }\r\n }\r\n\r\n input[i] = timetableService.checkForVisibleChildren(input[i], filters);\r\n input[i].hiddenByLocationFilter = input[i].locations.indexOf(filterVal) === -1 &&\r\n filterVal !== 'Show all';\r\n }\r\n\r\n return input;\r\n }\r\n};","export default timetableService => {\r\n return function (input, key, filters) {\r\n var val = filters[key],\r\n isOnline,\r\n c, // the class item for the inner loop\r\n item; // the course item for the outer loop\r\n\r\n for (var i = 0, l = input.length; i < l; i++) {\r\n item = input[i];\r\n\r\n for (var j = 0, m = item.classes.length; j < m; j++) {\r\n c = item.classes[j];\r\n isOnline = c.room.startsWith('ONL') || c.classType.startsWith('ONL');\r\n if (val === 'Show all' ||\r\n val.startsWith('On-campus') && !isOnline ||\r\n val.startsWith('Online') && isOnline) {\r\n c[key + 'Filter'] = true;\r\n } else {\r\n c[key + 'Filter'] = false;\r\n }\r\n }\r\n\r\n input[i] = timetableService.checkForVisibleChildren(item, filters);\r\n }\r\n\r\n return input;\r\n }\r\n};","export default timetableService => {\r\n return function (input, key, filters) {\r\n\r\n var hour = filters[key].hour,\r\n type = filters[key].type,\r\n c,\r\n i,\r\n j,\r\n m,\r\n l = input.length;\r\n\r\n if (hour === null || type === null || type === 'Show all') {\r\n for (i = 0; i < l; i++) {\r\n m = input[i].classes;\r\n for (j = 0; j < m.length; j++) {\r\n m[j].timeFilter = true;\r\n }\r\n\r\n input[i] = timetableService.checkForVisibleChildren(input[i], filters);\r\n }\r\n } else {\r\n for (i = 0; i < l; i++) {\r\n m = input[i].classes;\r\n for (j = 0; j < m.length; j++) {\r\n c = m[j];\r\n c.timeFilter = false;\r\n\r\n if (c.meetingStartTime !== undefined && c.meetingStartTime !== null) {\r\n\r\n if (type === 'Starting after') {\r\n if (hour &&\r\n parseInt(c.meetingStartTime.replace(':', '')) >=\r\n parseInt(hour.replace(':', ''))) {\r\n c.timeFilter = true;\r\n }\r\n } else if (type === 'Finishing before') {\r\n if (hour &&\r\n parseInt(c.meetingEndTime.replace(':', '')) <=\r\n parseInt(hour.replace(':', ''))) {\r\n c.timeFilter = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n input[i] = timetableService.checkForVisibleChildren(input[i], filters);\r\n }\r\n }\r\n return input;\r\n }\r\n};","import addedToPlannerController from './addedtoplanner.controller';\r\nimport classDetailModalController from './classdetail.modal.controller';\r\nimport confirmIcsModalController from './confirmics.modal.controller';\r\nimport firstRunModalController from './firstrun.modal.controller';\r\nimport plannerController from './planner.controller';\r\nimport recentSearchesController from './recentsearches.controller';\r\nimport removeFromPlannerModalController from './removefromplanner.modal.controller';\r\nimport timetableController from './timetable.controller';\r\nimport updateCourseSelectionModalController from './updatecourseselection.modal.controller';\r\n\r\nconst moduleName = 'usc.timetable.controllers';\r\n\r\nangular.module(moduleName, [])\r\n .controller('addedToPlannerCtrl', ['$scope', 'timetableService', 'storageService', addedToPlannerController])\r\n .controller('ClassDetailModalCtrl', ['$scope', '$uibModalInstance', 'c', 'all', classDetailModalController])\r\n .controller('ConfirmIcsModalCtrl', ['$scope', '$uibModalInstance', '$timeout', 'addedToPlanner', '$filter', confirmIcsModalController])\r\n .controller('FirstRunModalCtrl', ['$scope', '$uibModalInstance', firstRunModalController])\r\n .controller('uscTimetablePlannerController', ['$scope', '$rootScope', 'timetableService', 'plannerFactory', plannerController])\r\n .controller('recentSearchesCtrl', ['$scope', 'timetableService', 'storageService', recentSearchesController])\r\n .controller('RemoveCourseFromPlannerModalCtrl', ['$scope', '$uibModalInstance', removeFromPlannerModalController])\r\n .controller('UscTimetableController', ['$scope', '$rootScope', 'timetableService', 'plannerFactory', 'recentSearchesFactory', 'alertsService', '$uibModal', '$filter', '$timeout', '$q', 'timetableConfig', timetableController])\r\n .controller('UpdateClassSelectionModalCtrl', ['$scope', '$uibModalInstance', '$filter', 'courseCode', 'courseName', 'current', 'classes', updateCourseSelectionModalController]);\r\n\r\nexport default moduleName;","/**\r\n * Display a list of course cards in the added to planner UI container\r\n * @param {} $scope \r\n * @param {} timetableService \r\n * @param {} storageService \r\n * @returns {} \r\n */\r\nexport default function ($scope, timetableService, storageService) {\r\n\r\n /**\r\n * Update the added to planner list when selected term updates\r\n */\r\n timetableService.subscribe($scope, 'selectedTermChanged', () => {\r\n $scope.vm.addedToPlanner = storageService.getPlanner();\r\n });\r\n\r\n /**\r\n * Receive model updates when the recent courses object is updated in the service\r\n */\r\n timetableService.subscribe($scope, 'plannerChanged', (e, args) => {\r\n $scope.vm.addedToPlanner = args.addedToPlanner;\r\n });\r\n};","export default function ($scope, $uibModalInstance, c, all) {\r\n\r\n $scope.class = c.class;\r\n $scope.course = c;\r\n $scope.all = all;\r\n\r\n $scope.courseDetailHref = '/learn/courses-and-programs/courses/' +\r\n $scope.course.courseCode.toLowerCase();\r\n\r\n $scope.close = function() {\r\n $uibModalInstance.dismiss();\r\n };\r\n\r\n};","export default function ($scope, $uibModalInstance, $timeout, addedToPlanner, $filter) {\r\n\r\n $scope.getIcs = function () {\r\n\r\n var icsHeader = 'BEGIN:VCALENDAR\\r\\nVERSION:2.0\\r\\nPRODID:-//UniSC//NONSGML v1.0//EN\\r\\nX-WR-CALNAME:USC timetable planner\\r\\n',\r\n email = 'timetable@usc.edu.au',\r\n icsBody = '',\r\n icsMsg;\r\n\r\n angular.forEach(addedToPlanner, function (el) {\r\n\r\n if (el.hasOwnProperty('class')) {\r\n\r\n var icsEvent,\r\n dtStamp = new Date(),\r\n day = el.class.meetingDay,\r\n startTime = $filter('date')(el.class.meetingStartTime, \"HH:MM\").replace(\":\", \"\"),\r\n finishTime = $filter('date')(el.class.meetingEndTime, \"HH:MM\").replace(\":\", \"\"),\r\n startDate = el.class.meetingStartDate,\r\n finishDate = el.class.meetingEndDate,\r\n location = el.class.room + ' ' + el.class.location,\r\n title = el.courseCode + ' ' + el.class.classDesc,\r\n dtStartTime = $filter('date')(startDate, 'yyyyMMdd') + 'T' + startTime + '00',\r\n dtFinishTime = $filter('date')(startDate, 'yyyyMMdd') + 'T' + finishTime + '00',\r\n dtEnd = $filter('date')(finishDate, 'yyyyMMdd') + 'T' + finishTime + '00';\r\n\r\n icsEvent = 'BEGIN:VEVENT\\r\\nUID:' + email + '\\r\\nDTSTAMP:' + dtStamp.getFullYear() + (dtStamp.getMonth() + 1) + (dtStamp.getDate() + 1) + 'T' + dtStamp.getHours() + dtStamp.getMinutes() + '\\r\\n';\r\n icsEvent += 'DTSTART:' + dtStartTime + '\\r\\nDTEND:' + dtFinishTime + '\\r\\nLOCATION:' + location + '\\r\\nSUMMARY:' + title + '\\r\\nRRULE:FREQ=WEEKLY;UNTIL=' + dtEnd + ';BYDAY=' + day.substr(0, 2).toUpperCase() + '\\r\\nEND:VEVENT\\r\\n';\r\n\r\n icsBody += icsEvent;\r\n }\r\n });\r\n\r\n icsMsg = icsHeader + icsBody + 'END:VCALENDAR';\r\n\r\n if (!navigator.userAgent.match(/msie|trident/i)) {\r\n\r\n var downloadLink = document.createElement(\"a\");\r\n downloadLink.href = 'data:text/calendar;charset=utf-8,\\r\\n' + escape(icsMsg);\r\n downloadLink.download = \"Timetable planner.ics\";\r\n //when an event is triggered programmatically which already exists in the client side, it calls $apply within $digest for the second time\r\n // which causing Action Already In Progress error. \r\n //To avoid this we need to move the call to event outside of the digest, by using $timeout(fn, 0, false)\r\n //refer to https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply\r\n $timeout(function () {\r\n document.body.appendChild(downloadLink);\r\n downloadLink.click();\r\n document.body.removeChild(downloadLink);\r\n }, 0, false);\r\n\r\n }\r\n else {\r\n var blob = new Blob([icsMsg]);\r\n window.navigator.msSaveOrOpenBlob(blob, 'Timetable planner.ics');\r\n }\r\n };\r\n\r\n $scope.close = function () {\r\n $uibModalInstance.dismiss('cancel');\r\n };\r\n\r\n};","export default function ($scope, $uibModalInstance) {\r\n\r\n $scope.ok = function () {\r\n $uibModalInstance.close(true);\r\n };\r\n\r\n};","export default function ($scope, $rootScope, timetableService, plannerFactory) {\r\n var vm = this;\r\n\r\n vm.planner = plannerFactory.scaffold();\r\n\r\n function getOnline() {\r\n let online = [];\r\n\r\n vm.planner.forEach(day => {\r\n if (day.hours[0].classes.length) {\r\n online = online.concat(day.hours[0].classes);\r\n }\r\n });\r\n\r\n return online.length ? online : undefined;\r\n }\r\n\r\n timetableService.subscribe($scope, 'plannerChanged',\r\n function plannerUpdated(e, args) {\r\n vm.addedToPlanner = args.addedToPlanner;\r\n vm.onlineClassCount = args.onlineClassCount;\r\n vm.onlineCourseCount = args.onlineCourseCount;\r\n vm.planner = args.planner;\r\n vm.online = getOnline();\r\n });\r\n\r\n $rootScope.$watch('selectedTerm', function (newVal, oldVal) {\r\n if (newVal && newVal !== oldVal) {\r\n plannerFactory.getFromLocalStorage();\r\n }\r\n }, true);\r\n};","export default function ($scope, timetableService, storageService) {\r\n\r\n this.recent = storageService.getRecent();\r\n\r\n /**\r\n * Receive model updates when the recent courses object is updated in the service\r\n */\r\n timetableService.subscribe($scope, 'recentChanged', (e, arg) => this.recent = arg);\r\n\r\n if (this.recent.length) {\r\n\r\n // Get a list of history objects to be validated against the server side\r\n // exclude recent objects representing saved searches - only valid course items\r\n var validationData = this.recent.filter((v, i) => {\r\n v.index = i;\r\n return v.description;\r\n }).map(v => {\r\n return { courseCode: v.courseCode, termId: v.termId, index: v.index };\r\n });\r\n\r\n var fromSearch = this.recent.filter((v, i) => {\r\n v.index = i;\r\n return !v.description;\r\n });\r\n\r\n // possible we have no courses to check\r\n if (validationData.length) {\r\n // Call the server to get the course and term changes in the recently viewed\r\n timetableService.getValidatedCourseTerms(validationData).then(removalList => {\r\n var item,\r\n i,\r\n y;\r\n\r\n if (removalList.status.toLowerCase() === 'success' &&\r\n removalList.data &&\r\n removalList.data.length > 0) {\r\n // We have recieved some items to remove from the recently viewed list as they are no longer available.\r\n for (i = 0; i < removalList.data.length; i++) {\r\n item = removalList.data[i];\r\n for (y = 0; y < this.recent.length; y++) {\r\n if (this.recent[y].courseCode === item.courseCode &&\r\n this.recent[y].termId === item.termId) {\r\n this.recent.splice(y, 1);\r\n }\r\n }\r\n }\r\n\r\n if (fromSearch.length) {\r\n fromSearch.forEach(v => this.recent.splice(v.index, 0, v));\r\n }\r\n\r\n storageService.storeRecent(this.recent);\r\n }\r\n });\r\n }\r\n }\r\n};","export default function ($scope, $uibModalInstance) {\r\n $scope.ok = function () {\r\n $uibModalInstance.close(true);\r\n };\r\n\r\n $scope.cancel = function () {\r\n $uibModalInstance.dismiss('cancel');\r\n };\r\n};","export default function ($scope, $rootScope, timetableService, plannerFactory, recentSearchesFactory, alertsService, $uibModal, $filter, $timeout, $q, timetableConfig) {\r\n\r\n var showFirstRunModal = !timetableConfig.GODMODE,\r\n root = document.querySelector('[ng-controller=\"UscTimetableController\"]'),\r\n overlayInterval = root.dataset.overlayInterval || 28,\r\n now = new Date();\r\n\r\n // punting this into rootscope rather than creating another service - constant value, so happy to cause a little pollution...\r\n $rootScope.allClassesClosedMessage = root.dataset.allClosedMessage;\r\n\r\n // When the term changes, update the UI via init(), which essentially resets the view\r\n timetableService.subscribe($scope, 'selectedTermChanged', function (e, arg) {\r\n init(arg);\r\n });\r\n\r\n // Raised when all courses for the selected teaching period are available\r\n timetableService.subscribe($scope, 'coursesChanged', function (e, arg) {\r\n $scope.courses = arg.data;\r\n $scope.loadingCourses = false;\r\n });\r\n\r\n timetableService.subscribe($scope, 'resultsChanged', function (e, arg) {\r\n $scope.results = arg;\r\n $scope.noResults = $scope.results.length === 0;\r\n getClasses();\r\n });\r\n\r\n // declare a bunch of scoped variables\r\n // arrays\r\n $scope.courses = [];\r\n $scope.results = [];\r\n $scope.alerts = alertsService.get();\r\n $scope.locationFilters = [];\r\n $scope.days = timetableConfig.DAYS;\r\n //bools\r\n $scope.showFilters = false;\r\n $scope.showError = false;\r\n $scope.DBErrorMsg = false;\r\n $scope.noActiveFilters = true;\r\n\r\n //numeric\r\n $scope.perPage = 3;\r\n $scope.currentPage = 1;\r\n\r\n // should we show the first-run modal -> godmode will supress the modal, regardless of elapsed days since last displayed\r\n if (!timetableConfig.GODMODE && timetableConfig.HAS_LOCALSTORAGE) {\r\n // check first run modal date\r\n if (localStorage[timetableConfig.LOCAL_STORE_KEY + 'acceptedConditions']) {\r\n var lastModalDate = new Date(localStorage[timetableConfig.LOCAL_STORE_KEY + 'acceptedConditions']);\r\n if (Object.prototype.toString.call(lastModalDate) === '[object Date]') {\r\n var then = lastModalDate.getTime(),\r\n diff = (now.getTime() - then) / 864e5; // millseconds -> seconds -> minutes -> hours -> days\r\n\r\n showFirstRunModal = diff > overlayInterval;\r\n }\r\n }\r\n }\r\n\r\n $q.all([timetableService.getTerms(), timetableService.getCampus()])\r\n .then(function (resp) {\r\n\r\n if (resp[0]) {\r\n\r\n if (resp[0].status === 'Error' || resp[0].data.length === 0) {\r\n $scope.DBErrorMsg = true;\r\n } else {\r\n $scope.terms = $filter('orderBy')(resp[0].data, 'fullDescription');\r\n\r\n if (!timetableConfig.GODMODE) {\r\n $scope.terms = $scope.terms.filter(term => !term.godsOnly);\r\n }\r\n }\r\n }\r\n if (resp[1]) {\r\n if (resp[1].status === 'Error' || resp[1].data.length === 0) {\r\n $scope.DBErrorMsg = true;\r\n } else {\r\n var tempLocations = [];\r\n for (var camp = 0; camp < resp[1].data.length; camp++) {\r\n tempLocations.push(resp[1].data[camp]);\r\n }\r\n\r\n $scope.locationFilters = tempLocations.sort(function (a, b) {\r\n if (a < b) {\r\n return -1;\r\n }\r\n if (a > b) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n $scope.locationFilters.unshift('Show all');\r\n }\r\n }\r\n\r\n $scope.loadingCourses = false;\r\n\r\n timetableService.checkParams($scope.terms.map(function (v) {\r\n return v.id;\r\n }));\r\n });\r\n\r\n //////////////////////////////////////////////////////\r\n // SCOPED FUNCTIONS\r\n /////////////////////////////////////////////////////\r\n\r\n //reseting filters\r\n $scope.resetFilters = function () {\r\n resetFilters(false);\r\n };\r\n\r\n $scope.refresh = function () {\r\n init();\r\n };\r\n\r\n /**\r\n * Filter the results set in response to a UI change\r\n * If no results exist, and the location filter triggers this function, force a search for all courses\r\n * @param {} key \r\n * @returns {} \r\n */\r\n $scope.filterResults = function (key) {\r\n $scope.loadingCourses = true;\r\n if ($scope.results.length) {\r\n if (key === 'time' && $scope.activeFilters.time.hour !== null) {\r\n $scope.badgeHour = $scope.timeFilters.hour.where(function (h) {\r\n return h.value === $scope.activeFilters.time.hour;\r\n })[0].key;\r\n }\r\n\r\n $scope.results = $filter(key)($scope.results, key, $scope.activeFilters);\r\n $scope.currentPage = 1;\r\n\r\n countVisibleResults(); \r\n countTotalPages();\r\n showHideActiveFilters();\r\n } else if (key === 'location') {\r\n $scope.submitSearch(null, null, true);\r\n }\r\n $scope.loadingCourses = false;\r\n };\r\n\r\n $scope.updateFilter = function (key, index, weekend) {\r\n if (key === 'day') {\r\n $scope.activeFilters.day[index] = weekend !== true;\r\n }\r\n if (key === 'program') {\r\n $scope.activeFilters.program = $scope.programFilters[0];\r\n }\r\n if (key === 'location') {\r\n $scope.activeFilters.location = $scope.locationFilters[0];\r\n }\r\n if (key === 'type') {\r\n $scope.activeFilters.type = $scope.typeFilters[0];\r\n }\r\n\r\n if (key === 'time') {\r\n $scope.activeFilters.time = {\r\n type: $scope.timeFilters.type[0],\r\n hour: null\r\n };\r\n }\r\n\r\n $scope.selectedfilters--;\r\n $scope.results = $filter(key)($scope.results, key, $scope.activeFilters);\r\n $scope.currentPage = 1;\r\n\r\n countVisibleResults();\r\n countTotalPages();\r\n showHideActiveFilters();\r\n };\r\n\r\n $scope.paging = function (i) {\r\n $scope.currentPage = $scope.currentPage + i;\r\n };\r\n\r\n /**\r\n * Set the selected term in the factory, triggering a request for all courses for the term\r\n * @returns {} \r\n */\r\n $scope.setTerm = function () {\r\n $scope.loadingCourses = true;\r\n $scope.showFilters = false;\r\n timetableService.setSelectedTerm($scope.selectedTerm);\r\n };\r\n\r\n /**\r\n * Find the course detail when a selection is made in the search typeahead\r\n * @param {} $item \r\n * @returns {} \r\n */\r\n var prevSearchTerm = '', searching = false;\r\n\r\n $scope.submitSearchOnBlur = function () {\r\n searching = false;\r\n $timeout(function () {\r\n if (!searching) {\r\n $scope.submitSearch();\r\n }\r\n }, 100);\r\n }\r\n\r\n //submit button - find all courses matching search params\r\n $scope.submitSearch = function (typeaheadSelect, item, force) {\r\n\r\n searching = true;\r\n\r\n $scope.searchTerm = item ? item.fullDescription : $scope.searchTerm;\r\n\r\n if ($scope.searchTerm !== prevSearchTerm || force) {\r\n $scope.results = [];\r\n for (var i = 0, l = $scope.courses.length; i < l; i++) {\r\n var c = $scope.courses[i];\r\n\r\n if (c.fullDescription.toLowerCase().indexOf($scope.searchTerm.toLowerCase()) > -1) {\r\n c.hasVisibleChildren = true;\r\n c.hiddenByProgramFilter = false;\r\n\r\n $scope.results.push(c);\r\n }\r\n }\r\n $scope.noResults = $scope.results.length === 0;\r\n\r\n if ($scope.searchTerm.length) {\r\n recentSearchesFactory.add({\r\n courseCode: typeaheadSelect ? item.courseCode : $scope.searchTerm,\r\n description: typeaheadSelect ? item.description : '',\r\n termId: $scope.selectedTerm.id\r\n });\r\n }\r\n\r\n prevSearchTerm = $scope.searchTerm;\r\n\r\n getClasses();\r\n }\r\n }\r\n\r\n //////////////////////////////////////////////////////\r\n // PRIVATE FUNCTIONS\r\n /////////////////////////////////////////////////////\r\n\r\n /**\r\n * For the current set of search results, request the classes\r\n * @returns {} \r\n */\r\n function getClasses() {\r\n $scope.loadingCourses = true;\r\n var ids = $scope.results.map(function (v) {\r\n return v.courseId;\r\n });\r\n\r\n timetableService.getClassBySearchTerm(ids)\r\n .then(function (resp) {\r\n mapClassesToCourses(resp.data);\r\n });\r\n }\r\n\r\n /**\r\n * Relate classes object to the relevant course object in the search results\r\n * Also store a location string on the search result to ease filtering\r\n * @param {} classes \r\n * @returns {} \r\n */\r\n function mapClassesToCourses(classes) {\r\n $scope.results.forEach(function (result) {\r\n var c = classes.filter(function (vv) {\r\n return vv.key === result.courseId;\r\n })[0];\r\n\r\n if (c) {\r\n var offeredLocations = c.value.map(function (v) {\r\n return v.location;\r\n }).filter(function (value, index, self) {\r\n return self.indexOf(value) === index;\r\n }).join('|');\r\n\r\n result.classes = c.value;\r\n result.locations = offeredLocations;\r\n }\r\n });\r\n\r\n // need to trigger the location filter, as a location may exist prior to the results\r\n filterNewResults();\r\n $scope.loadingCourses = false;\r\n }\r\n\r\n\r\n // Generate the hour values for the time filer\r\n function populateTimeFilter() {\r\n var arr = [], seed = 7, i = 0;\r\n for (; i < 15; i++) {\r\n\r\n var time = seed <= 12 ? seed : seed - 12;\r\n\r\n arr.push({\r\n 'key': time + (seed < 12 ? 'am' : seed === 12 ? 'nn' : 'pm'),\r\n 'value': seed + ':00'\r\n });\r\n\r\n seed = seed + 1;\r\n }\r\n return arr;\r\n }\r\n\r\n function showHideActiveFilters() {\r\n $timeout(function () {\r\n $scope.noActiveFilters = document.getElementById('filteringBy').childElementCount === 0;\r\n }, 10);\r\n }\r\n\r\n /**\r\n * \r\n * @returns {} \r\n */\r\n function countVisibleResults() {\r\n $scope.visibleResultsCount = $scope.results.filter(function (el) {\r\n var allHidden = true;\r\n el.allClassesClosed = el.classes.filter(function (v) {\r\n allHidden = v.hiddenByFilter ? allHidden : false;\r\n return v.enrolmentStatus !== 'O' || (v.enrolmentStatus === 'O' && v.location !== $scope.activeFilters.location && $scope.activeFilters.location !== 'Show all');\r\n }).length === el.classes.length;\r\n\r\n el.allClassesHidden = allHidden;\r\n return el.hiddenByProgramFilter === false && el.hiddenByLocationFilter === false && allHidden === false;\r\n }).length;\r\n }\r\n\r\n function countTotalPages() {\r\n $scope.totalPages = Math.ceil($scope.visibleResultsCount / $scope.perPage);\r\n }\r\n\r\n //review the current set filters for new results\r\n function filterNewResults() {\r\n\r\n $scope.loadingCourses = true;\r\n\r\n var filters = ['day', 'location', 'time', 'program'];\r\n for (var i = 0; i < filters.length; i++) {\r\n $scope.results = $filter(filters[i])($scope.results, filters[i], $scope.activeFilters);\r\n }\r\n $filter('pattern')($scope.results);\r\n\r\n countVisibleResults();\r\n countTotalPages();\r\n $scope.loadingCourses = false;\r\n }\r\n\r\n function resetFilters(clearSearch) {\r\n // reset filter values to sensible defaults\r\n $scope.programFilters = ['Show all', 'Undergraduate', 'Postgraduate', 'Enabling'];\r\n $scope.typeFilters = ['Show all', 'On-campus only', 'Online only'];\r\n $scope.timeFilters = {\r\n type: ['Show all', 'Starting after', 'Finishing before'],\r\n hour: populateTimeFilter()\r\n };\r\n\r\n $scope.activeFilters = {\r\n program: $scope.programFilters[0],\r\n type: $scope.typeFilters[0],\r\n day: [false, true, true, true, true, true, true],\r\n time: {\r\n type: $scope.timeFilters.type[0],\r\n hour: null\r\n },\r\n location: $scope.locationFilters[0]\r\n };\r\n\r\n if (clearSearch === undefined) {\r\n //reset course search term \r\n $scope.searchTerm = '';\r\n $scope.totalPages = 0;\r\n $scope.errorMsg = '';\r\n //Reseting course details search \r\n } else {\r\n filterNewResults();\r\n }\r\n }\r\n\r\n if (showFirstRunModal && !timetableConfig.GODMODE) {\r\n var firstRunModalInstance = $uibModal.open({\r\n templateUrl: 'firstRunModal.html',\r\n controller: 'FirstRunModalCtrl',\r\n backdrop: 'static'\r\n });\r\n\r\n firstRunModalInstance.result.then(function (resp) {\r\n if (resp) {\r\n resetFilters();\r\n if (timetableConfig.HAS_LOCALSTORAGE) {\r\n localStorage[timetableConfig.LOCAL_STORE_KEY + 'acceptedConditions'] = new Date();\r\n }\r\n }\r\n });\r\n } else {\r\n resetFilters();\r\n }\r\n\r\n /**\r\n * Reset button or semester change calls init, clears all semester-specific variables\r\n * @param {} arg \r\n * @returns {} \r\n */\r\n function init(arg) {\r\n $scope.selectedTerm = arg || undefined;\r\n $scope.loadingCourses = true;\r\n $scope.showFilters = true;\r\n $scope.results = [];\r\n $scope.visibleResultsCount = 0;\r\n $rootScope.showAll = arg ? timetableService.getSelectedTerm().showAllFrom < now.getTime() || timetableConfig.GODMODE : false;\r\n\r\n if (timetableConfig.HAS_LOCALSTORAGE) {\r\n plannerFactory.clearPlannerUi();\r\n plannerFactory.getFromLocalStorage();\r\n }\r\n\r\n resetFilters();\r\n\r\n // this is a bit lazy, but fixes the infinite loading when reverting back to a previously selected teaching period\r\n $scope.loadingCourses = false;\r\n }\r\n};","export default function ($scope, $uibModalInstance, $filter, courseCode, courseName, current, classes) {\r\n\r\n $scope.courseName = courseName;\r\n $scope.courseCode = courseCode;\r\n\r\n $scope.validClasses = [];\r\n $scope.current = [];\r\n $scope.classTypes = [];\r\n\r\n var uniqueClassNos = [],\r\n currentClassNos = [],\r\n toRemove = [];\r\n\r\n function buildUniqueList(initial, parsed, uniqueArray, isCurrentClasses) {\r\n initial.forEach(c => {\r\n if (c && (c.enrolmentStatus === 'O' || isCurrentClasses)) {\r\n\r\n var classNo = c.classNo,\r\n i = uniqueArray.indexOf(classNo);\r\n\r\n if (i === -1) {\r\n c.isMultiday = false;\r\n parsed.push(c);\r\n uniqueArray.push(classNo);\r\n } else {\r\n parsed[i].isMultiday = true;\r\n $scope.hasMultiday = true;\r\n }\r\n\r\n if ($scope.classTypes.indexOf(c) === -1) {\r\n $scope.classTypes.push(c);\r\n }\r\n }\r\n });\r\n };\r\n\r\n buildUniqueList(current, $scope.current, currentClassNos, true);\r\n buildUniqueList(classes, $scope.validClasses, uniqueClassNos);\r\n\r\n // make sure no classes exist in valid that are already selected - multidays will still be appearing \r\n $scope.validClasses = $scope.validClasses.filter(c => currentClassNos.indexOf(c.classNo) === -1);\r\n\r\n $scope.toAdd = null;\r\n $scope.SetSelectedClass = t => {\r\n $scope.toAdd = t;\r\n }\r\n\r\n $scope.showCurrent = current.length !== 0;\r\n\r\n $scope.markForRemoval = () => {\r\n toRemove = $scope.current.filter(el =>el.checked);\r\n }\r\n\r\n $scope.getNgOption = c => \r\n !c.isMultiday\r\n ? `${c.classDesc} (${c.meetingDay}, ${$filter('dateTime')(c.meetingStartTime, 'time')}-${$filter('dateTime')(c.meetingEndTime, 'time')}, ${c.location})`\r\n : `${c.classDesc} (${c.classSection}) *`; \r\n\r\n $scope.ok = () => {\r\n var toAdd = $scope.validClasses.filter(o => (o.classNo.toString() + o.classMeetingNo.toString()) === $scope.toAdd); \r\n $uibModalInstance.close([toAdd, toRemove]);\r\n };\r\n\r\n $scope.cancel = function () {\r\n resetRemoval();\r\n $uibModalInstance.dismiss('cancel');\r\n };\r\n\r\n function resetRemoval() {\r\n $scope.current.forEach(o => o.checked = false); \r\n }\r\n};","import classBlock from './classblock.directive';\r\nimport plannerCourseCard from './plannercoursecard.directive';\r\nimport recentSearchCard from './recentsearchcard.directive';\r\nimport searchResult from './searchresult.directive';\r\nimport searchResultRow from './searchresultrow.directive';\r\n\r\nconst moduleName = 'usc.timetable.directives';\r\n\r\nangular.module(moduleName, [])\r\n .directive('classBlock', ['timetableService', 'plannerFactory', '$uibModal', classBlock])\r\n .directive('plannerCourseCard', ['$filter', 'timetableService', 'plannerFactory', '$uibModal', plannerCourseCard])\r\n .directive('recentSearchCard', ['timetableService', 'recentSearchesFactory', recentSearchCard])\r\n .directive('searchResult', ['$filter', '$sce', '$rootScope', searchResult])\r\n .directive('searchResultRow', ['plannerFactory', searchResultRow]);\r\n\r\nexport default moduleName;","\r\n\r\n/**\r\n * Display the class item in the planner grid UI\r\n * @param {} timetableService \r\n * @param {} plannerFactory \r\n * @param {} $uibModal \r\n * @returns {} \r\n */\r\nexport default function (timetableService, plannerFactory, $uibModal) {\r\n\r\n const classDetailModalTemplate = `\r\n
\r\n

{{ ::course.courseCode }} {{ ::course.description }} - {{ ::class.classDesc }}

\r\n
\r\n
\r\n
\r\n \r\n
\r\n

{{ class.noteText }}

\r\n
\r\n
\r\n
\r\n
Location
\r\n
{{ class.room }} ({{ class.location }})
\r\n
Day
\r\n
{{ class.meetingDayNo|dateTime:\\'day\\' }}
\r\n
Time
\r\n
\r\n {{ class.meetingStartTime|dateTime:\\'time\\' }}–{{ class.meetingEndTime|dateTime:\\'time\\' }}\r\n
\r\n
Dates
\r\n
\r\n \r\n {{ a.meetingStartDate | date:\\'d MMMM\\' }}–{{ a.meetingEndDate | date:\\'d MMMM\\' }}
\r\n
\r\n
\r\n
\r\n

For course requisites and fee information, refer to the course detail.

\r\n
\r\n
\r\n Course detail\r\n \r\n
`;\r\n\r\n return {\r\n scope: {\r\n classData: '='\r\n },\r\n restrict: 'E',\r\n replace: true,\r\n template: `\r\n
\r\n
{{ classData.courseCode }}
\r\n \r\n
\r\n \r\n
\r\n
`,\r\n link: function (scope) {\r\n\r\n scope.class = scope.classData.class;\r\n\r\n /**\r\n * Set the class on the block element, as determined by the properities of the class\r\n */\r\n function cssClass() {\r\n scope.cssClass = [\r\n scope.class.room === 'ONLINE' ? 'online' : '',\r\n scope.class.clash === 'left' ? 'clash-left' : '',\r\n scope.class.clash === 'right' ? 'clash-right' : '',\r\n scope.class.red ? 'clash-red' : ''\r\n ].join(' ').trim();\r\n\r\n scope.isOnline = scope.class.classDesc.toLowerCase().replace(' ', '') === 'online';\r\n }\r\n\r\n cssClass();\r\n\r\n /**\r\n * display the modal for the selected class, triggered by clicking the card.\r\n * fetches all classes for the given course to display in dropdown for adding new class selections\r\n * @returns {} \r\n */\r\n scope.showClassDetail = function () {\r\n\r\n timetableService.getClasses(scope.class.courseId).then(function (response) {\r\n\r\n var classes = response.data ? response.data.data : response;\r\n\r\n const modal = $uibModal.open({\r\n template: classDetailModalTemplate,\r\n controller: 'ClassDetailModalCtrl',\r\n resolve: {\r\n c: function () {\r\n return scope.classData;\r\n },\r\n all: function () {\r\n return classes.where(function (r) {\r\n return r.classNo === scope.class.classNo && r.meetingDayNo === scope.class.meetingDayNo && r.meetingStartTime === scope.class.meetingStartTime;\r\n });\r\n }\r\n }\r\n });\r\n\r\n // doesn't return anything, but need to manage the closure\r\n modal.result.then(() => { }, () => { });\r\n });\r\n };\r\n\r\n /**\r\n * Remove the class from the planner view\r\n * @returns {} \r\n */\r\n scope.removeFromPlanner = function () {\r\n plannerFactory.removeFromPlanner(scope.classData, false);\r\n }\r\n\r\n /**\r\n * When the planner is updated, the classes on the current class block may need to change\r\n * Easiest way to do this is subscribe to changes, then fetch the corresponding class from the planner\r\n * and replace the current with the new, and regenerate the CSS string\r\n */\r\n timetableService.subscribe(scope, 'plannerChanged',\r\n function (e, args) {\r\n var inPlanner = args.addedToPlanner;\r\n if (inPlanner.length) {\r\n var fromPlanner = inPlanner.filter(function (v) {\r\n return v.class.classNo === scope.class.classNo;\r\n })[0];\r\n\r\n if (fromPlanner) {\r\n scope.classData.class = fromPlanner.class;\r\n cssClass();\r\n }\r\n }\r\n });\r\n }\r\n };\r\n};","export default function ($filter, timetableService, plannerFactory, $uibModal) {\r\n\r\n var selectionModalTemplate = `\r\n
\r\n

Update selection:
\r\n {{ ::courseCode }} {{ ::courseName }}

\r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n

This class has multiple offerings each week, or an irregular schedule. Modifying it will update multiple class times in the planner.

\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n

No classes available

\r\n
\r\n
\r\n OR \r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n \r\n
`;\r\n\r\n return {\r\n scope: {\r\n course: '='\r\n },\r\n restrict: 'EA',\r\n replace: true,\r\n template: `\r\n
  • \r\n \r\n
    \r\n \r\n \r\n
    \r\n
  • `,\r\n link: function (scope) {\r\n\r\n scope.removeFromPlanner = function () {\r\n plannerFactory.removeFromPlanner(scope.course, true);\r\n }\r\n\r\n scope.updateSelectionModal = function () {\r\n var classes = [],\r\n current = [],\r\n selectedClassIds = plannerFactory.getSelectedClassIds(),\r\n i, k, l;\r\n\r\n timetableService.getClasses(scope.course.courseId).then(function (resp) {\r\n\r\n var r = resp.data ? resp.data.data : resp;\r\n\r\n for (i = 0, l = r.length; i < l; i++) {\r\n k = r[i];\r\n\r\n if (k.meetingStartTime !== null) {\r\n k.meetingStartTime = $filter('date')(k.meetingStartTime, 'HH:MM');\r\n k.meetingEndTime = $filter('date')(k.meetingEndTime, 'HH:MM');\r\n k.courseCode = scope.course.courseCode;\r\n k.description = scope.course.courseName;\r\n k.termId = scope.course.termId;\r\n k.courseId = scope.course.courseId;\r\n k.checked = false;\r\n\r\n if (k.classMeetingNo && selectedClassIds.indexOf(k.classNo.toString() + k.classMeetingNo.toString()) === -1) {\r\n classes.push(k);\r\n } else if (k.hasOwnProperty('classNo')) {\r\n current.push(k);\r\n }\r\n }\r\n }\r\n\r\n var modalInstance = $uibModal.open({\r\n template: selectionModalTemplate,\r\n controller: 'UpdateClassSelectionModalCtrl',\r\n resolve: {\r\n courseCode: () => scope.course.courseCode,\r\n courseName: () => scope.course.description,\r\n current: () => current,\r\n classes: () => classes\r\n }\r\n });\r\n\r\n modalInstance.result.then(function (resp) {\r\n\r\n // class to be added to planner\r\n if (resp[0].length > 0) {\r\n var classToAdd = resp[0][0],\r\n classesToAdd = classes.where(function (c) {\r\n // need to return any classes with the same id, to allow for multi-day classes\r\n return c.classNo === classToAdd.classNo;\r\n });\r\n\r\n plannerFactory.addToPlanner(classesToAdd,\r\n classToAdd.courseCode,\r\n classToAdd.description,\r\n classToAdd.courseId,\r\n classToAdd.termId,\r\n true);\r\n }\r\n\r\n // classes to be removed from planner\r\n if (resp[1].length > 0) {\r\n for (i = 0, l = resp[1].length; i < l; i++) {\r\n plannerFactory.removeFromPlanner(resp[1][i], false);\r\n }\r\n }\r\n }, () => {});\r\n });\r\n };\r\n }\r\n };\r\n};","/**\r\n * Build the card for display in the recent searches column\r\n * @param {} $rootScope \r\n * @param {} recentSearchesFactory \r\n * @returns {} \r\n */\r\nexport default function (timetableService, recentSearchesFactory) {\r\n\r\n var recentSearchCardTemplate = `\r\n
  • \r\n \r\n
    \r\n \r\n \r\n
    \r\n
  • `;\r\n\r\n return {\r\n scope: {\r\n course: '=',\r\n submitSearch: '&'\r\n },\r\n restrict: 'E',\r\n replace: true,\r\n template: recentSearchCardTemplate,\r\n link: function (scope) {\r\n\r\n scope.get = function () {\r\n timetableService.search(scope.course.courseCode, scope.course.termId);\r\n };\r\n\r\n scope.remove = function () {\r\n recentSearchesFactory.remove(scope.course);\r\n };\r\n }\r\n };\r\n};","/**\r\n * Display the search result item\r\n * @param {} $filter \r\n * @returns {} \r\n */\r\nexport default function ($filter, $sce, $rootScope) {\r\n\r\n\r\n var searchResultTemplate = `\r\n
    {{ ::result.fullDescription }}
    \r\n

    \r\n

    0\">Coordinated by

    \r\n

    Coordinated by {{ ::result.formalName }}

    \r\n
    \r\n

    This course is only available online.

    \r\n

    Remember that your courses may have various components such as lectures, tutorials or workshops which you will need to select/enrol into.

    \r\n

    \r\n

    \r\n

    \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
    Class Day Campus RoomTime Dates
    \r\n
    \r\n
    \r\n
    \r\n

    All classes for this course are hidden by filters.

    \r\n
    \r\n
    `;\r\n\r\n\r\n return {\r\n scope: {\r\n result: '='\r\n },\r\n restrict: 'E',\r\n replace: false,\r\n template: searchResultTemplate,\r\n link: function (scope) {\r\n\r\n scope.reverseSort = false;\r\n var currentSort; \r\n\r\n scope.sortByColumn = function (col) {\r\n scope.reverseSort = col !== currentSort ? false : !scope.reverseSort;\r\n\r\n var sortBy = ['classSection', scope.reverseSort ? '-hiddenTitle' : '+hiddenTitle', scope.reverseSort ? '-meetingStartDate' : '+meetingStartDate'];\r\n var hasHiddenTitles = scope.result.classes.some(x => !x.hiddenByFilter && x.hiddenTitle);\r\n\r\n scope.result.classes = $filter('orderBy')\r\n (scope.result.classes, hasHiddenTitles ? sortBy : [col, 'classSection'], scope.reverseSort);\r\n\r\n currentSort = col;\r\n }\r\n\r\n scope.allClassesClosedMessage = $sce.trustAsHtml($rootScope.allClassesClosedMessage);\r\n scope.showAll = $rootScope.showAll;\r\n\r\n if (scope.result.classes) {\r\n scope.noteText =\r\n scope.result.classes[0].noteSeq > 0 && scope.result.classes[0].noteText.indexOf(' ') !== -1\r\n ? scope.result.classes[0].noteText\r\n : undefined;\r\n }\r\n }\r\n };\r\n};","\r\n/**\r\n * Build a search result table row\r\n * @param {} $rootScope \r\n * @param {} recentSearchesFactory \r\n * @returns {} \r\n */\r\nexport default function (plannerFactory) {\r\n\r\n var searchResultRowTemplate = `\r\n \r\n {{ result.classSection }} {{ result.classDesc }}\r\n
    \r\n \r\n
    \r\n \r\n \r\n {{ hideDayTime ? '-' : result.meetingDay }}\r\n \r\n \r\n {{ hideDayTime ? '-' : (result.meetingStartTime|dateTime:\\'time\\') + \\'-\\' + (result.meetingEndTime|dateTime:\\'time\\') }}\r\n {{result.meetingStartDate|date:\"d MMM\"}}-{{result.meetingEndDate|date:\"d MMM\"}}\r\n \r\n \r\n CLOSED\r\n `;\r\n\r\n return {\r\n scope: {\r\n course: '=',\r\n result: '='\r\n },\r\n restrict: 'A',\r\n replace: false,\r\n template: searchResultRowTemplate,\r\n link: (scope, element) => {\r\n\r\n if (scope.result.enrolmentStatus !== 'O') {\r\n element[0].classList.add('closed');\r\n }\r\n\r\n // hide day and time for any item where day, start and end are not defined\r\n scope.hideDayTime = true;\r\n if (scope.result.meetingDay && scope.result.meetingStartTime && scope.result.meetingEndTime) {\r\n scope.hideDayTime = false;\r\n }\r\n\r\n scope.addToPlanner = () =>\r\n plannerFactory.addToPlanner(scope.result, scope.course.courseCode, scope.course.description, scope.course.courseId, scope.course.termId); \r\n\r\n }\r\n };\r\n};","import timetableControllers from './controllers/_controllers';\r\nimport timetableDirectives from './directives/_directives';\r\nimport timetableFilters from './filters/_filters';\r\nimport timetableResources from './resources/_resources';\r\n\r\nimport 'Sass/views/timetable.scss';\r\n\r\nconst moduleName = 'usc.timetable';\r\n\r\n/**\r\n * Check for querystring value where godmode=true\r\n * @returns {} \r\n */\r\nconst isGodMode = () => {\r\n var queryString = location.href.indexOf('?') !== -1 ? location.href.substr(location.href.indexOf('?')) : '',\r\n params = queryString.substr(1, queryString.length - 1).split('&'),\r\n i,\r\n keyValue,\r\n resp = false;\r\n\r\n for (i = 0; i < params.length; i++) {\r\n keyValue = params[i].split('=');\r\n if (keyValue.length &&\r\n keyValue[0].toLowerCase() === 'godmode' &&\r\n keyValue[1].toLowerCase().startsWith('true')) {\r\n resp = true;\r\n }\r\n }\r\n\r\n return resp;\r\n};\r\n\r\n/**\r\n * Is localstorage API available?\r\n * @returns {} \r\n */\r\nconst checkLocalStorage = () => {\r\n try {\r\n return 'localStorage' in window && window['localStorage'] !== null;\r\n } catch (e) {\r\n return false;\r\n }\r\n};\r\n\r\nangular.module(moduleName,\r\n [\r\n timetableControllers,\r\n timetableDirectives,\r\n timetableFilters,\r\n timetableResources\r\n ]).constant('timetableConfig',\r\n {\r\n 'LOCAL_STORE_KEY': '__usc__timetable__',\r\n 'DAYS': ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\r\n 'SIDEBAR_MAX': 6,\r\n 'HAS_LOCALSTORAGE': checkLocalStorage(),\r\n 'GODMODE': isGodMode()\r\n });\r\n\r\nconst app = angular.module(window.uscApp);\r\napp.requires.push(moduleName);","import alertsService from './alerts.service';\r\nimport plannerFactory from './planner.factory';\r\nimport recentSearchesFactory from './recentsearches.factory';\r\nimport storageService from './storage.service';\r\nimport timetableFactory from './timetable.factory';\r\n\r\nconst moduleName = 'usc.timetable.resources';\r\n\r\nangular.module(moduleName, [])\r\n .factory('alertsService', alertsService)\r\n .service('plannerFactory', ['$rootScope', '$filter', 'timetableService', 'storageService', 'alertsService', '$uibModal', 'timetableConfig', plannerFactory])\r\n .service('recentSearchesFactory', ['$rootScope', 'storageService', 'timetableConfig', recentSearchesFactory])\r\n .service('storageService', ['$rootScope', 'timetableConfig', 'timetableService', storageService])\r\n .factory('timetableService', ['$rootScope', '$http', '$q', timetableFactory]);\r\n\r\n\r\n\r\nexport default moduleName;","\r\n/**\r\n * The service for displaying alerts\r\n * @param {} constants \r\n * @returns {} \r\n */\r\nexport default function () {\r\n\r\n var alerts = [];\r\n\r\n /**\r\n * Push an alert object into the current alert stack\r\n * @param {} type \r\n * @param {} prefix \r\n * @param {} text \r\n * @returns {} \r\n */\r\n function add(type, prefix, msg) {\r\n alerts.push({\r\n type: type,\r\n prefix: prefix,\r\n msg: msg,\r\n close: () => alerts.splice(0, 1)\r\n });\r\n }\r\n\r\n return {\r\n add: add,\r\n get: () => alerts\r\n }\r\n};","export default function ($rootScope, $filter, timetableService, storageService, alertsService, $uibModal, timetableConfig) {\r\n\r\n var data = {\r\n onlineCourseCount: 0,\r\n onlineClassCount: 0,\r\n addedToPlanner: [],\r\n planner: []\r\n };\r\n\r\n /* the modal, keep these templates out of the main html view */\r\n var removeModalTemplate =\r\n '
    ' +\r\n ' ' +\r\n '

    Are you sure?

    ' +\r\n '
    ' +\r\n '
    ' +\r\n '

    Removing a course will remove all associated classes from the planner.

    ' +\r\n '
    ' +\r\n '
    ' +\r\n ' ' +\r\n ' ' +\r\n '
    ';\r\n\r\n /**\r\n * Build the empty planner view\r\n * @returns {} \r\n */\r\n function scaffold() {\r\n var i, j, l = timetableConfig.DAYS.length, o, temp = [];\r\n\r\n for (i = 0; i < l; i++) {\r\n\r\n o = {};\r\n o.name = timetableConfig.DAYS[i];\r\n o.hours = [];\r\n\r\n // 15-> 16 to add extra spot for online\r\n for (j = 0; j < 16; j++) {\r\n o.hours.push({ 'classes': [] });\r\n }\r\n temp.push(o);\r\n data.planner.push(o);\r\n }\r\n\r\n return temp;\r\n }\r\n\r\n /**\r\n * Emit the change event, this is available for subscription via subscribe()\r\n * @returns {} \r\n */\r\n function notify() {\r\n $rootScope.$emit('plannerChanged', data);\r\n }\r\n\r\n /**\r\n * Add the course/class to the planner object\r\n * @param {} c \r\n * @param {} courseCode \r\n * @param {} description \r\n * @param {} courseId \r\n * @param {} termId \r\n * @param {} fromModal \r\n * @param {} courses \r\n * @returns {} \r\n */\r\n function addToPlanner(c, courseCode, description, courseId, termId, fromModal) {\r\n\r\n var classes;\r\n // need to fetch the courses from the service, which returns a promise, hence the closure\r\n timetableService.getClasses(c.courseId, termId)\r\n .then(function (r) {\r\n classes = r.data ? r.data.data : r;\r\n add();\r\n });\r\n\r\n function add() {\r\n\r\n var uniqueInPlanner = [];\r\n data.addedToPlanner.forEach(function (course) {\r\n if (uniqueInPlanner.indexOf(course.courseCode) === -1) {\r\n uniqueInPlanner.push(course.courseCode);\r\n }\r\n });\r\n\r\n // show alert if:\r\n // there are six courses in the planner and the object to add is a course\r\n // there are six courses in the planner and the object to add is a class but the coursecode has not already been added\r\n if (uniqueInPlanner.length === timetableConfig.SIDEBAR_MAX &&\r\n (c === null || uniqueInPlanner.indexOf(courseCode) === -1 && c !== null)) {\r\n alertsService.add('danger', 'ERROR', 'Unable to add ' + courseCode + '. Remove at least one selection and try again. Maximum selections is ' + timetableConfig.SIDEBAR_MAX);\r\n } else {\r\n\r\n // need to check for multiple instance of the same class id \r\n // $scope.results[0].classes holds the class list for the current object if the search came from a typeahead selection\r\n // if it was character search, results needs to be iterated\r\n // multiDay.length will be >= 1 - either the class sent to addToPlanner, or a set of classes with matching classNo\r\n // results.length will be 0 if it's modal selection, so multiday just holds the class object, if one exists\r\n var i,\r\n classesToAdd = [];\r\n\r\n if ((fromModal === undefined || fromModal !== true) && c !== null) {\r\n\r\n if (classes) {\r\n classes.forEach(function (currentClass) {\r\n if (classesToAdd[0] === undefined && currentClass.classNo === c.classNo) {\r\n classesToAdd.push(currentClass);\r\n } else if (currentClass.classNo === c.classNo &&\r\n currentClass.meetingDayNo !== c.meetingDayNo &&\r\n (currentClass.meetingStartTime !== c.meetingStartTime &&\r\n currentClass.meetingEndTime !== c.meetingEndTime ||\r\n currentClass.classMeetingNo !== c.classMeetingNo)) {\r\n\r\n classesToAdd.push(currentClass);\r\n }\r\n });\r\n }\r\n\r\n } else if (c !== null && fromModal === true) {\r\n\r\n angular.forEach(c,\r\n function (currentClass) {\r\n if (classesToAdd[0] === undefined) {\r\n classesToAdd.push(currentClass);\r\n }\r\n if (classesToAdd.length > 1) {\r\n angular.forEach(classesToAdd,\r\n function (currentClassB) {\r\n if (currentClass.meetingDayNo !== currentClassB.meetingDayNo &&\r\n (currentClass.meetingStartTime !== currentClassB.meetingStartTime &&\r\n currentClass.meetingEndTime !== currentClassB.meetingEndTime)) {\r\n classesToAdd.push(currentClass);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n // online classes are often listed more than once, but should only be added once\r\n // remove all but a single instance of the online class\r\n var foundOnlineOffering = false;\r\n classesToAdd.forEach(function (v, i) {\r\n if (foundOnlineOffering && v.room === 'ONLINE') {\r\n classesToAdd.splice(1, i);\r\n } else if (v.room === 'ONLINE') {\r\n foundOnlineOffering = true;\r\n }\r\n });\r\n\r\n for (i = 0; i < classesToAdd.length; i += 1) {\r\n\r\n var classInstance = classesToAdd[i],\r\n hasClash = false,\r\n exactClash = false,\r\n courseFound = false,\r\n clash = null;\r\n\r\n if (!classInstance.meetingDayNo) {\r\n var startDate = new Date(classInstance.meetingStartDate);\r\n classInstance.meetingDayNo = startDate.getDay() + 1; // our week starts on sunday, 1 index\r\n classInstance.meetingDay = timetableConfig.DAYS[startDate.getDay()];\r\n }\r\n\r\n var classFound = data.addedToPlanner.where(function (plannerItem) {\r\n\r\n if (plannerItem.courseCode === courseCode) {\r\n courseFound = true;\r\n }\r\n\r\n if (classInstance && classInstance.room !== 'ONLINE') {\r\n if (plannerItem &&\r\n plannerItem.hasOwnProperty('class') &&\r\n plannerItem.class.meetingDay === classInstance.meetingDay) {\r\n\r\n // start times are the same = exact clash\r\n var newItemStartDate = new Date(classInstance.meetingStartDate),\r\n newItemEndDate = new Date(classInstance.meetingEndDate),\r\n plannerItemStartDate = new Date(plannerItem.class.meetingStartDate),\r\n plannerItemEndDate = new Date(plannerItem.class.meetingEndDate);\r\n\r\n // check both directions - existing may fall in new, new may fall in existing\r\n // particularly relevant for single-date classes\r\n if ((newItemStartDate < plannerItemEndDate && newItemStartDate >= plannerItemStartDate) ||\r\n (newItemEndDate <= plannerItemEndDate && newItemEndDate > plannerItemStartDate) ||\r\n (plannerItemStartDate < newItemEndDate && plannerItemStartDate >= newItemStartDate) ||\r\n (plannerItemEndDate <= newItemEndDate && plannerItemEndDate > newItemStartDate)) {\r\n\r\n var plannerItemStart = parseFloat($filter('date')(plannerItem.class.meetingStartTime, 'H.MM')),\r\n plannerItemEnd = parseFloat($filter('date')(plannerItem.class.meetingEndTime, 'H.MM')),\r\n newItemStart = parseFloat($filter('date')(classInstance.meetingStartTime, 'H.MM')),\r\n newItemEnd = parseFloat($filter('date')(classInstance.meetingEndTime, 'H.MM'));\r\n\r\n if (plannerItemStart === newItemStart) {\r\n hasClash = true;\r\n exactClash = true;\r\n clash = plannerItem;\r\n } else if (\r\n newItemStart > plannerItemStart && newItemStart < plannerItemEnd || // start of new overlaps\r\n newItemEnd > plannerItemStart && newItemEnd < plannerItemEnd || // end of new overlaps \r\n plannerItemStart > newItemStart && plannerItemStart < newItemEnd || // start of existing overlaps\r\n plannerItemEnd > newItemStart && plannerItemEnd < newItemEnd) { // end of existing overlaps\r\n hasClash = true;\r\n clash = plannerItem;\r\n }\r\n }\r\n }\r\n\r\n if (plannerItem && plannerItem.hasOwnProperty('id')) {\r\n return plannerItem.id ===\r\n classInstance.classNo.toString() + classInstance.classMeetingNo.toString();\r\n } else if (plannerItem && plannerItem.hasOwnProperty('class')) {\r\n return plannerItem.class.classNo === classInstance.classNo;\r\n }\r\n }\r\n return false;\r\n }).length;\r\n\r\n // allow multiday classes to clash start times\r\n if (exactClash && classesToAdd.length === 1 && classInstance.classNo === clash.class.classNo) {\r\n alertsService.add('danger',\r\n 'ERROR',\r\n 'Unable to add ' +\r\n classInstance.classSection +\r\n ' ' +\r\n classInstance.classDesc +\r\n ' - class is already in planner.');\r\n } else {\r\n // this will be classes where start/finish times overlap existing\r\n if (hasClash) {\r\n alertsService.add('danger', 'WARNING', classInstance.classSection + ' ' + classInstance.classDesc + ' clashes with ' + clash.class.classSection + ' ' + clash.class.classDesc);\r\n }\r\n if (classFound === 0 && classInstance !== null) {\r\n // checkClashes flag prevents checking clashes when adding multiple classes at once\r\n addClassToPlanner(classInstance,\r\n courseCode,\r\n description,\r\n courseId,\r\n termId,\r\n false,\r\n (classesToAdd.length === 1));\r\n } else if (!courseFound) {\r\n addCourseToPlanner(courseCode, description, courseId, termId, false);\r\n }\r\n }\r\n }\r\n\r\n // if adding multiple classes, warn the user of possible clashes and check planner for these\r\n if (classesToAdd.length > 1) {\r\n\r\n alertsService.addAlert('danger', 'WARNING', classInstance.classSection + ' ' + classInstance.classDesc + ' is offered on different days each week and may conflict with existing classes.');\r\n\r\n var day;\r\n if (classesToAdd.length > 1) {\r\n for (i = 0; i < classesToAdd.length; i++) {\r\n day = data.planner.where(function (o) {\r\n return o.name === classesToAdd[i].meetingDay;\r\n })[0];\r\n\r\n checkDayForClashes(day, true);\r\n }\r\n } else {\r\n day = data.planner.where(function (o) {\r\n return o.name === classInstance.meetingDay;\r\n })[0];\r\n\r\n checkDayForClashes(day, true);\r\n }\r\n }\r\n }\r\n\r\n storageService.storePlanner(data.addedToPlanner);\r\n notify();\r\n }\r\n }\r\n\r\n function addClassToPlanner(c, courseCode, description, courseId, termId, checkUnique, checkClashes) {\r\n // the class object is nested within an object identifying the parent course by code and name\r\n\r\n var exists = false;\r\n if (checkUnique) {\r\n exists = data.addedToPlanner.where(function (existingElement) {\r\n if (c !== null) {\r\n return existingElement.hasOwnProperty('id')\r\n ? existingElement.id === c.classNo.toString() + c.classMeetingNo.toString()\r\n : existingElement.classNo === c.classNo;\r\n }\r\n return true;\r\n }).length > 0 ? true : false;\r\n }\r\n\r\n var o = {\r\n 'class': c,\r\n courseCode: courseCode,\r\n description: description,\r\n courseId: courseId,\r\n termId: termId,\r\n id: c.classNo.toString() + c.classMeetingNo.toString()\r\n };\r\n\r\n o.class.clash = '';\r\n o.class.red = '';\r\n o.class.meetingEndTime = $filter('date')(c.meetingEndTime, 'HH:MM');\r\n o.class.meetingStartTime = $filter('date')(c.meetingStartTime, 'HH:MM');\r\n o.class.duration = o.class.meetingEndTime ? (parseInt(o.class.meetingEndTime.replace(':', '')) - parseInt(o.class.meetingStartTime.replace(':', ''))) / 2 : 0;\r\n\r\n var day = data.planner.where(function (d) {\r\n return d.name === c.meetingDay;\r\n })[0];\r\n\r\n if (o.class.room === 'ONLINE') {\r\n day.hours[0].classes.push(o);\r\n } else {\r\n day.hours[Math.round((parseInt($filter('date')(o.class.meetingStartTime, 'HH:MM').replace(':', '')) - 600) / 100)].classes.push(o); // eg (1900 - 600) / 100 = 13, or 7pm -> 6am + 12hours, where the 6am cell is labelled 'online'\r\n }\r\n\r\n if (checkClashes !== false) {\r\n checkDayForClashes(day, true);\r\n }\r\n\r\n data.planner[o.class.meetingDayNo - 1].hasClasses = true;\r\n\r\n if (!exists) {\r\n data.addedToPlanner.push(o);\r\n alertsService.add('success', 'SUCCESS', 'Class ' + c.classSection + ' ' + c.classDesc + ' successfully added to planner.');\r\n }\r\n\r\n // find the day with the most online options added, set that count as the onlineClassCount value, which controls the height of the top row of the planner\r\n // online classes can't clash, so must stack instead.\r\n var x = 0;\r\n data.planner.forEach(function (day) {\r\n if (day.hours[0].classes.length > x) {\r\n x = day.hours[0].classes.length;\r\n }\r\n });\r\n data.onlineClassCount = x;\r\n }\r\n\r\n function checkDayForClashes(day, isAdd) {\r\n\r\n // if course removed, reset clash value for all existing\r\n var i, q, classes, j, r;\r\n if (!isAdd) {\r\n for (i = 0, q = day.hours.length; i < q; i++) {\r\n if (day.hours[i].classes.length > 0) {\r\n classes = day.hours[i].classes;\r\n for (j = 0, r = classes.length; j < r; j++) {\r\n classes[j].class.clash = '';\r\n classes[j].class.red = '';\r\n }\r\n }\r\n }\r\n }\r\n\r\n // check each hour of the current day\r\n for (i = 0, q = day.hours.length; i < q; i++) {\r\n\r\n // if the hour has classes\r\n if (day.hours[i].classes.length > 0) {\r\n\r\n classes = day.hours[i].classes;\r\n\r\n // check each class in the current hour\r\n for (j = 0, r = classes.length; j < r; j++) {\r\n\r\n var c = classes[j].class,\r\n finishHour = c.meetingEndTime ? Math.round((parseInt(c.meetingEndTime.replace(':', '')) - 600) / 100) : i + c.duration;\r\n\r\n if (c.room !== 'ONLINE') {\r\n checkFollowingClasses(i, finishHour, c, day);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n function checkFollowingClasses(i, finishHour, c, day) {\r\n // given the start and finish time for the current class, check for others starting in the same period.\r\n var kClasses,\r\n kClass;\r\n\r\n for (i; i < finishHour; i++) {\r\n\r\n kClasses = day.hours[i].classes;\r\n\r\n if (kClasses.length > 0) {\r\n\r\n for (var l = 0, t = kClasses.length; l < t; l++) {\r\n\r\n kClass = kClasses[l].class;\r\n\r\n if ((c.classNo.toString() + c.classMeetingNo.toString()).toLowerCase() !==\r\n (kClass.classNo.toString() + kClass.classMeetingNo.toString()).toLowerCase()) {\r\n\r\n if (c.clash !== '') {\r\n kClass.clash = c.clash === 'left' ? 'right' : 'left';\r\n } else {\r\n c.clash = 'left';\r\n kClass.clash = 'right';\r\n }\r\n\r\n var newStartDate = new Date(c.meetingStartDate),\r\n newEndDate = new Date(c.meetingEndDate),\r\n kClassStartDate = new Date(kClass.meetingStartDate),\r\n kClassEndDate = new Date(kClass.meetingEndDate);\r\n\r\n if ((newStartDate < kClassEndDate && newStartDate >= kClassStartDate) ||\r\n (newEndDate <= kClassEndDate && newEndDate > kClassStartDate)) {\r\n\r\n c.red = true;\r\n kClass.red = true;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * manage removal of class/course from the planner, and related storage etc\r\n * @param {Object} c - will be removed from the planner array\r\n * @param {book} isCourse -indicates the object type, being course or class\r\n * @returns {} \r\n */\r\n function removeFromPlanner(c, isCourse) {\r\n if (isCourse) {\r\n\r\n var modalInstance = $uibModal.open({\r\n template: removeModalTemplate,\r\n controller: 'RemoveCourseFromPlannerModalCtrl'\r\n });\r\n\r\n modalInstance.result.then(function (resp) {\r\n if (resp === true) {\r\n doRemoveFromPlanner(c);\r\n }\r\n });\r\n } else {\r\n\r\n var classNo = null,\r\n courseId = null,\r\n hasClasses,\r\n day,\r\n hour,\r\n i,\r\n j,\r\n k,\r\n l,\r\n m,\r\n o;\r\n\r\n for (i = 0, j = data.planner.length; i < j; i++) {\r\n day = data.planner[i];\r\n hasClasses = false;\r\n\r\n for (k = 0, l = Object.size(day.hours); k < l; k++) {\r\n hour = day.hours[Object.keys(day.hours)[k]];\r\n m = Object.size(hour.classes);\r\n\r\n if (m > 0) {\r\n while (m--) {\r\n o = hour.classes[m];\r\n //two different methods of removing class from planner \r\n //one using class selection modal template by checking classNo and one using x button for class in planner by checking id\r\n if (c.class !== undefined && o.class.classNo === c.class.classNo ||\r\n c.hasOwnProperty('classNo') &&\r\n o.id.indexOf(c.classNo.toString()) === 0) {\r\n classNo = o.class.classNo;\r\n courseId = o.courseId;\r\n hour.classes.splice(hour.classes.indexOf(o), 1);\r\n\r\n checkDayForClashes(day, false);\r\n }\r\n }\r\n if (Object.size(hour.classes) > 0) {\r\n hasClasses = true;\r\n }\r\n }\r\n }\r\n if (!hasClasses) {\r\n data.planner[i].hasClasses = false;\r\n }\r\n }\r\n\r\n data.addedToPlanner = data.addedToPlanner.where(function (p) {\r\n return p.class !== undefined ? p.class.classNo !== classNo : p.courseId !== courseId;\r\n });\r\n\r\n storageService.storePlanner(data.addedToPlanner);\r\n\r\n notify();\r\n }\r\n }\r\n\r\n\r\n /**\r\n * execute the actual removal from the planner, once the previous function has completed its modifications\r\n * @param {} c \r\n * @returns {} \r\n */\r\n function doRemoveFromPlanner(c) {\r\n\r\n data.addedToPlanner = data.addedToPlanner.filter(function (p) {\r\n return p.courseCode !== c && p.courseCode !== c.courseCode; // c could be a code or course object\r\n });\r\n\r\n var i, j, k, l, m, o, day, hasClasses, hour;\r\n\r\n for (i = 0, j = data.planner.length; i < j; i++) {\r\n\r\n day = data.planner[i];\r\n hasClasses = false;\r\n\r\n for (k = 0, l = Object.size(day.hours); k < l; k++) {\r\n\r\n hour = day.hours[Object.keys(day.hours)[k]];\r\n m = Object.size(hour.classes);\r\n\r\n if (m > 0) {\r\n while (m--) {\r\n o = hour.classes[m];\r\n if (o.courseCode === c || o.courseCode === c.courseCode) {\r\n hour.classes.splice(hour.classes.indexOf(o), 1);\r\n checkDayForClashes(day, false);\r\n }\r\n }\r\n }\r\n if (Object.size(hour.classes) > 0) {\r\n hasClasses = true;\r\n }\r\n }\r\n if (!hasClasses) {\r\n data.planner[i].hasClasses = false;\r\n }\r\n }\r\n\r\n storageService.storePlanner(data.addedToPlanner);\r\n notify();\r\n }\r\n\r\n /**\r\n * \r\n * @param {} courseCode \r\n * @param {} description \r\n * @param {} courseId \r\n * @param {} termId \r\n * @param {} checkUnique \r\n * @returns {} \r\n */\r\n function addCourseToPlanner(courseCode, description, courseId, termId, checkUnique) {\r\n\r\n var exists = false;\r\n if (checkUnique) {\r\n exists = data.addedToPlanner.where(function (el) {\r\n return el.courseCode === courseCode;\r\n }).length;\r\n }\r\n /*if it's not currently added then add this from current courses or if it's not existed in the current courses send */\r\n if (!exists) {\r\n\r\n var course = {\r\n courseCode: courseCode,\r\n description: description,\r\n termId: termId,\r\n courseId: courseId\r\n };\r\n\r\n data.addedToPlanner.push(course);\r\n\r\n alertsService.add('success', 'SUCCESS', 'Course ' + course.description + ' successfully added to planner.');\r\n }\r\n }\r\n\r\n /**\r\n * Removes all classes from the planner by emptying the containing array\r\n * @returns {} \r\n */\r\n function clearPlannerUi() {\r\n var i, j;\r\n for (i = 0; i < timetableConfig.DAYS.length; i++) {\r\n for (j = 0; j < 15; j++) {\r\n if (data.planner[i] && data.planner[i].hours[j]) {\r\n data.planner[i].hours[j].classes = [];\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Fetch the planner from localstorage, then validated included classes against the current offering for the selected term\r\n */\r\n function getFromLocalStorage() {\r\n\r\n data.addedToPlanner = storageService.getPlanner();\r\n\r\n // Matt Crawford \r\n // Create an array for verification at the server side of the existance of a course\r\n if (data.addedToPlanner && data.addedToPlanner.length > 0) {\r\n var indexes = [];\r\n\r\n angular.forEach(data.addedToPlanner,\r\n function (item) {\r\n\r\n if (!indexes[item.termId]) {\r\n indexes[item.termId] = [];\r\n }\r\n\r\n if (indexes[item.termId.toString()].indexOf(item.courseId.toString()) === -1) {\r\n indexes[item.termId.toString()].push(item.courseId.toString());\r\n }\r\n });\r\n\r\n // Load the matching items from the server\r\n if (indexes.length > 0) {\r\n angular.forEach(indexes, function (courseIds, term) {\r\n timetableService.getClassBySearchTerm(courseIds, term).then(function (cls) {\r\n if (cls.data.data && cls.data.data.length > 0) {\r\n\r\n var updateUi = false;\r\n\r\n // Iterate through each item that has been added to the planner\r\n for (var addedItem = 0; addedItem < data.addedToPlanner.length; addedItem++) {\r\n var scopeItem = data.addedToPlanner[addedItem];\r\n\r\n // Iterate through the multi dimental array of data return from the server\r\n var found = false;\r\n for (var serverDs = 0; serverDs < cls.data.data.length; serverDs++) {\r\n\r\n var serverData = cls.data.data[serverDs].value;\r\n for (var item = 0; item < serverData.length; item++) {\r\n var serverItem = serverData[item];\r\n if (serverItem.enrolmentStatus === 'C' && !$rootScope.godMode)\r\n continue;\r\n\r\n if (scopeItem.courseCode === serverItem.courseCode &&\r\n scopeItem.courseId === serverItem.courseId &&\r\n scopeItem.class.classSection ===\r\n serverItem.classSection) {\r\n // We have found the item\r\n found = true;\r\n break;\r\n }\r\n }\r\n\r\n if (found)\r\n break;\r\n }\r\n\r\n if (!found) {\r\n data.addedToPlanner.splice(addedItem, 1);\r\n updateUi = true;\r\n }\r\n }\r\n\r\n // Store the results if we have removed anything and refresh the UI\r\n // This needs to be called due to the asyncronis nature of this call,\r\n // The add items code below will be called before we get here\r\n if (updateUi) {\r\n\r\n storageService.storePlanner(data.addedToPlanner);\r\n clearPlannerUi();\r\n\r\n for (var j = 0, l = data.addedToPlanner.length; j < l; j++) {\r\n var c = data.addedToPlanner[j];\r\n if (c.hasOwnProperty('class')) {\r\n addClassToPlanner(c.class,\r\n c.courseCode,\r\n c.description,\r\n c.courseId,\r\n c.termId,\r\n true);\r\n } else {\r\n addCourseToPlanner(c.courseCode,\r\n c.description,\r\n c.courseId,\r\n c.termId,\r\n true);\r\n }\r\n }\r\n }\r\n }\r\n });\r\n });\r\n }\r\n }\r\n // Add items to the planner now\r\n if (data.addedToPlanner !== null) {\r\n for (var j = 0, l = data.addedToPlanner.length; j < l; j++) {\r\n var c = data.addedToPlanner[j];\r\n if (c.hasOwnProperty('class')) {\r\n addClassToPlanner(c.class, c.courseCode, c.description, c.courseId, c.termId, true);\r\n } else {\r\n addCourseToPlanner(c.courseCode, c.description, c.courseId, c.termId, true);\r\n }\r\n }\r\n } else {\r\n data.addedToPlanner = [];\r\n }\r\n\r\n notify();\r\n }\r\n\r\n /**\r\n * Generic function to return the current state\r\n */\r\n function get() {\r\n return data;\r\n }\r\n\r\n /**\r\n * Return an array of class ids, for the classes added to the current planner view\r\n * @returns {} \r\n */\r\n function getSelectedClassIds() {\r\n return data.addedToPlanner.map(function (v) {\r\n return v.id;\r\n });\r\n }\r\n\r\n return {\r\n addToPlanner: addToPlanner,\r\n get: get,\r\n removeFromPlanner: removeFromPlanner,\r\n clearPlannerUi: clearPlannerUi,\r\n getFromLocalStorage: getFromLocalStorage,\r\n getSelectedClassIds: getSelectedClassIds,\r\n scaffold: scaffold,\r\n notify: notify\r\n }\r\n};","\r\n/**\r\n * Interface for adding and removing search results to the recent searches set\r\n * @param {} $rootScope \r\n * @param {} storageService \r\n * @param {} $constants \r\n * @returns {} \r\n */\r\nexport default function ($rootScope, storageService, timetableConfig) {\r\n\r\n var recent = storageService.getRecent();\r\n\r\n /**\r\n * Emit the change event, this is available for subscription via timetableservice.subscribe()\r\n * @returns {} \r\n */\r\n function notify() {\r\n $rootScope.$emit('recentChanged', recent);\r\n }\r\n\r\n /**\r\n * Add a course, class or search term to the recently viewed array\r\n * @param {} c \r\n * @returns {} \r\n */\r\n function add(c) {\r\n\r\n var found = recent.where(function (el) {\r\n return el.courseCode === c.courseCode || c.courseCode === el.fullDescription;\r\n }).length;\r\n\r\n if (!found && recent.length) {\r\n if (recent.length + 1 > timetableConfig.SIDEBAR_MAX) {\r\n recent.splice(recent.length - 1, 1);\r\n }\r\n\r\n recent.splice(0, 0, c);\r\n } else if (!recent.length) {\r\n recent[0] = c;\r\n } else if (found) {\r\n\r\n var index = recent.findIndex(function (el) {\r\n return el.courseCode === c.courseCode || c.courseCode === el.fullDescription;\r\n });\r\n\r\n recent.splice(0, 0, recent.splice(index, 1)[0]);\r\n }\r\n\r\n // store it, then tell the world\r\n storageService.storeRecent(recent);\r\n notify();\r\n }\r\n\r\n /**\r\n * Remove the selected item from the recent searches object, then update stored version\r\n * @param {} $event \r\n * @param {} index \r\n * @returns {} \r\n */\r\n function remove(c) {\r\n\r\n var index = recent.findIndex(function (el) {\r\n return el.courseCode === c.courseCode || c.courseCode === el.fullDescription;\r\n });\r\n\r\n recent.splice(index, 1);\r\n\r\n storageService.storeRecent(recent);\r\n notify();\r\n };\r\n\r\n return {\r\n add: add,\r\n remove: remove\r\n }\r\n};","/**\r\n * The service for interacting with local storage\r\n * Includes pub-sub functions for syncing data across the app\r\n * @param {} constants \r\n * @returns {} \r\n */\r\nexport default function ($rootScope, timetableConfig, timetableService) {\r\n\r\n var selectedTerm = {},\r\n recent = [],\r\n planner = [];\r\n\r\n /**\r\n * Update the added to planner list when selected term updates\r\n */\r\n timetableService.subscribe($rootScope.$new(), 'selectedTermChanged',\r\n function selectedTermChanged(e, arg) {\r\n selectedTerm = arg;\r\n });\r\n\r\n /**\r\n * Push the planner courses into local storage, if available, using the selected term id as an identifier for later retrieval\r\n * @param {} data \r\n * @param {} term \r\n * @returns {} \r\n */\r\n function storePlanner(data) {\r\n if (timetableConfig.HAS_LOCALSTORAGE && data !== null && selectedTerm && selectedTerm.id) {\r\n localStorage[timetableConfig.LOCAL_STORE_KEY + 'planner_' + selectedTerm.id] = JSON.stringify(data);\r\n }\r\n }\r\n\r\n /**\r\n * Push recently viewed courses object into local storage, if it is available\r\n * @param {} data \r\n * @returns {} \r\n */\r\n function storeRecent(data) {\r\n if (timetableConfig.HAS_LOCALSTORAGE && data !== null) {\r\n localStorage[timetableConfig.LOCAL_STORE_KEY + 'recent'] = JSON.stringify(data);\r\n }\r\n }\r\n\r\n /**\r\n * Retrieves recent course search information from localstorage. If none exists, or localstorage is not available, returns an empty array\r\n * @returns {} \r\n */\r\n function getRecent() {\r\n if (timetableConfig.HAS_LOCALSTORAGE) {\r\n recent = JSON.parse(localStorage.getItem(timetableConfig.LOCAL_STORE_KEY + 'recent')) || [];\r\n $rootScope.$emit('getRecent', recent);\r\n return recent;\r\n }\r\n return [];\r\n }\r\n\r\n /**\r\n * Retrieves planner information from localstorage, provided a term has been selected. If none exists, or localstorage is not available, returns an empty array \r\n * @returns {} \r\n */\r\n function getPlanner() {\r\n if (timetableConfig.HAS_LOCALSTORAGE && selectedTerm && selectedTerm.id) {\r\n planner = JSON.parse(localStorage.getItem(timetableConfig.LOCAL_STORE_KEY + 'planner_' + selectedTerm.id)) || [];\r\n $rootScope.$emit('getPlanner', planner);\r\n return planner;\r\n }\r\n return [];\r\n }\r\n\r\n return {\r\n storePlanner: storePlanner,\r\n storeRecent: storeRecent,\r\n getPlanner: getPlanner,\r\n getRecent: getRecent\r\n }\r\n};","export default function ($rootScope, $http, $q) {\r\n\r\n var URL_BASE = '/webapi/classsearch/',\r\n selectedTerm = {},\r\n currentTerms = [],\r\n courses = {},\r\n classes = {};\r\n\r\n /**\r\n * Generic subscription function for pubsub syncing\r\n * @param {} scope \r\n * @param {} event \r\n * @param {} callback \r\n * @returns {} \r\n */\r\n function subscribe(scope, event, callback) {\r\n var handler = $rootScope.$on(event, callback);\r\n scope.$on('$destroy', handler);\r\n }\r\n\r\n /**\r\n * Get all currently timetabled terms and cache the result \r\n * @returns {} \r\n */\r\n function getTerms() {\r\n return $http.get(URL_BASE + 'GetCurrentTerms').then(function (result) {\r\n currentTerms = result.data.data;\r\n return result.data;\r\n });\r\n }\r\n\r\n /**\r\n * Get all courses for the currently selected term and cache the result to a local object using the termId as the key \r\n * @returns {} \r\n */\r\n function getCourses() {\r\n var promise;\r\n\r\n var termId = selectedTerm.id;\r\n\r\n if (!courses[termId]) {\r\n var url = URL_BASE + 'GetCourses?term=' + termId;\r\n promise = $http.get(url);\r\n promise.then(function (response) {\r\n\r\n response.data.data = response.data.data.sort(function (a, b) {\r\n if (a.courseCode < b.courseCode) {\r\n return -1;\r\n }\r\n if (a.courseCode > b.courseCode) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n courses[termId] = response.data;\r\n $rootScope.$emit('coursesChanged', response.data);\r\n });\r\n } else {\r\n promise = $q.when(courses[termId]);\r\n $rootScope.$emit('coursesChanged', courses[termId]);\r\n }\r\n return promise;\r\n }\r\n\r\n /**\r\n * Get the employee by id\r\n * @param {} emplId \r\n * @returns {} \r\n */\r\n function getEmployee(emplId) {\r\n return $http.get(URL_BASE + 'GetCoord?empl=' + emplId).then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n /**\r\n * Get classes for the given term and course id, cache the result\r\n * Cached result will be returned if it exists.\r\n * @param {} termId \r\n * @param {} courseId \r\n * @returns {} \r\n */\r\n function getClasses(courseId, termId) {\r\n\r\n var promise,\r\n term = termId || selectedTerm.id,\r\n key = term + '_' + courseId;\r\n\r\n if (!classes[key]) {\r\n var url = URL_BASE + 'GetClassMeetings?term=' + term + '&course=' + courseId;\r\n promise = $http.get(url);\r\n promise.then(function (response) {\r\n classes[key] = response.data.data;\r\n\r\n });\r\n } else {\r\n promise = $q.when(classes[key]);\r\n }\r\n return promise;\r\n }\r\n\r\n /**\r\n * \r\n * @param {} data \r\n * @returns {} \r\n */\r\n function getValidatedCourseTerms(data) {\r\n return $http({\r\n method: 'POST',\r\n url: URL_BASE + 'VerifyCourseTerm',\r\n data: JSON.stringify(data)\r\n }).then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n function getClassBySearchTerm(courseList, term) {\r\n var data = {\r\n termId: term || selectedTerm.id,\r\n CourseList: courseList\r\n };\r\n return $http({\r\n method: 'POST',\r\n url: URL_BASE + 'GetClassbySearchTerm',\r\n data: JSON.stringify(data)\r\n }).then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n function getCourseDetails(courseId) {\r\n return $http.get(URL_BASE + 'GetCourseDetails?&course=' + courseId).then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n function getCampus() {\r\n return $http.get(URL_BASE + 'GetCampus').then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n function setSelectedTerm(term) {\r\n selectedTerm = currentTerms.filter(function (v) {\r\n return v.id === term.id || v.id === term; // term may be object or int\r\n })[0];\r\n\r\n getCourses();\r\n $rootScope.$emit('selectedTermChanged', selectedTerm);\r\n }\r\n\r\n /**\r\n * Get the selected term - this is not a promise and will return immediately\r\n * @returns {} \r\n */\r\n function getSelectedTerm() {\r\n return selectedTerm;\r\n }\r\n\r\n /**\r\n * Return a \r\n * @param {} query \r\n * @param {} termId \r\n * @returns {} \r\n */\r\n function search(query, termId) {\r\n\r\n setSelectedTerm(termId);\r\n\r\n getCourses(termId)\r\n .then(function (r) {\r\n var c = r.data.data ? r.data.data : r.data,\r\n resp = c.filter(function (v) {\r\n return v.courseCode === query || v.fullDescription.toLowerCase().indexOf(query.toLowerCase()) !== -1;\r\n });\r\n $rootScope.$emit('resultsChanged', resp);\r\n });\r\n }\r\n\r\n /**\r\n * Check for an inbound course in the query string, and submit a search if it exists\r\n */\r\n function checkParams(terms) {\r\n\r\n var course,\r\n i,\r\n keyValue,\r\n queryString = location.search.substr(1),\r\n params = queryString.split('&');\r\n\r\n for (i = 0; i < params.length; i++) {\r\n keyValue = params[i].split('=');\r\n\r\n if (keyValue.length && keyValue[0] === 'course') {\r\n course = keyValue[1];\r\n }\r\n }\r\n if (course) {\r\n\r\n // needs a term, but still returns everything, not sure why.\r\n setSelectedTerm(terms[0]);\r\n\r\n getCourseDetails(course).then(function (resp) {\r\n $rootScope.$emit('resultsChanged', !resp.data ? [] : resp.data.filter(function (v) {\r\n return terms.indexOf(v.termId) !== -1;\r\n }));\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Check the provided item for any class instances which are not hidden by filters\r\n * @param {any} item\r\n * @param {any} filters\r\n */\r\n function checkForVisibleChildren(item, filters) {\r\n var keys = [];\r\n for (var f in filters) {\r\n if (!keys.hasOwnProperty(f)) {\r\n keys.push(f);\r\n }\r\n }\r\n\r\n item.hasVisibleChildren = false;\r\n\r\n for (var j = 0, m = item.classes.length; j < m; j++) {\r\n var hiddenByFilter = false,\r\n jClass = item.classes[j];\r\n\r\n for (var k = 0, n = keys.length; k < n; k++) {\r\n if (jClass.hasOwnProperty(keys[k] + 'Filter') && jClass[keys[k] + 'Filter'] === false ||\r\n (jClass.enrolmentStatus !== 'O' && !$rootScope.showAll)) {\r\n hiddenByFilter = true;\r\n }\r\n }\r\n jClass.hiddenByFilter = hiddenByFilter;\r\n }\r\n\r\n var visibleChildrenCount = item.classes.where(function (el) {\r\n return el.hiddenByFilter === false;\r\n }).length;\r\n\r\n if (visibleChildrenCount > 0) {\r\n item.hasVisibleChildren = true;\r\n }\r\n return item;\r\n }\r\n\r\n /* Expose a public API */\r\n return {\r\n subscribe: subscribe,\r\n getCourses: getCourses,\r\n search: search,\r\n getTerms: getTerms,\r\n getEmployee: getEmployee,\r\n getClasses: getClasses,\r\n getValidatedCourseTerms: getValidatedCourseTerms,\r\n getClassBySearchTerm: getClassBySearchTerm,\r\n getCourseDetails: getCourseDetails,\r\n getCampus: getCampus,\r\n getSelectedTerm: getSelectedTerm,\r\n setSelectedTerm: setSelectedTerm,\r\n checkParams: checkParams,\r\n checkForVisibleChildren: checkForVisibleChildren\r\n };\r\n};"],"sourceRoot":""}