{"version":3,"sources":["scripts/app.js"],"names":["bsCompilerService","$q","$http","$injector","$compile","$controller","$templateCache","$log","findElement","query","element","angular","document","querySelectorAll","fetchTemplate","template","fetchPromises","get","cache","then","res","data","this","compile","options","test","warn","templateUrl","controller","controllerAs","resolve","copy","locals","transformTemplate","identity","bindToController","forEach","value","key","isString","invoke","extend","$template","when","Error","titleTemplate","all","templates","templateEl","removeAttr","html","outerHTML","contentTemplate","contentEl","next","remove","replace","trim","contents","linkFn","link","scope","$scope","invokeCtrl","instance","ctrl","isObject","children","apply","arguments","$inject","module","directive","$locale","$modal","$state","$alert","recipeApiService","userListApiService","menuApiService","createMenuHelper","titleService","restrict","menuData","enableSubmit","disableSubmit","SHORT_DAYS","getShortDays","localChefs","setTitle","tabs","map","day","name","toLowerCase","isSelected","selectedTab","menu","getMenuData","addNewStation","push","emptyStation","selectTab","find","tab","getFilters","filters","getRecipe","recipes","pagination","meta","getLocalChefs","chefs","removeByIndex","index","splice","selectChefs","src","dest","assigned_chefs","slice","addRecipe","stationRecipes","title","customClass","filter","recipe","item","id","length","onSelectRecipe","undefined","$hide","assignChefs","originalList","localChef","some","selectedChef","isChecked","chef","findedChef","action","cancel","openRemoveModal","arr","type","titles","station","stationMenu","openRemoveMenuModal","menuId","deleteMenu","go","createMenu","method","isCopy","copyMenuData","alertTitle","author_chef_id","content","show","container","startDate","start_date","onSetPage","offset","filterRecipes","categories","sort","filteredRecipes","isChanged","scheduleHours","getScheduleHours","scheduleMeal","schedule","addStation","start","end","edit","cancelPage","isEditMenu","chefsLength","titleLength","isRecipesAdded","weekDaysKeys","Object","keys","weekdays","factory","DEFAULT_STATIONS","mon","tue","wed","thu","fri","sat","sun","weekday","field","shortDays","DATETIME_FORMATS","SHORTDAY","shift","h","m","hh","ampm","isSwitched","i","postfix","$resource","API_URL","CONFIRM_URL","URL","userListApi","limit","getUsers","params","transformResponse","JSON","parse","user","fullName","first_name","last_name","createUser","updateUser","isArray","deleteUser","getAllUsers","$promise","role_id","confirm_url","userApi","login","resetPassword","changePassword","checkResetToken","email","password","resetToken","reset_token","new_password","getIds","Array","el","recipeApi","createRecipe","updateRecipe","deleteRecipe","getSubRecipe","calculateRecipe","size","importRecipe","searchRecipe","getNutritionFacts","getIngredients","unit","amount","searchIngredients","filterPromise","saveFilters","getDefaultFilters","recipeCopy","recipeData","mainRecipe","serving","portion","categories_id","allergens_id","allergens","dietaries_id","dietaries","sub_recipes","subrecipe","ingredients","ingredient","ing","nid","unit_id","custom","calories","total_fat","saturated_fat","cholesterol","sodium","carbohydrate","dietary_fiber","protein","sugar","methods","desc","cuisine","cuisine_id","photo","patchRecipe","user_title","recipeId","subRecipeId","recipeUrl","url","category[]","cuisine[]","dietary[]","predicate","direction","dir","getPhotoUrl","search","q","moment","$filter","transformMenuData","skipDelete","recipe_id","price","author_chef_name","menuApi","updateMenu","getMenu","getMenuList","utcOffset","_d","date","downloadMenuSheet","downloadMenuTemplate","downloadMenuPDF","headers","Content-Type","Accept","responseType","$window","placeholderColors","NUTRITION_MAPPING","userService","PermPermissionStore","recipeHelper","print","helper","categoriesToPrint","addSection","concat","disableApply","disableReset","NUTRITION_TO_PRINT_MAPPING","calculateIngredients","servingSize","calculatedRecipe","onChangeServings","color","getColor","category","labelTypes","categoryName","indexOf","split","join","definePermission","getUser","getIngredientsForPrint","result","openEditModal","ingredientName","resetToDefault","defaultValue","transformNutritions","transformIngredients","totalNutritions","nutrition","nutritionsSum","isNumber","$watch","subRecipes","subRecipe","section","colors","Math","floor","random","onSelect","isLoading","getRandomColor","num","input","chars","breakOnWord","isNaN","substring","charAt","substr","lastspace","lastIndexOf","onChange","categoriesFilter","isMenuState","initFilter","cuisines","category_groups","categoryGroup","dietary","noop","selectOption","skipChangeCb","selectAllOptions","checkbox","clearAll","Upload","isValidRecipe","forCancel","recipeTitleLength","ingredientsLength","methodsLength","nutritionsLength","isValid","nutritionSum","saveRecipe","showAlert","totalNutritionsWithServing","findIndex","option","getColumnsCount","ceil","uploadImage","img","invalidFiles","invalidImg","onBlurIngredient","$index","checkIngredient","checkSubmit","checkSubrecipe","recipeArr","changeAmount","editNutritions","originalVal","units","calculateTotalNutritions","skipAdding","calculateNutritionSum","editRecipe","part","getInfo","originalObject","toFixed","checkUnits","is_custom","timeout","setTimeout","getElementById","focus","clearTimeout","unitIndex","nutritions","changeIngredientUnit","changeCustomIngredientUnit","submitRecipe","upload","transformRecipeData","imgPreview","constant","customUnits","ingredientUnits","defaultUnits","separator","transformIngredient","transformedIngredients","calculateNutrition","sum","prop","replaceAmount","nutritionValue","itemDefaultAmount","defaultAmount","allergen","nutrition_facts","availableOptions","addRecipeIngredient","array","fat","carbs","prot","kcal","addRecipeMethod","selectedOption","getPagesArray","totalPages","pagesArray","chunk","chunkSize","elem","pre","currentPage","currentChunk","setPage","page","$event","preventDefault","stopPropagation","per_page","setChunk","pages","total","current_page","tplType","isPasswordReset","getResetToken","loginForm","$valid","submit","isUserExist","setUser","require","$element","$attrs","$ctrl","$validators","equals","modelValue","viewValue","$$parentForm","$viewValue","bind","e","which","$apply","$eval","onEnterPress","users","mapping","ACCEPTED_USER_ROLES","openUserCreateModal","newUser","reqData","from","to","status","emailAlreadyTaken","openUserEditModal","role","editUser","filteredIndex","filteredUsers","openUserRemoveModal","removeUser","deletedUser","provider","defaults","animation","prefixClass","prefixEvent","target","placement","trigger","keyboard","delay","autoClose","bsEnabled","mouseDownPreventDefault","mouseDownStopPropagation","viewport","selector","padding","$get","$rootScope","$bsCompiler","$animate","$sce","dimensions","$$rAF","$timeout","TooltipFactory","config","enterAnimateCallback","$emit","$tooltip","isDefined","onShow","isFunction","leaveAnimateCallback","onHide","tipElement","_tipToHide","_blur","blur","destroyTipElement","bindTriggerEvents","triggers","on","toggle","enter","leave","nodeName","isTouch","$onFocusElementMouseDown","unbindTriggerEvents","off","bindKeyboardEvents","$onKeyUp","$onFocusKeyUp","unbindKeyboardEvents","bindAutoCloseEvents","stopEventPropagation","$body","hide","_autoCloseEventsBinded","unbindAutoCloseEvents","event","getPosition","isBody","tagName","elRect","getBoundingClientRect","rect","p","width","right","left","height","bottom","top","elOffset","scroll","documentElement","scrollTop","body","outerDims","clientWidth","innerHeight","getCalculatedOffset","position","actualWidth","actualHeight","applyPlacement","tip","offsetWidth","offsetHeight","marginTop","parseInt","css","marginLeft","setOffset","using","props","round","delta","getViewportAdjustedDelta","isVertical","arrowDelta","arrowOffsetPosition","replaceArrow","$viewport","viewportPadding","viewportDimensions","topEdgeOffset","bottomEdgeOffset","leftEdgeOffset","rightEdgeOffset","dimension","isHorizontal","$arrow","$isShown","tipScope","$destroy","$options","promise","$new","parseFloat","$id","attr","trustAsHtml","$setEnabled","isEnabled","$$postDigest","setEnabled","$show","$toggle","hoverState","compileData","tipContainer","init","isElement","destroy","onBeforeShow","parent","after","lastChild","clonedElement","display","visibility","addClass","prepend","safeDigest","$applyPlacement","version","minor","onBeforeHide","evt","setViewport","autoToken","autoPlace","elementPosition","tipWidth","tipHeight","originalPlacement","viewportPosition","removeClass","tipPosition","$$phase","$root","$digest","isNative","navigator","userAgent","$location","$parse","transclusion","tooltip","falseValueRegExp","bsKey","toUpperCase","dataTarget","hasOwnProperty","$observe","newValue","oldValue","bsTooltip","bsShow","match","$on","offsetParentElement","docElement","ownerDocument","offsetParent","fn","extra","currentStyle","window","getComputedStyle","style","boxRect","pageYOffset","clientTop","pageXOffset","scrollLeft","clientLeft","curPosition","curLeft","curCSSTop","curTop","curOffset","curCSSLeft","calculatePosition","curElem","call","offsetParentEl","offsetParentRect","outer","PopoverFactory","$popover","requestAnimationFrame","popover","bsPopover","totalCount","perPage","$document","listener","contains","onClickOutside","$applyAsync","elm","attrs","applyKeyup","onKeyup","allowedKeys","backdropAnimation","backdrop","zIndex","ModalFactory","bodyElement","bindBackdropEvents","modalElement","hideOnBackdropClick","backdropElement","preventEventDefault","unbindBackdropEvents","currentTarget","destroyModalElement","modalScope","dialogBaseZindex","backdropBaseZindex","z-index","backdropCount","defaultPrevented","validSizes","lg","sm","modalClass","bsModal","modal","service","FileSaver","Blob","$localStorage","fromDate","format","selectMenu","menuItem","clearMenu","menuList","setDate","currentWeek","weekMonday","$resolved","deletedIndex","disableDownload","location","path","saveAs","isMenuAuthor","currentUser","ngModel","maxLength","inputMaxLength","val","$modelValue","$setViewValue","inputInteger","digits","min","$render","inputFloat","inputCurrency","only","$parsers","isActive","routeName","activeRoute","current","openLogoutModal","logout","DropdownFactory","onBodyClick","$dropdown","parentEl","$onKeyDown","keyCode","items","matchesSelector","isUndefined","eq","bodyEl","hasClass","Element","prototype","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","tElement","tAttrs","bsDropdown","nextSibling","nodeType","className","parentNode","removeChild","dropdown","useNative","dateType","dateFormat","timezone","modelDateFormat","dayFormat","monthFormat","yearFormat","monthTitleFormat","yearTitleFormat","strictFormat","autoclose","minDate","Infinity","maxDate","startView","minView","startWeek","daysOfWeekDisabled","hasToday","hasClear","iconLeft","iconRight","disableWeek","$dateFormatter","datepickerViews","$datePickerTooltip","DatepickerFactory","updateSelected","selected","$datepicker","$isSelected","focusElement","parentScope","pickerViews","$views","views","viewDate","$mode","$iconLeft","$iconRight","$hasToday","$hasClear","$picker","$select","row","selectedRow","rows","select","$selectPane","$toggleMode","setMode","$setToday","Date","$clear","update","isDate","getTime","$date","$build","updateDisabledDates","dateRanges","disabledDateRanges","l","$setDisabledEl","keep","$dateValue","year","getFullYear","month","getMonth","getDate","mode","pristine","built","build","$updateSelected","disabled","isDisabled","steps","targetDate","UTC","getUTCFullYear","getUTCMonth","getUTCDate","$onMouseDown","targetEl","triggerHandler","shiftKey","altKey","onKeyDown","_init","_destroy","_show","_hide","lang","getDefaultLocale","$dateParser","normalizeDateRanges","ranges","validateAgainstMinMaxDate","parsedDate","isMinValid","datepicker","isMaxValid","$setValidity","getDateFormattedString","formatDate","dateParser","strict","getDateForAttribute","disabledDates","disabledRanges","previousValue","unshift","timezoneOffsetAdjust","toISOString","$formatters","NaN","arrays","mod","n","picker","weekDaysMin","weekdaysShort","weekDaysLabels","weekDaysLabelsHtml","force","firstDayOfMonth","firstDayOfMonthOffset","getTimezoneOffset","firstDate","getDay","firstDateOffset","today","toDateString","days","daylightSavingAdjust","isToday","label","muted","showLabels","labels","week","startRow","nextWeek","setHours","isTodayDisabled","time","newDate","actualTime","months","lastDate","actualMonth","setMonth","firstYear","years","actualYear","setYear","$localeProvider","ParseDate","hours","minutes","seconds","milliseconds","isNumeric","isFinite","indexOfCaseInsensitive","len","str","toString","setMilliseconds","setSeconds","setMinutes","getHours","setFullYear","getMinutes","getSeconds","getMilliseconds","toDate","proto","dateFilter","DateParserFactory","regExpForFormat","re","buildDateAbstractRegex","buildDateParseRegex","escapedFormat","escapeReservedSymbols","escapedLiteralFormat","literalRegex","formatParts","dateElements","regExpMap","dateRegexParts","isFormatStringLiteral","trimLiteralEscapeChars","text","abstractRegex","RegExp","setMapForFormat","buildDateParseValuesMap","valuesMatch","keyIndex","valueKey","valueFunction","valuesRegex","valuesFunctionMap","exec","setFnMap","regex","setMap","sss","ss","s","mm","HH","H","a","EEEE","DAY","EEE","dd","d","MMMM","MONTH","MMM","SHORTMONTH","MM","M","yyyy","yy","y","$format","baseDate","formatRegex","formatSetMap","matches","getTimeForAttribute","undo","splitTimeFormat","getDatetimeFormat","hoursFormat","timeFormat","minutesFormat","secondsFormat","timeSeparator","showSeconds","showAM","userApiService","userData","LOGIN_STATE","isUserLoggedIn","apiToken","getToken","clearToken","firstName","lastName","token","currentTitle","querySelector","textContent","$sessionStorage","collapsed","onSuccess","noResults","searchParams","originalPagination","DROPDOWN_MAPPING","selectedName","stringify","setOrder","scrollTo","openImportModal","placeholder","selectedObject","inputChange","inputChangeParams","onBlur","onBlurParams","ngReadonly","dataField","titleField","descriptionField","imageField","imageUri","inputClass","inputName","userPause","localData","searchFields","minLengthUser","matchClass","lastSearchTerm","currentIndex","justChanged","searchTimer","hideTimer","searching","pause","minLength","searchStr","isNewSearchNeeded","newTerm","oldTerm","processResults","responseData","results","titleFields","titleCode","t","description","image","strPart","resultRow","searchTimerComplete","isFound","hideResults","showDropdown","resetHideResults","hoverRow","keyPressed","selectResult","inputField","duration","dismissable","AlertFactory","bsAlert","alert","TABLES_MAPPING","$qProvider","errorOnUnhandledRejections","run","PermRoleStore","defineRole","roleName","defineManyRoles","Admin","Main Chef","Local Chef","ev","toParams","router","prevState","error","log","message","toState","$stateProvider","$urlRouterProvider","state","permissions","except","redirectTo","default","abstract","$stateParams","otherwise","protocol","hostname","port","userList","$httpProvider","$modalProvider","$alertProvider","$datepickerProvider","$logProvider","$locationProvider","debugEnabled","html5Mode","hashPrefix","interceptors","request","responseError","$broadcast","reject","put"],"mappings":"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","file":"scripts/app-015a383086.js","sourcesContent":["angular.module('components.create-menu.create-menu',\n ['components.datepicker.datepicker',\n 'components.data-access.api.menu-api-service',\n 'components.create-menu-helper.create-menu-helper',\n 'components.data-access.title-service'])\n .directive('createMenu',\n function ($locale, $modal, $state, $alert,\n recipeApiService, userListApiService, menuApiService, createMenuHelper, titleService) {\n return {\n restrict: 'E',\n scope: {\n menuData: '=?',\n },\n replace: true,\n templateUrl: 'app/components/menu/create-menu/create-menu.html',\n link: function ($scope) {\n var SHORT_DAYS = createMenuHelper.getShortDays();\n $scope.localChefs = [];\n titleService.setTitle($scope.menuData ? 'Edit Menu' : 'Create Menu');\n\n $scope.tabs = SHORT_DAYS.map(function (day) {\n return { name: day.toLowerCase(), isSelected: false };\n });\n\n $scope.tabs[0].isSelected = true;\n $scope.selectedTab = $scope.tabs[0];\n\n $scope.menu = createMenuHelper.getMenuData();\n $scope.menu.data = $scope.menuData || $scope.menu.data;\n\n $scope.addNewStation = function (menu) {\n menu[$scope.selectedTab.name].push(angular.copy($scope.menu.emptyStation));\n };\n\n $scope.selectTab = function (selectedTab) {\n $scope.tabs.find(function (tab) {\n return tab.isSelected;\n }).isSelected = false;\n\n selectedTab.isSelected = true;\n $scope.selectedTab = selectedTab;\n };\n\n recipeApiService.getFilters().then(function (filters) {\n $scope.filters = filters;\n });\n\n recipeApiService.getRecipe().then(function (recipes) {\n $scope.recipes = recipes.data;\n $scope.pagination = recipes.meta.pagination;\n });\n\n userListApiService.getLocalChefs().then(function (chefs) {\n $scope.localChefs = chefs;\n });\n\n $scope.removeByIndex = function (recipes, index) {\n return recipes.splice(index, 1);\n };\n\n $scope.selectChefs = function (src, dest) {\n $scope.menu.data.assigned_chefs = dest.slice();\n };\n\n $scope.addRecipe = function (stationRecipes, title, index) {\n return $modal({\n title: title || 'Add Recipe',\n templateUrl: 'app/components/modal/templates/catalogue.html',\n customClass: 'menu-modal-large',\n scope: $scope,\n controller: function ($scope) {\n if (!$scope.recipes) {\n recipeApiService.getRecipe().then(function (recipes) {\n $scope.recipes = recipes.data;\n });\n }\n\n $scope.recipes = $scope.recipes.filter(function (recipe) {\n return stationRecipes.filter(function (item) {\n return item.id === recipe.id;\n }).length === 0;\n });\n\n $scope.onSelectRecipe = function (recipe) {\n if (index !== undefined) {\n stationRecipes[index] = recipe;\n } else {\n stationRecipes.push(recipe);\n }\n $scope.$hide();\n };\n },\n });\n };\n\n $scope.assignChefs = function () {\n return $modal({\n title: 'Assigned to',\n templateUrl: 'app/components/modal/templates/local-chefs.html',\n customClass: 'local-chefs-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.originalList = angular.copy($scope.localChefs);\n $scope.localChefs.forEach(function (localChef) {\n !$scope.menu.data.assigned_chefs.some(function (selectedChef) {\n return localChef.id === selectedChef.id;\n }) && (localChef.isChecked = false);\n });\n\n $scope.menu.data.assigned_chefs.forEach(function (chef) {\n var findedChef = $scope.localChefs.find(function (localChef) {\n return chef.id === localChef.id;\n });\n if (findedChef) {\n findedChef.isChecked = true;\n }\n });\n\n $scope.action = function () {\n $scope.selectChefs('selectedChefs', $scope.localChefs.filter(function (chef) {\n return chef.isChecked;\n }));\n $scope.$hide();\n };\n\n $scope.cancel = function () {\n $scope.$hide();\n };\n },\n });\n };\n\n $scope.openRemoveModal = function (arr, type, index, name) {\n var titles = {\n station: 'Are you sure want to delete this station?',\n recipe: 'Are you sure want to delete this recipe from the menu?',\n stationMenu: 'Are you sure want to delete
' + name + ' station from this menu?',\n chef: 'Are you sure want to deassign
' + name + ' from this menu?',\n };\n\n return $modal({\n title: titles[type],\n templateUrl: 'app/components/modal/templates/confirm.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n $scope.removeByIndex(arr, index);\n $scope.$hide();\n };\n },\n });\n };\n\n $scope.openRemoveMenuModal = function (menuId) {\n return $modal({\n title: 'Are you sure want to delete this menu?',\n templateUrl: 'app/components/modal/templates/confirm.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n menuApiService.deleteMenu(menuId).then(function () {\n $scope.$hide();\n $state.go('main.menu');\n });\n };\n },\n });\n };\n\n $scope.createMenu = function (method, isCopy) {\n $scope.disableSubmit = true;\n var copyMenuData = angular.copy($scope.menu.data);\n var alertTitle = isCopy ?\n 'Copy menu has been created' :\n $scope.menuData ? 'The menu has been changed' : 'New menu has been created';\n\n delete copyMenuData.author_chef_id;\n menuApiService[(method || ($scope.menuData ? 'update' : 'create')) + 'Menu'](copyMenuData, isCopy)\n .then(function (data) {\n $alert({\n content: '' + alertTitle,\n type: 'success',\n show: true,\n container: '.alert-container',\n });\n $state.go('main.' + (isCopy ? 'edit-menu' : 'menu'), {\n menuId: data.id,\n startDate: $scope.menu.data.start_date,\n });\n }, enableSubmit);\n };\n\n $scope.onSetPage = function (offset) {\n $scope.offset = offset;\n\n return recipeApiService.filterRecipes($scope.categories, offset, $scope.sort).then(function (recipes) {\n $scope.filteredRecipes = recipes.data;\n $scope.pagination = recipes.meta.pagination;\n $scope.isChanged = false;\n });\n };\n\n $scope.scheduleHours = createMenuHelper.getScheduleHours();\n\n $scope.scheduleMeal = function (schedule) {\n return $modal({\n title: 'Schedule of meal',\n templateUrl: 'app/components/modal/templates/schedule.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.schedule = angular.copy(schedule) || [];\n\n $scope.cancel = function () {\n $scope.$hide();\n };\n\n $scope.addStation = function () {\n $scope.schedule.length < 10 && $scope.schedule.push({ name: '', start: '', end: '' });\n };\n\n $scope.edit = function () {\n $scope.menu.data.schedule = angular.copy($scope.schedule);\n $scope.$hide();\n };\n\n if ($scope.schedule.length === 0) {\n $scope.addStation();\n }\n },\n });\n };\n\n $scope.cancelPage = function (isEditMenu) {\n var chefsLength = $scope.menu.data.assigned_chefs.length;\n var titleLength = $scope.menu.data.title.length;\n var isRecipesAdded = false;\n var weekDaysKeys = Object.keys($scope.menu.data.weekdays);\n\n weekDaysKeys.map(function (day) {\n $scope.menu.data.weekdays[day].map(function (station) {\n if (station.recipes.length || station.name) {\n isRecipesAdded = true;\n }\n });\n });\n\n if (isEditMenu || chefsLength || titleLength || isRecipesAdded) {\n $modal({\n title: 'Are you sure you want to leave this page? All changes will be lost',\n templateUrl: 'app/components/modal/templates/confirm.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n $scope.$hide();\n $state.go('main.menu');\n };\n },\n });\n } else {\n $state.go('main.menu');\n }\n };\n\n function enableSubmit() {\n $scope.disableSubmit = false;\n }\n },\n };\n });\n\nangular.module('components.create-menu-helper.create-menu-helper', [])\n .factory('createMenuHelper', function($locale) {\n var DEFAULT_STATIONS = [\n {\n name: '',\n recipes: []\n },\n {\n name: '',\n recipes: []\n },\n {\n name: '',\n recipes: []\n },\n {\n name: '',\n recipes: []\n }\n ];\n\n var menu = {\n data: {\n title: '',\n start_date: '',\n weekdays: {\n mon: [],\n tue: [],\n wed: [],\n thu: [],\n fri: [],\n sat: [],\n sun: []\n },\n assigned_chefs: []\n },\n emptyStation: {\n name: '',\n recipes: []\n }\n };\n\n angular.forEach(menu.data.weekdays, function(weekday, field) {\n menu.data.weekdays[field] = angular.copy(DEFAULT_STATIONS);\n });\n\n return {\n getMenuData: function() {\n return angular.copy(menu);\n },\n\n getShortDays: function() {\n var shortDays = angular.copy($locale.DATETIME_FORMATS.SHORTDAY);\n shortDays.push(shortDays.shift());\n\n return shortDays;\n },\n\n getScheduleHours: function() {\n var scheduleHours = [],\n h = 6,\n m = ':00',\n hh = ':30',\n ampm = ' am',\n isSwitched = false;\n\n for(var i = 0; i < 35; i++) {\n var postfix = i % 2 ? hh : m;\n\n if(h > 12) {\n h = 1;\n isSwitched = false;\n }\n\n if(h >= 12 && !isSwitched) {\n ampm = ampm === ' am' ? ' pm' : ' am';\n isSwitched = true;\n }\n\n scheduleHours.push(h + postfix + ampm);\n\n if (i % 2) h++;\n }\n\n return scheduleHours;\n }\n }\n });\n\nangular.module('components.data-access.api.user-list-service', ['ngResource'])\n .factory('userListApiService', function($resource, API_URL, CONFIRM_URL) {\n var URL = API_URL + '/:type/:id';\n\n var userListApi = $resource(URL, {limit: '@limit', offset: '@offset', id: '@id'}, {\n getUsers: {\n method: 'GET',\n params: {\n type: 'users'\n },\n transformResponse: function(res) {\n res = res ? JSON.parse(res) : {};\n res.data = res.data ? res.data.map(function(user) {\n user.fullName = user.first_name + ' ' + user.last_name;\n return user;\n }) : {};\n\n return res;\n }\n },\n\n createUser: {\n method: 'POST',\n params: {\n type: 'users'\n },\n transformResponse: function(res) {\n res = JSON.parse(res);\n res.fullName = res.first_name + ' ' + res.last_name;\n\n return res;\n }\n },\n\n updateUser: {\n method: 'PUT',\n params: {\n type: 'users'\n },\n transformResponse: function(res) {\n res = JSON.parse(res);\n res.fullName = res.first_name + ' ' + res.last_name;\n\n return res;\n }\n },\n\n getLocalChefs: {\n method: 'GET',\n params: {\n type: 'menus',\n id: 'chefs'\n },\n isArray: true\n },\n\n deleteUser: {\n method: 'DELETE',\n params: {\n type: 'users'\n }\n }\n });\n\n return {\n getAllUsers: function() {\n return userListApi.getUsers({limit: 1000, offset: 0}).$promise;\n },\n\n createUser: function(user) {\n user.role_id = user.role_id.id;\n user.confirm_url = CONFIRM_URL;\n\n return userListApi.createUser(user).$promise;\n },\n\n updateUser: function(user) {\n user.role_id = user.role_id.id;\n\n return userListApi.updateUser(user).$promise;\n },\n\n deleteUser: function(id) {\n return userListApi.deleteUser({id: id}).$promise;\n },\n\n getLocalChefs: function() {\n return userListApi.getLocalChefs().$promise;\n }\n }\n });\n\nangular.module('components.data-access.api.user-api-service', ['ngResource'])\n .factory('userApiService', function($resource, API_URL, CONFIRM_URL) {\n var URL = API_URL + '/:type/:action';\n\n var userApi = $resource(URL, {}, {\n login: {\n method: 'POST',\n params: {\n type: 'session'\n }\n },\n\n resetPassword: {\n method: 'POST',\n params: {\n type: 'users',\n action: 'reset-password'\n }\n },\n\n changePassword: {\n method: 'PUT',\n params: {\n type: 'users',\n action: 'update-password'\n }\n },\n\n checkResetToken: {\n method: 'POST',\n params: {\n type: 'users',\n action: 'check-password-reset-token'\n }\n }\n });\n\n return {\n login: function(user) {\n return userApi.login(user).$promise;\n },\n\n resetPassword: function(email) {\n var data = {\n email: email,\n 'confirm_url': CONFIRM_URL\n };\n\n return userApi.resetPassword(data).$promise;\n },\n\n changePassword: function(password, resetToken) {\n var data = {\n 'reset_token': resetToken,\n 'new_password': password\n };\n\n return userApi.changePassword(data).$promise;\n },\n\n checkResetToken: function(resetToken) {\n var data = {\n 'reset_token': resetToken\n };\n\n return userApi.checkResetToken(data).$promise;\n }\n }\n });\n\nangular.module('components.data-access.api.recipe-api-service', ['ngResource'])\n .factory('recipeApiService', function($resource, API_URL) {\n var URL = API_URL + '/:type/:action/:id/:size';\n\n function getIds(arr) {\n return Array.isArray(arr) ? arr.map(function(el) {\n return el.id;\n }) : arr.id;\n }\n\n var recipeApi = $resource(URL, {}, {\n createRecipe: {\n method: 'POST',\n params: {\n type: 'recipes'\n }\n },\n\n updateRecipe: {\n method: 'PUT',\n params: {\n type: 'recipes',\n id: '@id'\n }\n },\n\n deleteRecipe: {\n method: 'DELETE',\n params: {\n type: 'recipes'\n }\n },\n\n getFilters: {\n method: 'GET',\n params: {\n type: 'recipes',\n action: 'general-options-list'\n }\n },\n\n getRecipe: {\n method: 'GET',\n params: {\n type: 'recipes'\n }\n },\n\n getSubRecipe: {\n method: 'GET',\n params: {\n action: 'subrecipes'\n }\n },\n\n calculateRecipe: {\n method: 'PUT',\n params: {\n type: 'recipes',\n action: 'recalculate',\n id: '@id',\n size: '@size'\n }\n },\n\n importRecipe: {\n method: 'GET',\n params: {\n type: 'recipes',\n action: 'import'\n }\n },\n\n searchRecipe: {\n method: 'GET',\n isArray: true,\n params: {\n type: 'recipes',\n action: 'search'\n }\n },\n\n getNutritionFacts: {\n method: 'POST',\n isArray: true,\n params: {\n type: 'ingredients',\n action: 'calc'\n }\n },\n\n getIngredients: {\n method: 'GET',\n params: {\n type: 'ingredients',\n action: 'nid',\n unit: 'unit',\n amount: 'amount'\n }\n },\n\n searchIngredients: {\n method: 'GET',\n params: {\n type: 'ingredients',\n action: 'search'\n },\n isArray: true\n }\n });\n\n return {\n filterPromise: {},\n\n saveFilters: function(data) {\n this.filterPromise.data = angular.copy(data);\n },\n\n getDefaultFilters: function() {\n return this.filterPromise.data || this.getFilters();\n },\n\n createRecipe: function(recipe, isCopy) {\n var recipeCopy = angular.copy(recipe);\n\n var recipeData = {\n title: isCopy ? 'Copy of ' + recipeCopy.mainRecipe.title : recipeCopy.mainRecipe.title,\n serving: recipeCopy.mainRecipe.serving,\n portion: {\n size: recipeCopy.mainRecipe.portion.size,\n unit: getIds(recipeCopy.mainRecipe.portion.unit)\n },\n categories_id: getIds(recipeCopy.mainRecipe.categories),\n allergens_id: getIds(recipeCopy.mainRecipe.allergens),\n dietaries_id: getIds(recipeCopy.mainRecipe.dietaries),\n sub_recipes: recipeCopy.recipes.map(function(subrecipe, index) {\n subrecipe.ingredients = subrecipe.ingredients.map(function(ingredient) {\n var ing = {\n id: ingredient.nid - 0,\n amount: ingredient.amount,\n unit_id: getIds(ingredient.unit)\n };\n\n if(!ingredient.nid) {\n ing = {\n amount: ingredient.amount,\n custom: {\n name: ingredient.name,\n unit: {\n calories: ingredient.calories - 0,\n total_fat: ingredient.total_fat - 0,\n saturated_fat: ingredient.saturated_fat ? ingredient.saturated_fat - 0 : 0,\n cholesterol: ingredient.cholesterol - 0,\n sodium: ingredient.sodium - 0,\n carbohydrate: ingredient.carbohydrate - 0,\n dietary_fiber: ingredient.dietary_fiber - 0,\n protein: ingredient.protein - 0,\n sugar: ingredient.sugar - 0,\n name: ingredient.unit.value\n }\n }\n }\n }\n\n return ing;\n });\n\n return {\n title: index === 0 ? recipeCopy.mainRecipe.title : subrecipe.title,\n ingredients: subrecipe.ingredients,\n methods: subrecipe.methods.filter(function(method) {\n return !!method.desc;\n })\n }\n })\n };\n\n if(recipeCopy.mainRecipe.cuisine && recipeCopy.mainRecipe.cuisine.id) {\n recipeData.cuisine_id = getIds(recipeCopy.mainRecipe.cuisine);\n }\n\n if(recipeCopy.mainRecipe.photo) {\n recipeData.photo = recipeCopy.mainRecipe.photo.id || recipeCopy.mainRecipe.photo;\n }\n\n return recipeApi.createRecipe(recipeData).$promise;\n },\n\n updateRecipe: function(recipe) {\n var recipeCopy = angular.copy(recipe);\n\n var recipeData = {\n id: recipeCopy.id,\n title: recipeCopy.mainRecipe.title,\n serving: recipeCopy.mainRecipe.serving,\n portion: {\n size: recipeCopy.mainRecipe.portion.size,\n unit: getIds(recipeCopy.mainRecipe.portion.unit)\n },\n categories_id: getIds(recipeCopy.mainRecipe.categories),\n allergens_id: getIds(recipeCopy.mainRecipe.allergens),\n dietaries_id: getIds(recipeCopy.mainRecipe.dietaries),\n sub_recipes: recipeCopy.recipes.map(function(subrecipe, index) {\n subrecipe.ingredients = subrecipe.ingredients.map(function(ingredient) {\n var ing = {\n id: ingredient.nid - 0,\n amount: ingredient.amount,\n unit_id: getIds(ingredient.unit)\n };\n\n if(!ingredient.nid) {\n ing = {\n amount: ingredient.amount,\n custom: {\n name: ingredient.name,\n unit: {\n calories: ingredient.calories - 0,\n total_fat: ingredient.total_fat - 0,\n saturated_fat: ingredient.saturated_fat ? ingredient.saturated_fat - 0 : 0,\n cholesterol: ingredient.cholesterol - 0,\n sodium: ingredient.sodium - 0,\n carbohydrate: ingredient.carbohydrate - 0,\n dietary_fiber: ingredient.dietary_fiber - 0,\n protein: ingredient.protein - 0,\n sugar: ingredient.sugar - 0,\n name: ingredient.unit.value\n }\n }\n }\n }\n\n return ing;\n });\n\n return {\n title: index === 0 ? recipeCopy.mainRecipe.title : subrecipe.title,\n ingredients: subrecipe.ingredients,\n methods: subrecipe.methods.filter(function(method) {\n return !!method.desc;\n })\n }\n }),\n photo: (recipeCopy.mainRecipe.photo && recipeCopy.mainRecipe.photo.id) || recipeCopy.mainRecipe.photo\n };\n\n if(recipeCopy.mainRecipe.cuisine && recipeCopy.mainRecipe.cuisine.id) {\n recipeData.cuisine_id = getIds(recipeCopy.mainRecipe.cuisine);\n }\n\n return recipeApi.updateRecipe(recipeData).$promise;\n },\n\n patchRecipe: function(recipe) {\n var recipeCopy = angular.copy(recipe);\n\n var recipeData = {\n id: recipeCopy.id,\n title: recipeCopy.title,\n serving: recipeCopy.serving,\n portion: recipeCopy.portion,\n categories_id: getIds(recipeCopy.categories),\n allergens_id: getIds(recipeCopy.allergens),\n dietaries_id: getIds(recipeCopy.dietaries),\n sub_recipes: recipeCopy.sub_recipes.map(function(subrecipe) {\n subrecipe.ingredients = subrecipe.ingredients.map(function(ingredient) {\n var ing = {\n id: ingredient.id - 0,\n amount: ingredient.amount,\n unit_id: getIds(ingredient.unit)\n };\n if(ingredient.user_title) {\n ing.user_title = ingredient.user_title;\n }\n\n return ing;\n });\n\n return {\n title: subrecipe.title,\n ingredients: subrecipe.ingredients,\n methods: subrecipe.methods.filter(function(method) {\n return !!method.desc;\n })\n }\n }),\n photo: (recipeCopy.photo && recipeCopy.photo.id) || recipeCopy.photo\n };\n\n if(recipeCopy.cuisine && recipeCopy.cuisine.id) {\n recipeData.cuisine_id = getIds(recipeCopy.cuisine);\n }\n\n return recipeApi.updateRecipe(recipeData).$promise;\n },\n\n deleteRecipe: function(id) {\n return recipeApi.deleteRecipe({id: id}).$promise;\n },\n\n getFilters: function() {\n return recipeApi.getFilters().$promise;\n },\n\n getRecipe: function(recipeId) {\n return recipeApi.getRecipe({id: recipeId || '', limit: 51}).$promise;\n },\n\n getSubRecipe: function(subRecipeId) {\n return recipeApi.getSubRecipe({id: subRecipeId}).$promise;\n },\n\n calculateRecipe: function(data) {\n return recipeApi.calculateRecipe(data).$promise;\n },\n\n importRecipe: function(recipeUrl) {\n return recipeApi.importRecipe({url: recipeUrl}).$promise;\n },\n\n filterRecipes: function(categories, offset, sort) {\n sort = sort || {};\n offset = offset || 0;\n var options = {\n 'category[]': categories['category[]'],\n 'cuisine[]': categories['cuisine[]'],\n 'dietary[]': categories['dietary[]'],\n limit: 51,\n offset: offset,\n sort: sort.predicate,\n direction: sort.dir\n };\n return recipeApi.getRecipe(options).$promise;\n },\n\n getPhotoUrl: function() {\n return API_URL + '/recipes/photo';\n },\n\n searchRecipe: function(search) {\n return recipeApi.searchRecipe({q: search}).$promise;\n },\n\n getIngredients: function(data) {\n return recipeApi.getIngredients({id: data.nid, unit: data.unit, amount: data.amount}).$promise;\n },\n\n searchIngredients: function(search) {\n return recipeApi.searchIngredients({q: search}).$promise;\n },\n\n getNutritionFacts: function(ingredient) {\n var ing = angular.copy(ingredient);\n ing.unit = ing.unit.value;\n delete ing.name;\n delete ing.amount;\n\n return recipeApi.getNutritionFacts(ing).$promise;\n }\n }\n });\n\nangular.module('components.data-access.api.menu-api-service', ['ngResource'])\n .factory('menuApiService', function($resource, $http, API_URL, moment, $filter) {\n function transformMenuData(menuData, skipDelete, isCopy) {\n menuData.assigned_chefs = menuData.assigned_chefs && menuData.assigned_chefs.length ? menuData.assigned_chefs.map(function(chef) {\n return chef.id;\n }) : [];\n menuData.start_date = $filter('date')(menuData.start_date, 'yyyy-MM-dd');\n angular.forEach(menuData.weekdays, function(weekday) {\n weekday.forEach(function(day, index) {\n weekday[index] = {\n name: day.name,\n recipes: day.recipes\n };\n\n weekday[index].recipes = day.recipes.map(function(recipe) {\n return {recipe_id: recipe.id, price: recipe.price};\n })\n });\n });\n\n if(menuData.id && !skipDelete) {\n delete menuData.id;\n delete menuData.author_chef_name;\n }\n\n if(isCopy) {\n menuData.title = 'Copy of ' + menuData.title;\n }\n }\n\n var URL = API_URL + '/:type/:action';\n\n var menuApi = $resource(URL, {}, {\n createMenu: {\n method: 'POST',\n params: {\n type: 'menus'\n }\n },\n\n updateMenu: {\n method: 'PUT',\n params: {\n type: 'menus',\n action: '@id'\n }\n },\n\n deleteMenu: {\n method: 'DELETE',\n params: {\n type: 'menus',\n action: '@id'\n }\n },\n\n getMenu: {\n method: 'GET',\n params: {\n type: 'menus'\n }\n },\n\n getMenuList: {\n method: 'GET',\n isArray: true,\n params: {\n type: 'menus'\n }\n }\n });\n\n return {\n createMenu: function(data, isCopy) {\n var menuData = angular.copy(data);\n transformMenuData(menuData, false, isCopy);\n\n return menuApi.createMenu(menuData).$promise;\n },\n\n updateMenu: function(data) {\n var menuData = angular.copy(data);\n transformMenuData(menuData, true);\n\n return menuApi.updateMenu(menuData).$promise;\n },\n\n deleteMenu: function(menuId) {\n return menuApi.deleteMenu({action: menuId}).$promise;\n },\n\n getMenu: function(menuId) {\n return menuApi.getMenu({action: menuId}).$promise.then(function(menuData) {\n menuData.start_date = moment(menuData.start_date).utcOffset(0)._d;\n\n return menuData;\n });\n },\n\n getMenuList: function(date) {\n return menuApi.getMenuList({date: date || $filter('date')(moment().day(1)._d, 'yyyy-MM-dd')}).$promise;\n },\n\n downloadMenuSheet: function(menuId) {\n return $http({\n url: API_URL + '/menus/' + menuId + '/download',\n method: 'GET'\n });\n },\n\n downloadMenuTemplate: function(menuId) {\n return $http({\n url: API_URL + '/menus/' + menuId + '/word',\n method: 'GET'\n });\n },\n\n downloadMenuPDF: function(menuId) {\n return $http({\n url: API_URL + '/export/menu/' + menuId,\n method: 'GET',\n headers: {\n 'Content-Type': 'application/pdf',\n 'Accept': 'application/pdf'\n },\n responseType: 'blob'\n });\n }\n }\n });\n\nangular.module(\"components.catalogue.view-recipe.view-recipe\",\n [\"components.nutritions-table.nutritions-table\", \"components.data-access.title-service\"])\n .directive(\"viewRecipe\",\n function ($window, $modal, placeholderColors, NUTRITION_MAPPING,\n userService, PermPermissionStore, recipeApiService, titleService, recipeHelper) {\n return {\n restrict: \"E\",\n scope: {\n recipe: \"=\",\n },\n replace: true,\n templateUrl: \"app/components/catalogue/view-recipe/view-recipe.html\",\n link: function ($scope) {\n $scope.print = function () {\n return $window.print();\n };\n $scope.helper = recipeHelper;\n $scope.NUTRITION_MAPPING = NUTRITION_MAPPING;\n $scope.categoriesToPrint = [];\n $scope.addSection = [].concat($scope.recipe.allergens);\n $scope.disableApply = true;\n $scope.disableReset = $scope.recipe.serving === $scope.recipe.default.serving;\n\n $scope.NUTRITION_TO_PRINT_MAPPING = [\n { key: \"Calories\", value: \"calories\" },\n {\n key: \"Total Fat\", value: \"total_fat\", categories: [{\n key: \"Saturated Fat\", value: \"saturated_fat\", unit: \"g\",\n }], unit: \"g\",\n },\n { key: \"Cholesterol\", value: \"cholesterol\", unit: \"mg\" },\n { key: \"Sodium\", value: \"sodium\", unit: \"mg \" },\n {\n key: \"Total Carbohydrates\",\n categories: [{ key: \"Dietary Fiber\", value: \"dietary_fiber\", unit: \"g\" }, {\n key: \"Total Sugars\",\n value: \"sugar\",\n unit: \"g\",\n }],\n value: \"carbohydrate\",\n unit: \"g\",\n },\n { key: \"Protein\", value: \"protein\", unit: \"g\" },\n ];\n\n $scope.calculateIngredients = function (servingSize) {\n return recipeApiService.calculateRecipe({\n size: servingSize,\n id: $scope.recipe.id,\n }).then(function (calculatedRecipe) {\n $scope.disableApply = true;\n $scope.disableReset = $scope.recipe.serving === $scope.recipe.default.serving;\n return $scope.recipe = calculatedRecipe;\n });\n };\n\n $scope.onChangeServings = function () {\n $scope.disableApply = (!$scope.recipe.serving);\n };\n\n $scope.color = placeholderColors.getColor();\n\n titleService.setTitle($scope.recipe.title);\n\n $scope.recipe.dietaries.forEach(function (category) {\n var labelTypes = [\"vegetarian\", \"vegan\", \"gluten free\"];\n var categoryName = category.name.toLowerCase();\n\n if (labelTypes.indexOf(categoryName) + 1) {\n $scope.categoriesToPrint.push(categoryName.split(\" \").join(\"_\"));\n }\n });\n\n PermPermissionStore\n .definePermission(\"canEditRecipe\", function () {\n return userService.getUser(\"id\") === $scope.recipe.chef.id;\n });\n\n $scope.getIngredientsForPrint = function (ingredients) {\n var result = [];\n ingredients.forEach(function (ingredient) {\n result.push(ingredient.user_title || ingredient.name);\n });\n return result.join(\", \");\n };\n\n $scope.openEditModal = function (ingredient) {\n return $modal({\n title: \"Change ingredient name\",\n templateUrl: \"app/components/modal/templates/edit-ingredient.html\",\n customClass: \"user-create-modal\",\n scope: $scope,\n controller: function ($scope) {\n $scope.ingredient = ingredient;\n $scope.ingredientName = ingredient.user_title || ingredient.name;\n\n $scope.resetToDefault = function (defaultValue) {\n $scope.ingredientName = defaultValue;\n };\n\n $scope.action = function (ingredientName) {\n ingredient.user_title = ingredientName;\n $scope.disableSubmit = true;\n return recipeApiService.patchRecipe($scope.recipe).then(function () {\n $scope.$hide();\n }, function enableSubmit() {\n $scope.disableSubmit = false;\n ingredient.user_title = ingredientName;\n });\n };\n },\n });\n };\n\n $scope.transformNutritions = function() {\n $scope.recipe.sub_recipes.forEach(function(recipe) {\n recipe = $scope.helper.transformIngredients(recipe);\n });\n var totalNutritions = {};\n\n $scope.recipe.sub_recipes.forEach(function (recipe) {\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n if (totalNutritions[nutrition.value] === undefined) {\n totalNutritions[nutrition.value] = 0;\n }\n recipe.nutritionsSum = recipe.nutritionsSum || {};\n totalNutritions[nutrition.value] += angular.isNumber(recipe.nutritionsSum[nutrition.value] - 0) ? recipe.nutritionsSum[nutrition.value] : 0;\n });\n });\n };\n\n $scope.transformNutritions();\n\n $scope.$watch(\"recipe.sub_recipes\", function (subRecipes) {\n if (subRecipes) {\n $scope.addSection = $scope.addSection = [].concat($scope.recipe.allergens);\n\n subRecipes.forEach(function (subRecipe) {\n $scope.addSection = $scope.addSection.concat(subRecipe.ingredients);\n });\n\n $scope.addSection = $scope.addSection.map(function (section) {\n return section.user_title ? section.user_title : section.name;\n }).join(\"\");\n }\n }, true);\n },\n };\n\n }).factory(\"placeholderColors\", function () {\n var colors = [\"#FFEED6\", \"#ECE4F7\", \"#DAEFFA\", \"#FFF5D6\", \"#FCE1EF\", \"#E5F6D3\"];\n\n return {\n getColor: function () {\n return colors[Math.floor(Math.random() * colors.length)];\n },\n };\n});\n\nangular.module(\"components.catalogue.recipe-list.recipe-list\", [])\n .directive(\"recipeList\", function ($state) {\n return {\n restrict: \"E\",\n scope: {\n recipes: \"=\",\n onSelect: \"=?\",\n isLoading: \"=\",\n },\n replace: true,\n templateUrl: \"app/components/catalogue/recipe-list/recipe-list.html\",\n link: function ($scope) {\n $scope.onSelect = $scope.onSelect || function (recipe) {\n return $state.go(\"main.view-recipe\", { recipeId: recipe.id });\n };\n\n $scope.getRandomColor = function (num) {\n var colors = [\"violet\", \"pink\", \"yellow\", \"green\", \"orange\", \"blue\"];\n var index = Math.floor(num%6) > 5 ? 0 : Math.floor(num%6);\n return colors[index];\n };\n },\n };\n }).filter(\"truncate\", function () {\n return function (input, chars, breakOnWord) {\n if (isNaN(chars)) return input;\n if (chars <= 0) return \"\";\n if (input && input.length > chars) {\n input = input.substring(0, chars);\n\n if (!breakOnWord) {\n var lastspace = input.lastIndexOf(\" \");\n //get last space\n if (lastspace !== -1) {\n input = input.substr(0, lastspace);\n }\n } else {\n while (input.charAt(input.length - 1) === \" \") {\n input = input.substr(0, input.length - 1);\n }\n }\n return input + \"…\";\n }\n return input;\n };\n});\n\nangular.module('components.catalogue.recipe-filters.recipe-filters', [])\n .directive('recipeFilters', function () {\n return {\n restrict: 'E',\n scope: {\n filters: '=',\n onChange: '=?',\n categoriesFilter: '=?',\n isMenuState: '=?'\n },\n templateUrl: 'app/components/catalogue/recipe-filters/recipe-filters.html',\n replace: true,\n link: function ($scope) {\n $scope.categories = {\n 'cuisine[]': [],\n 'category[]': [],\n 'dietary[]': []\n };\n\n if ($scope.categoriesFilter && Object.keys($scope.categoriesFilter).length) {\n $scope.categories = initFilter($scope.categoriesFilter);\n }\n\n $scope.onChange = $scope.onChange || angular.noop;\n\n $scope.selectOption = function (data, field, name, skipChangeCb) {\n var index = $scope.categories[name].indexOf(data.id);\n\n if (index === -1 && data.isChecked) {\n $scope.categories[name].push(data.id);\n }\n if (index !== -1 && !data.isChecked) {\n $scope.categories[name].splice(index, 1);\n }\n\n !skipChangeCb && $scope.onChange($scope.categories);\n };\n\n $scope.selectAllOptions = function (data, field, name, checkbox) {\n data.forEach(function (category) {\n category.isChecked = checkbox.isChecked;\n $scope.selectOption(category, field, name, true);\n });\n\n $scope.onChange($scope.categories);\n };\n\n $scope.clearAll = function () {\n angular.forEach($scope.categories, function (category) {\n category.length = 0;\n });\n\n $scope.filters.cuisines.forEach(function (cuisine) {\n cuisine.isChecked = false;\n });\n\n $scope.filters.category_groups.forEach(function (categoryGroup) {\n categoryGroup.isChecked = false;\n categoryGroup.categories.forEach(function (category) {\n category.isChecked = false;\n });\n });\n\n $scope.onChange($scope.categories);\n };\n\n if ($scope.isMenuState) {\n $scope.clearAll();\n }\n\n function initFilter(categories) {\n $scope.filters.cuisines.forEach(function (cuisine) {\n if (categories['cuisine[]'].indexOf(cuisine.id) > -1) {\n cuisine.isChecked = true;\n }\n });\n\n $scope.filters.category_groups.forEach(function (categoryGroup) {\n categoryGroup.categories.forEach(function (category) {\n if (categories['category[]'].indexOf(category.id) > -1) {\n category.isChecked = true;\n }\n });\n });\n\n $scope.filters.dietary.forEach(function (dietary) {\n if (categories['dietary[]'].indexOf(dietary.id) > -1) {\n dietary.isChecked = true;\n }\n });\n\n return categories;\n }\n }\n };\n });\n\nangular.module(\n \"components.catalogue.create-recipe.create-recipe\",\n [\"angucomplete\", \"components.max-length\", \"components.data-access.title-service\"])\n .directive(\"createRecipe\",\n function (recipeData, titleService, $modal, $window, recipeApiService, $state, $filter, $alert, API_URL, recipeHelper, NUTRITION_MAPPING, Upload) {\n return {\n restrict: \"E\",\n scope: {\n options: \"=\",\n recipe: \"=?\",\n },\n templateUrl: \"app/components/catalogue/create-recipe/create-recipe.html\",\n link: function ($scope) {\n $scope.API_URL = API_URL;\n $scope.NUTRITION_MAPPING = NUTRITION_MAPPING;\n $scope.totalNutritions = {};\n $scope.totalNutritionsWithServing = {};\n $scope.disableSubmit = true;\n $scope.options.cuisines = $filter(\"orderBy\")($scope.options.cuisines, \"name\");\n\n $scope.recipeData = angular.copy(recipeData);\n\n $scope.helper = recipeHelper;\n\n titleService.setTitle($scope.recipe ? \"Edit recipe\" : \"Create recipe\");\n\n $scope.selectOption = function (data, field) {\n var index = $scope.recipeData.mainRecipe[field].findIndex(function (option) {\n return option.id === data.id;\n });\n\n if (index !== -1) {\n $scope.recipeData.mainRecipe[field].splice(index, 1);\n } else {\n $scope.recipeData.mainRecipe[field].push(data);\n }\n };\n\n $scope.getColumnsCount = function (length, limit) {\n return Math.ceil(length / limit);\n };\n\n $scope.uploadImage = function (img, invalidFiles) {\n $scope.recipeData.mainRecipe.photo = null;\n\n $scope.invalidImg = !!invalidFiles.length;\n if (img) {\n $scope.img = img;\n }\n };\n\n $scope.onBlurIngredient = function (ingredient, name, recipe, $index) {\n $scope.helper.checkIngredient(ingredient, name, recipe, $index);\n $scope.checkSubmit();\n };\n\n $scope.checkSubmit = function () {\n $scope.disableSubmit = !isValidRecipe(false);\n };\n\n $scope.checkSubrecipe = function (subRecipe, name) {\n subRecipe.title = name;\n $scope.checkSubmit();\n };\n\n function enableSubmit() {\n $scope.disableSubmit = false;\n }\n\n function isValidRecipe(forCancel) {\n var recipeTitleLength = $scope.recipeData.mainRecipe.title ? $scope.recipeData.mainRecipe.title.length : false;\n var ingredientsLength = [];\n var methodsLength = [];\n var nutritionsLength = true;\n var isValid = false;\n\n $scope.recipeData.recipes.map(function (recipe) {\n recipe.methods.map(function (el) {\n if (el.desc !== \"\") {\n methodsLength.push(el);\n }\n });\n recipe.ingredients.map(function (el) {\n if (el.name !== \"\") {\n ingredientsLength.push(el);\n }\n if (!el.nutritionSum) {\n nutritionsLength = false;\n }\n });\n });\n\n if (forCancel) {\n isValid = (recipeTitleLength || ingredientsLength.length || methodsLength.length);\n } else {\n isValid = (recipeTitleLength && ingredientsLength.length && nutritionsLength);\n }\n\n return isValid;\n }\n\n $scope.removeByIndex = function (recipe, index, recipeArr, title) {\n return $modal({\n title: \"Are you sure want to delete this \" + title + \"?\",\n templateUrl: \"app/components/modal/templates/confirm.html\",\n customClass: \"user-create-modal\",\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n recipe.splice(index, 1);\n $scope.$hide();\n $scope.changeAmount(recipeArr || recipe, index <= 0 ? index : index - 1);\n };\n },\n });\n };\n\n $scope.editNutritions = function (ingredient, recipe, $index) {\n return $modal({\n title: \"Nutrition facts\",\n templateUrl: \"app/components/modal/templates/edit-nutritions.html\",\n customClass: \"user-create-modal\",\n scope: $scope,\n controller: function ($scope) {\n $scope.originalVal = angular.copy(ingredient);\n $scope.ingredient = ingredient;\n\n $scope.cancel = function () {\n recipe.ingredients[$index] = $scope.originalVal;\n $scope.$hide();\n };\n\n $scope.edit = function () {\n if ($scope.ingredient.unit.id !== \"lbs\" && $scope.ingredient.unit.id !== \"qty\") {\n recipeApiService.getNutritionFacts($scope.ingredient).then(function (units) {\n $scope.ingredient.units = units;\n $scope.changeAmount(recipe, $index);\n $scope.$hide();\n });\n } else {\n $scope.changeAmount(recipe, $index);\n $scope.$hide();\n }\n };\n },\n });\n };\n\n $scope.calculateTotalNutritions = function (skipAdding) {\n if (skipAdding) {\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n $scope.totalNutritionsWithServing[nutrition.value] = $scope.totalNutritions[nutrition.value] / ($scope.recipeData.mainRecipe.serving || 1);\n });\n\n return;\n }\n\n $scope.recipeData.recipes.forEach(function (recipe) {\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n if ($scope.totalNutritions[nutrition.value] === undefined) {\n $scope.totalNutritions[nutrition.value] = 0;\n }\n recipe.nutritionsSum = recipe.nutritionsSum || {};\n $scope.totalNutritions[nutrition.value] += angular.isNumber(recipe.nutritionsSum[nutrition.value] - 0) ? recipe.nutritionsSum[nutrition.value] : 0;\n });\n });\n\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n $scope.totalNutritionsWithServing[nutrition.value] = $scope.totalNutritions[nutrition.value] / $scope.recipeData.mainRecipe.serving;\n });\n $scope.checkSubmit();\n };\n\n $scope.changeAmount = function (recipe, $index) {\n $index = $index || 0;\n if (!recipe.ingredients || !recipe.ingredients.length) {\n return;\n }\n\n $scope.totalNutritions = {};\n\n recipe.ingredients[$index] = recipe.ingredients[$index] || { nutritionSum: {} };\n recipe.ingredients[$index].nutritionSum = {};\n recipe.nutritionsSum = {};\n\n recipe.ingredients.forEach(function (ingredient) {\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.nutritionsSum[nutrition.value] = $scope.helper.calculateNutritionSum(recipe.nutritionsSum, ingredient, nutrition.value, 0, $scope.editRecipe);\n });\n });\n\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.ingredients[$index].nutritionSum[nutrition.value] =\n $scope.helper.calculateNutritionSum(recipe.ingredients[$index].nutritionSum, recipe.ingredients[$index], nutrition.value, 1, $scope.editRecipe);\n });\n\n $scope.calculateTotalNutritions();\n };\n\n $scope.checkIngredient = function (ingredient, part) {\n if (!ingredient[part]) {\n ingredient[part] = \"N/A\";\n }\n };\n\n $scope.getInfo = function (value, ingredient, recipe, $index) {\n recipeApiService.getIngredients({ nid: value.originalObject.nid }).then(function (ingredients) {\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n ingredient[nutrition.value] = ingredients.units[0][nutrition.value] && ingredients.units[0][nutrition.value].toFixed(2);\n });\n\n ingredient.units = $scope.helper.checkUnits(ingredients.units);\n ingredient.name = ingredients.name;\n ingredient.nid = ingredients.id;\n ingredient.unit = ingredient.units[0];\n ingredient.amount = recipe.ingredients[$index].amount || 1;\n ingredient.is_custom = ingredients.is_custom;\n\n recipe.ingredients[$index] = ingredient;\n\n $scope.changeAmount(recipe, $index);\n\n var timeout = setTimeout(function () {\n var el = document.getElementById(ingredient.nid + \"_value\");\n el.focus();\n clearTimeout(timeout);\n }, 10);\n });\n };\n\n $scope.getSubRecipe = function (value, subRecipe, recipe, $index) {\n recipeApiService.getSubRecipe(value.originalObject.id).then(function (subRecipe) {\n $scope.recipeData.recipes[$index] = subRecipe;\n subRecipe.ingredients.forEach(function (ingredient, index) {\n var unitIndex = ingredient.units.findIndex(function (unit) {\n return unit.name === ingredient.unit.name;\n });\n if (unitIndex === -1) {\n unitIndex = 0;\n }\n\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n ingredient[nutrition.value] = ingredient.units[unitIndex][nutrition.value] && ingredient.units[unitIndex][nutrition.value].toFixed(2);\n });\n\n if (subRecipe.ingredients[index].is_custom) {\n var id = subRecipe.ingredients[index].unit.name === \"cup\" ? \"cups\" : subRecipe.ingredients[index].unit.name;\n\n subRecipe.ingredients[index].unit = {\n name: id,\n id: id,\n value: subRecipe.ingredients[index].unit.name,\n };\n subRecipe.ingredients[index].units = null;\n } else {\n subRecipe.ingredients[index].nid = subRecipe.ingredients[index].id;\n subRecipe.ingredients[index].units = subRecipe.ingredients[index].units.map(function (unit) {\n return { name: unit.name, id: unit.id, nutritions: unit };\n });\n subRecipe.ingredients[index].unit = subRecipe.ingredients[index].units.find(function (unit) {\n return subRecipe.ingredients[index].unit.id === unit.id;\n });\n }\n $scope.changeAmount(subRecipe, index);\n });\n });\n };\n\n $scope.changeIngredientUnit = function (unit, recipe, $index) {\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.ingredients[$index][nutrition.value] = unit.nutritions[nutrition.value].toFixed(2);\n });\n\n $scope.changeAmount(recipe, $index);\n };\n\n $scope.changeCustomIngredientUnit = function (unit, recipe, $index) {\n recipe.ingredients[$index].units = recipe.ingredients[$index].units || [];\n\n var nutritions = recipe.ingredients[$index].units.find(function (ing) {\n return ing.name === unit.value;\n }) || {};\n\n $scope.NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.ingredients[$index][nutrition.value] = nutritions[nutrition.value] ? nutritions[nutrition.value].toFixed(2) : undefined;\n });\n\n $scope.changeAmount(recipe, $index);\n };\n\n $scope.submitRecipe = function (method, isCopy) {\n var upload = {};\n\n if ($scope.img) {\n upload = Upload.upload({\n url: recipeApiService.getPhotoUrl(),\n data: { photo: $scope.img },\n method: \"POST\",\n });\n\n upload.then(function (photo) {\n $scope.recipeData.mainRecipe.photo = photo.data.id;\n saveRecipe(method, isCopy);\n });\n } else {\n saveRecipe(method, isCopy);\n }\n };\n\n function saveRecipe(method, isCopy) {\n $scope.disableSubmit = true;\n recipeApiService[method + \"Recipe\"]($scope.recipeData, isCopy)\n .then(function (data) {\n $state.go(\"main.\" + (isCopy ? \"edit\" : \"view\") + \"-recipe\", { recipeId: data.id });\n showAlert(isCopy, method);\n },\n enableSubmit);\n }\n\n function showAlert(isCopy, method) {\n var alertTitle = isCopy ? \"Copy recipe has been created\" :\n method === \"create\" ? \"New recipe has been created\" : \"The recipe has been changed\";\n $alert({\n content: \"\" + alertTitle,\n type: \"success\",\n show: true,\n container: \".alert-container\"\n });\n\n }\n\n $scope.deleteRecipe = function (id) {\n return $modal({\n title: \"Are you sure want to delete this recipe? It may affect menus\",\n templateUrl: \"app/components/modal/templates/confirm.html\",\n customClass: \"user-create-modal\",\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n return recipeApiService.deleteRecipe(id).then(function () {\n $scope.$hide();\n $state.go(\"main.catalogue\");\n });\n };\n },\n });\n };\n\n $scope.cancelPage = function () {\n if ($scope.recipeData.mainRecipe.id || isValidRecipe(true)) {\n $modal({\n title: \"Are you sure you want to leave this page? All changes will be lost\",\n templateUrl: \"app/components/modal/templates/confirm.html\",\n customClass: \"user-create-modal\",\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n $scope.$hide();\n if ($scope.recipeData.mainRecipe.id) {\n $state.go(\"main.view-recipe\", { recipeId: $scope.recipeData.mainRecipe.id });\n } else {\n $state.go(\"main.catalogue\");\n }\n };\n },\n });\n } else {\n $state.go(\"main.catalogue\");\n }\n };\n\n if ($scope.recipe) {\n $scope.editRecipe = true;\n $scope.helper.transformRecipeData($scope.recipeData, $scope.recipe, $scope.options, $scope.changeAmount);\n $scope.checkSubmit();\n if ($scope.recipe.photo) {\n $scope.imgPreview = $scope.recipe.photo;\n }\n }\n },\n };\n }).constant(\"NUTRITION_MAPPING\", [\n { key: \"Calories\", value: \"calories\" },\n { key: \"Total Fat\", value: \"total_fat\", unit: \"g\" },\n { key: \"Saturated Fat\", value: \"saturated_fat\", unit: \"g\" },\n { key: \"Cholesterol\", value: \"cholesterol\", unit: \"mg\" },\n { key: \"Sodium\", value: \"sodium\", unit: \"mg \" },\n { key: \"Total Carbohydrates\", value: \"carbohydrate\", unit: \"g\" },\n { key: \"Dietary Fiber\", value: \"dietary_fiber\", unit: \"g\" },\n { key: \"Total Sugars\", value: \"sugar\", unit: \"g\" },\n { key: \"Protein\", value: \"protein\", unit: \"g\" },\n]);\n\nangular.module(\"components.catalogue.create-recipe.create-recipe\").factory(\"recipeHelper\", function (NUTRITION_MAPPING) {\n function checkUnits(units) {\n var customUnits = [];\n var ingredientUnits = [];\n var defaultUnits = [\"tsp\", \"tbsp\", \"oz\", \"cups\", \"gallon\", \"pint\", \"ml\", \"g\", \"pound\", \"clove\",\n \"can\", \"serving\", \"each\", \"slice\", \"head\", \"bunch\", \"small\", \"medium\", \"large\", \"whole\", \"lbs\"];\n\n units.forEach(function (unit) {\n if (defaultUnits.indexOf(unit.name) === -1) {\n // if unit is not default\n customUnits.push({ name: unit.name, id: unit.id, nutritions: unit });\n } else {\n ingredientUnits.push({ name: unit.name, id: unit.id, nutritions: unit });\n }\n });\n\n if (customUnits.length) {\n ingredientUnits.push({ name: \"─────────────────\", id: 0, nutritions: null, separator: true });\n ingredientUnits = ingredientUnits.concat(customUnits);\n }\n\n return ingredientUnits;\n }\n\n function transformIngredient(recipe, index) {\n if (recipe.ingredients[index].is_custom) {\n var id = recipe.ingredients[index].unit.name === 'cup' ? 'cups' : recipe.ingredients[index].unit.name;\n\n recipe.ingredients[index].unit = { name: id, id: id, value: recipe.ingredients[index].unit.name };\n recipe.ingredients[index].units = null;\n } else {\n recipe.ingredients[index].nid = recipe.ingredients[index].id;\n recipe.ingredients[index].units = recipe.ingredients[index].units.map(function (unit) {\n return { name: unit.name, id: unit.id, nutritions: unit };\n });\n recipe.ingredients[index].units = checkUnits(recipe.ingredients[index].units);\n // recipe.ingredients[index].defaultAmount = recipe.ingredients[index].amount;\n recipe.ingredients[index].unit = recipe.ingredients[index].units.find(function (unit) {\n return recipe.ingredients[index].unit.id === unit.id;\n });\n }\n\n return recipe;\n }\n\n function changeAmount(recipe, $index, editRecipe) {\n $index = $index || 0;\n\n recipe.transformedIngredients[$index] = recipe.transformedIngredients[$index] || { nutritionSum: {} };\n recipe.transformedIngredients[$index].nutritionSum = {};\n recipe.nutritionsSum = {};\n\n recipe.transformedIngredients.forEach(function (ingredient) {\n NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.nutritionsSum[nutrition.value] = calculateNutrition(recipe.nutritionsSum, ingredient, nutrition.value, 0, editRecipe);\n });\n });\n\n NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.transformedIngredients[$index].nutritionSum[nutrition.value] =\n calculateNutrition(recipe.transformedIngredients[$index].nutritionSum, recipe.transformedIngredients[$index], nutrition.value, 1, editRecipe);\n });\n\n return recipe;\n }\n\n function calculateNutrition(sum, item, prop, replaceAmount, editRecipe) {\n var value = sum[prop];\n var nutritionValue = item[prop];\n var itemDefaultAmount = (item.defaultAmount || 1);\n\n if (value === undefined) {\n value = 0;\n }\n if (editRecipe) {\n value += angular.isNumber(nutritionValue - 0) ? (nutritionValue / itemDefaultAmount * (item.amount || 0)) : 0;\n } else {\n value += angular.isNumber(nutritionValue - 0) ? nutritionValue * (item.amount || replaceAmount) : 0;\n }\n return value;\n }\n\n return {\n transformRecipeData: function (recipeData, recipe, options, changeAmount) {\n recipeData.id = recipe.id;\n recipeData.mainRecipe = recipe;\n recipeData.recipes = recipe.sub_recipes;\n\n recipeData.mainRecipe.categories.forEach(function (category) {\n options.category_groups.forEach(function (categoryGroup) {\n categoryGroup.categories.forEach(function (option) {\n if (category.id === option.id) {\n option.isChecked = true;\n }\n });\n });\n });\n\n recipeData.mainRecipe.allergens.forEach(function (allergen) {\n options.allergens.forEach(function (option) {\n if (allergen.id === option.id) {\n option.isChecked = true;\n }\n });\n });\n\n recipeData.mainRecipe.dietaries.forEach(function (dietary) {\n options.dietary.forEach(function (option) {\n if (dietary.id === option.id) {\n option.isChecked = true;\n }\n });\n });\n\n recipeData.recipes.forEach(function (recipe) {\n if (!recipe.methods.length) {\n recipe.methods.push({ desc: \"\" });\n }\n recipe.ingredients.forEach(function (ing, index) {\n NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.ingredients[index][nutrition.value] = recipe.ingredients[index].nutrition_facts[nutrition.value] / recipe.ingredients[index].amount;\n });\n\n recipe = transformIngredient(recipe, index);\n changeAmount(recipe, index);\n });\n });\n\n recipeData.mainRecipe.portion.unit = recipeData.unit.availableOptions.find(function (option) {\n return recipe.portion.unit === option.id;\n });\n },\n\n calculateNutritionSum: function (sum, item, prop, replaceAmount, editRecipe) {\n return calculateNutrition(sum, item, prop, replaceAmount, editRecipe);\n },\n\n transformIngredients: function (recipe) {\n recipe.transformedIngredients = [];\n recipe.ingredients.forEach(function (ingredient, index) {\n NUTRITION_MAPPING.forEach(function (nutrition) {\n recipe.ingredients[index][nutrition.value] = recipe.ingredients[index].nutrition_facts[nutrition.value];\n });\n\n recipe = transformIngredient(recipe, index);\n recipe.transformedIngredients[index] = ingredient;\n recipe = changeAmount(recipe, index, true);\n });\n\n return recipe;\n },\n\n addRecipeIngredient: function (ingredients) {\n ingredients.push({\n id: 0,\n name: \"\",\n total_fat: \"-\",\n carbohydrate: \"-\",\n protein: \"-\",\n calories: \"-\",\n sugar: \"-\",\n amount: 1,\n unit: { id: \"lbs\", name: \"lbs\", value: \"lbs\" },\n });\n },\n\n checkIngredient: function (ingredient, name, recipe, $index) {\n if (recipe.ingredients[$index].name !== name) {\n recipe.ingredients[$index] = {\n name: name,\n total_fat: undefined,\n carbohydrate: undefined,\n protein: undefined,\n calories: undefined,\n sugar: undefined,\n amount: 1,\n unit: { id: \"lbs\", name: \"lbs\", value: \"lbs\" },\n };\n }\n },\n\n addRecipe: function (array) {\n array.push({\n subrecipe: \"Sub Recipe\",\n name: \"\",\n ingredients: [\n {\n name: \"\",\n fat: \"\",\n carbs: \"\",\n prot: \"\",\n kcal: \"\",\n sugar: \"\",\n amount: 1,\n unit: { id: \"lbs\", name: \"lbs\", value: \"lbs\" },\n nutritionsSum: {},\n },\n ],\n methods: [\n {\n desc: \"\",\n },\n ],\n nutritionsSum: {},\n });\n },\n\n addRecipeMethod: function (methods, index) {\n methods.splice(index + 1, 0, {\n desc: \"\",\n });\n // methods.push({\n // desc: \"\",\n // });\n },\n\n checkUnits: function (units) {\n return checkUnits(units);\n },\n };\n})\n .constant(\"recipeData\", {\n unit: {\n availableOptions: [\n { id: \"oz\", name: \"oz\", value: \"oz\" },\n { id: \"cups\", name: \"Cups\", value: \"cup\" },\n { id: \"qty\", name: \"Quantity\", value: \"qty\" },\n ],\n selectedOption: { id: \"oz\", name: \"oz\", value: \"oz\" },\n },\n ingredientUnits: {\n availableOptions: [\n { id: \"lbs\", name: \"lbs\", value: \"lbs\" },\n { id: \"tsp\", name: \"tsp\", value: \"tsp\" },\n { id: \"tbsp\", name: \"tbsp\", value: \"tbsp\" },\n { id: \"oz\", name: \"oz\", value: \"oz\" },\n { id: \"cups\", name: \"cups\", value: \"cup\" },\n { id: \"qty\", name: \"qty\", value: \"qty\" },\n ],\n selectedOption: { id: \"lbs\", name: \"lbs\", value: \"lbs\" },\n },\n mainRecipe: {\n title: \"\",\n categories: [],\n allergens: [],\n cuisine: [],\n dietaries: [],\n serving: 1,\n portion: {\n size: 1,\n unit: { id: \"oz\", name: \"oz\", value: \"oz\" },\n },\n },\n recipes: [\n {\n title: \"Main Recipe\",\n ingredients: [\n {\n name: \"\",\n total_fat: \"-\",\n carbohydrate: \"-\",\n protein: \"-\",\n calories: \"-\",\n amount: 0,\n unit: { id: \"lbs\", name: \"lbs\", value: \"lbs\" },\n },\n ],\n methods: [\n {\n desc: \"\",\n },\n ],\n nutritionsSum: {},\n },\n ],\n });\n\nangular.module('components.catalogue.catalogue-pagination.catalogue-pagination', [])\n .directive('cataloguePagination', function () {\n function getPagesArray(totalPages) {\n var pagesArray = [];\n\n for (var i = 0; i <= totalPages; i++) {\n pagesArray.push(i);\n }\n\n return chunk(pagesArray, 10);\n }\n\n function chunk(array, chunkSize) {\n return [].concat.apply([],\n array.map(function (elem, i) {\n return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];\n })\n );\n }\n\n return {\n restrict: 'E',\n scope: {\n data: '=',\n onSetPage: '=?',\n },\n replace: true,\n templateUrl: 'app/components/catalogue/catalogue-pagination/catalogue-pagination.html',\n link: {\n pre: function($scope) {\n $scope.currentPage = 0;\n $scope.onSetPage = $scope.onSetPage || angular.noop;\n $scope.currentChunk = 0;\n\n $scope.setPage = function (page, $event) {\n $event.preventDefault();\n $event.stopPropagation();\n\n $scope.currentPage = page;\n $scope.onSetPage($scope.currentPage * $scope.data.per_page);\n };\n\n $scope.setChunk = function (index, $event) {\n $event.preventDefault();\n $scope.currentChunk = $scope.currentChunk + index;\n };\n\n $scope.$watch('data', function (data) {\n if (data) {\n $scope.pagination = data;\n $scope.pages = getPagesArray(Math.floor((data.total - 1) / data.per_page));\n if (data.current_page === 0) {\n $scope.currentPage = 0;\n } else {\n $scope.currentPage = Math.ceil(data.current_page / data.per_page);\n $scope.currentChunk = Math.floor(($scope.currentPage - 1) / 10);\n }\n }\n });\n },\n },\n };\n });\n\nangular.module('components.user-login.user-login', [\n 'components.data-access.user-service',\n 'components.alert.alert'\n]).directive('userLogin', function (userService, $alert, $state) {\n return {\n scope: {\n tplType: '@'\n },\n templateUrl: 'app/components/user-login/user-login.html',\n link: function ($scope) {\n $scope.tplType = $scope.tplType || 'login'\n\n $scope.user = {\n email: userService.getUser('email'),\n isPasswordReset: this.isPasswordReset || userService.getUser('isPasswordReset')\n }\n\n if ( $scope.tplType === 'change-password' && !!userService.getResetToken() ) {\n userService.checkResetToken().then(function () {}, function () {\n $alert({\n content: 'This link is expired or has already been used.
Please provide your Guest Services login email and request a new link',\n type: 'info',\n show: true,\n container: '.password-reset-alert-wrapper'\n })\n\n $state.go('forgot-password')\n })\n }\n\n $scope.login = function ($event) {\n if ( $scope.loginForm.$valid && !$scope.disableSubmit ) {\n $scope.submit('login', $scope.user, $event)\n }\n }\n\n $scope.submit = function (action, data, $event) {\n if ( $event ) {\n $event.preventDefault()\n $event.stopPropagation()\n }\n\n $scope.disableSubmit = true\n userService[action](data).then(function () {\n $scope.isUserExist = true\n $scope.disableSubmit = false\n if ( action === 'resetPassword' ) {\n return $alert({\n content: 'Email with a link to restore your password has been sent to ' + $scope.user.email + ' address',\n type: 'success',\n show: true,\n container: '.password-reset-alert-wrapper'\n })\n }\n }, function () {\n $scope.isUserExist = false\n $scope.disableSubmit = false\n })\n }\n\n $scope.$watch('user.email', function (email) {\n if ( email ) {\n userService.setUser({ email: email })\n }\n })\n }\n }\n}).directive('equals', function () {\n return {\n require: 'ngModel',\n link: function ($scope, $element, $attrs, $ctrl) {\n $ctrl.$validators.equals = function (modelValue, viewValue) {\n return $ctrl.$$parentForm[$attrs.equals].$viewValue === viewValue\n }\n }\n }\n}).directive('onEnterPress', function () {\n return function ($scope, $element, $attrs) {\n $element.bind('keyup', function (e) {\n if ( e.which === 13 ) {\n $scope.$apply(function () {\n $scope.$eval($attrs.onEnterPress)\n })\n }\n })\n }\n})\n\nangular.module('components.user-list-table.user-list-table',\n ['components.tooltip.tooltip', 'components.pagination.pagination', 'components.data-access.title-service',])\n .directive('userListTable', function($modal, $alert, userListApiService, titleService) {\n return {\n restrict: 'E',\n scope: {\n users: '=',\n mapping: '=?'\n },\n templateUrl: 'app/components/user-list-table/user-list-table.html',\n link: function($scope) {\n $scope.ACCEPTED_USER_ROLES = [\n {name: 'Main Chef', value: 'Main_Chef', id: 2},\n {name: 'Local Chef', value: 'Local_Chef', id: 3},\n {name: 'Admin', value: 'Admin', id: 1}\n ];\n titleService.setTitle('Users');\n\n $scope.openUserCreateModal = function() {\n return $modal({\n title: 'Create New User',\n templateUrl: 'app/components/modal/templates/user-create.tpl.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function($scope) {\n $scope.newUser = {\n role_id: $scope.ACCEPTED_USER_ROLES[1]\n };\n\n $scope.createUser = function($event) {\n $event.preventDefault();\n $event.stopPropagation();\n var reqData = angular.copy($scope.newUser);\n\n userListApiService.createUser(reqData).then(function(data) {\n $scope.users.push(data);\n $scope.setPage($scope.from, $scope.to);\n $scope.$hide();\n $alert({\n content: 'New user was created',\n type: 'success',\n show: true,\n container: '.alert-container'\n });\n }, function(res) {\n if(res.status === 409) {\n $scope.emailAlreadyTaken = true;\n }\n })\n };\n }\n });\n };\n\n $scope.openUserEditModal = function(user) {\n return $modal({\n title: 'Edit User',\n templateUrl: 'app/components/modal/templates/user-edit.tpl.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function($scope) {\n\n var role = $scope.ACCEPTED_USER_ROLES.find(function(role) {\n return user['role_id'] === role.id;\n });\n\n $scope.user = {\n 'first_name': user['first_name'],\n 'last_name': user['last_name'],\n role_id: role,\n id: user.id\n };\n\n $scope.email = user.email;\n\n $scope.editUser = function($event) {\n $event.preventDefault();\n $event.stopPropagation();\n\n var reqData = angular.copy($scope.user);\n\n userListApiService.updateUser(reqData).then(function(data) {\n\n var index = $scope.users.findIndex(function(user) {\n return user.id === data.id;\n });\n\n var filteredIndex = $scope.filteredUsers.findIndex(function(user) {\n return user.id === data.id;\n });\n\n $scope.users[index] = data;\n $scope.filteredUsers[filteredIndex] = data;\n\n $scope.$hide();\n $alert({\n content: 'User ' + data.fullName + ' was changed successfully',\n type: 'success',\n show: true,\n container: '.alert-container'\n });\n })\n };\n }\n });\n };\n\n $scope.openUserRemoveModal = function(id) {\n return $modal({\n title: 'Are you sure want to delete this user?',\n templateUrl: 'app/components/modal/templates/user-remove.tpl.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function($scope) {\n $scope.removeUser = function() {\n userListApiService.deleteUser(id).then(function() {\n var index = $scope.users.findIndex(function(user) {\n return user.id === id;\n });\n var deletedUser = $scope.users[index].fullName;\n $scope.users.splice(index, 1);\n $scope.setPage($scope.from, $scope.to);\n $scope.$hide();\n $alert({\n content: 'User ' + deletedUser + ' was deleted',\n type: 'info',\n show: true,\n container: '.alert-container'\n });\n });\n };\n }\n });\n };\n\n $scope.setPage = function(from, to) {\n $scope.from = from || 0;\n $scope.to = to || 50;\n $scope.filteredUsers = $scope.users.slice($scope.from, $scope.to);\n };\n\n $scope.setPage($scope.from, $scope.to);\n }\n }\n });\n\nangular.module('components.tooltip.tooltip', ['components.tooltip.dimensions-helper'])\n .provider('$tooltip', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n templateUrl: 'app/components/tooltip/tooltip.html',\n template: '',\n titleTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n mouseDownPreventDefault: true,\n mouseDownStopPropagation: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function ($window, $rootScope, $bsCompiler, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n var $body = angular.element($window.document);\n\n function TooltipFactory (element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n var promise = $tooltip.$promise = $bsCompiler.compile(options);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n var nodeName = element[0].nodeName.toLowerCase();\n if (options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // Store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if (options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function (isEnabled) {\n scope.$$postDigest(function () {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function () {\n scope.$$postDigest(function () {\n $tooltip.hide();\n });\n };\n scope.$show = function () {\n scope.$$postDigest(function () {\n $tooltip.show();\n });\n };\n scope.$toggle = function () {\n scope.$$postDigest(function () {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout;\n var hoverState;\n\n // Fetch, compile then initialize tooltip\n var compileData;\n var tipElement;\n var tipContainer;\n var tipScope;\n promise.then(function (data) {\n compileData = data;\n $tooltip.init();\n });\n\n $tooltip.init = function () {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if (options.container === 'self') {\n tipContainer = element;\n } else if (angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if (options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if (options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if (options.show) {\n scope.$$postDigest(function () {\n if (options.trigger === 'focus') {\n element[0].focus();\n } else {\n $tooltip.show();\n }\n });\n }\n\n };\n\n $tooltip.destroy = function () {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function () {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function () {\n if (hoverState === 'in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function () {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n options.onBeforeShow($tooltip);\n }\n var parent;\n var after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if (tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = compileData.link(tipScope, function (clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if (options.animation) tipElement.addClass(options.animation);\n // Options: type\n if (options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if (options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n if (after) {\n after.after(tipElement);\n } else {\n parent.prepend(tipElement);\n }\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.enter(tipElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(tipElement, parent, after).then(enterAnimateCallback);\n }\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if (tipElement) tipElement.css({visibility: 'visible'});\n\n // Bind events\n if (options.keyboard) {\n if (options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n });\n\n if (options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback () {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n options.onShow($tooltip);\n }\n }\n\n $tooltip.leave = function () {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function (blur) {\n\n if (!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n options.onBeforeHide($tooltip);\n }\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.leave(tipElement, leaveAnimateCallback);\n } else {\n $animate.leave(tipElement).then(leaveAnimateCallback);\n }\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if (options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if (options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback () {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n options.onHide($tooltip);\n }\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if (_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function (evt) {\n if (evt) { evt.preventDefault(); }\n if ($tooltip.$isShown) {\n $tooltip.leave();\n } else {\n $tooltip.enter();\n }\n };\n\n $tooltip.focus = function () {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function (isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function (viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function () {\n if (!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement;\n var autoToken = /\\s?auto?\\s?/i;\n var autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition();\n var tipWidth = tipElement.prop('offsetWidth');\n var tipHeight = tipElement.prop('offsetHeight');\n\n // Refresh viewport position\n $tooltip.$viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var viewportPosition = getPosition($tooltip.$viewport);\n\n if (/bottom/.test(originalPlacement) && elementPosition.bottom + tipHeight > viewportPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (/top/.test(originalPlacement) && elementPosition.top - tipHeight < viewportPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n if (/left/.test(originalPlacement) && elementPosition.left - tipWidth < viewportPosition.left) {\n placement = placement.replace('left', 'right');\n } else if (/right/.test(originalPlacement) && elementPosition.right + tipWidth > viewportPosition.width) {\n placement = placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function (evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function (evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function (evt) {\n if (options.mouseDownPreventDefault) { evt.preventDefault(); }\n if (options.mouseDownStopPropagation) { evt.stopPropagation(); }\n // Some browsers do not auto-focus buttons (eg. Safari)\n if ($tooltip.$isShown) {\n element[0].blur();\n } else {\n element[0].focus();\n }\n };\n\n // bind/unbind events\n function bindTriggerEvents () {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function (trigger) {\n if (trigger === 'click' || trigger === 'contextmenu') {\n element.on(trigger, $tooltip.toggle);\n } else if (trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n if (nodeName === 'button' && trigger !== 'hover') {\n element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n });\n }\n\n function unbindTriggerEvents () {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if (trigger === 'click' || trigger === 'contextmenu') {\n element.off(trigger, $tooltip.toggle);\n } else if (trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n if (nodeName === 'button' && trigger !== 'hover') {\n element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n }\n\n function bindKeyboardEvents () {\n if (options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents () {\n if (options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents () {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function () {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents () {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation (event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition ($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0];\n var isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n /* eslint-disable guard-for-in */\n for (var p in elRect) { // eslint-disable-line\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n /* eslint-enable guard-for-in */\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, {width: elRect.right - elRect.left, height: elRect.bottom - elRect.top});\n }\n var elOffset = isBody ? {top: 0, left: 0} : dimensions.offset(el);\n var scroll = {scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0};\n var outerDims = isBody ? {width: document.documentElement.clientWidth, height: $window.innerHeight} : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset (placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if (!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if (split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n break;\n default:\n break;\n }\n } else if (split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight + position.height;\n break;\n case 'bottom':\n offset.top = position.top;\n break;\n default:\n break;\n }\n }\n\n return offset;\n }\n\n function applyPlacement (offset, placement) {\n var tip = tipElement[0];\n var width = tip.offsetWidth;\n var height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10);\n var marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth;\n var actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement);\n var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight;\n var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n // @source https://github.com/twbs/bootstrap/blob/v3.3.5/js/tooltip.js#L380\n function getViewportAdjustedDelta (placement, position, actualWidth, actualHeight) {\n var delta = {top: 0, left: 0};\n if (!$tooltip.$viewport) return delta;\n\n var viewportPadding = options.viewport && options.viewport.padding || 0;\n var viewportDimensions = getPosition($tooltip.$viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll;\n var bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding;\n var rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow (delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement () {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if ($tooltip.$isShown && tipElement !== null) {\n if (options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if (options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if (tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if (tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest (scope) {\n /* eslint-disable no-unused-expressions */\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n /* eslint-enable no-unused-expressions */\n }\n\n function findElement (query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function ($window, $location, $sce, $parse, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink (scope, element, attr, transclusion) {\n\n var tooltip;\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'titleTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function (key) {\n if (angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) {\n options[key] = false;\n }\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if (angular.isDefined(dataTarget)) {\n if (falseValueRegExp.test(dataTarget)) {\n options.target = false;\n } else {\n options.target = dataTarget;\n }\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')) {\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function (newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n if (angular.isDefined(oldValue)) {\n $$rAF(function () {\n if (tooltip) tooltip.$applyPlacement();\n });\n }\n }\n });\n\n attr.$observe('disabled', function (newValue) {\n if (newValue && tooltip.$isShown) {\n tooltip.hide();\n }\n });\n\n // Support scope as an object\n if (attr.bsTooltip) {\n scope.$watch(attr.bsTooltip, function (newValue, oldValue) {\n if (angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n if (angular.isDefined(oldValue)) {\n $$rAF(function () {\n if (tooltip) tooltip.$applyPlacement();\n });\n }\n }, true);\n }\n\n // Visibility binding support\n if (attr.bsShow) {\n scope.$watch(attr.bsShow, function (newValue, oldValue) {\n if (!tooltip || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n if (newValue === true) {\n tooltip.show();\n } else {\n tooltip.hide();\n }\n });\n }\n\n // Enabled binding support\n if (attr.bsEnabled) {\n scope.$watch(attr.bsEnabled, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if (!tooltip || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n if (newValue === false) {\n tooltip.setEnabled(false);\n } else {\n tooltip.setEnabled(true);\n }\n });\n }\n\n // Viewport support\n if (attr.viewport) {\n scope.$watch(attr.viewport, function (newValue) {\n if (!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n }\n\n // Initialize popover\n tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n\n'use strict';\n\nangular.module('components.tooltip.dimensions-helper', [])\n\n .factory('dimensions', function () {\n\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function (element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function (element, prop, extra) {\n var value;\n if (element.currentStyle) { // IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function (element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n\n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition;\n var curLeft;\n var curCSSTop;\n var curTop;\n var curOffset;\n var curCSSLeft;\n var calculatePosition;\n var position = fn.css(element, 'position');\n var curElem = angular.element(element);\n var props = {};\n\n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n\n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') &&\n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n\n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n\n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n\n if (options.top !== null) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if (options.left !== null) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function (element) {\n\n var offsetParentRect = {top: 0, left: 0};\n var offsetParentEl;\n var offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentEl\n offsetParentEl = offsetParentElement(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentEl, 'html')) {\n offsetParentRect = fn.offset(offsetParentEl);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentEl, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentEl, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n function offsetParentElement (element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if (nodeName(offsetParent, '#document')) return docElement.documentElement;\n while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n }\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function (element, outer) {\n var value = element.offsetHeight;\n if (outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function (element, outer) {\n var value = element.offsetWidth;\n if (outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n\nangular.module('components.popover.popover', ['components.tooltip.tooltip'])\n .provider('$popover', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n templateUrl: 'app/components/popover/popover.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function ($tooltip) {\n\n function PopoverFactory (element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if (options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function ($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink (scope, element, attr) {\n\n var popover;\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent', 'bsEnabled'], function (key) {\n if (angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if (angular.isDefined(dataTarget)) {\n if (falseValueRegExp.test(dataTarget)) {\n options.target = false;\n } else {\n options.target = dataTarget;\n }\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function (key) {\n if (attr[key]) {\n attr.$observe(key, function (newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n if (angular.isDefined(oldValue)) {\n requestAnimationFrame(function () {\n if (popover) popover.$applyPlacement();\n });\n }\n });\n }\n });\n\n // Support scope as an object\n if (attr.bsPopover) {\n scope.$watch(attr.bsPopover, function (newValue, oldValue) {\n if (angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n if (angular.isDefined(oldValue)) {\n requestAnimationFrame(function () {\n if (popover) popover.$applyPlacement();\n });\n }\n }, true);\n }\n\n // Visibility binding support\n if (attr.bsShow) {\n scope.$watch(attr.bsShow, function (newValue, oldValue) {\n if (!popover || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n if (newValue === true) {\n popover.show();\n } else {\n popover.hide();\n }\n });\n }\n\n // Enabled binding support\n if (attr.bsEnabled) {\n scope.$watch(attr.bsEnabled, function (newValue) {\n if (!popover || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(popover),?/i);\n if (newValue === false) {\n popover.setEnabled(false);\n } else {\n popover.setEnabled(true);\n }\n });\n }\n\n // Viewport support\n if (attr.viewport) {\n scope.$watch(attr.viewport, function (newValue) {\n if (!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n }\n\n // Initialize popover\n popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n\nangular.module('components.pagination.pagination', [])\n .directive('pagination', function() {\n function getPagesArray(totalPages) {\n var pagesArray = [];\n\n for(var i = 1; i <= totalPages + 1; i++) {\n pagesArray.push(i);\n }\n return chunk(pagesArray, 10);\n }\n\n function chunk(array, chunkSize) {\n return [].concat.apply([],\n array.map(function(elem,i) {\n return i % chunkSize ? [] : [array.slice(i,i+chunkSize)];\n })\n );\n }\n\n return {\n restrict: 'E',\n scope: {\n totalCount: '=',\n perPage: '=?',\n onSetPage: '='\n },\n replace: true,\n templateUrl: 'app/components/pagination/pagination.html',\n link: {\n pre: function($scope) {\n $scope.perPage = $scope.perPage || 50;\n $scope.currentPage = 0;\n $scope.onSetPage = $scope.onSetPage || angular.noop;\n $scope.currentChunk = 0;\n\n $scope.setPage = function(page, $event) {\n if($event) {\n $event && $event.preventDefault();\n $event.stopPropagation();\n }\n\n $scope.currentPage = page;\n $scope.onSetPage($scope.currentPage * $scope.perPage, ($scope.currentPage + 1) * $scope.perPage);\n };\n\n $scope.setChunk = function(index, $event) {\n $event.preventDefault();\n $scope.currentChunk = $scope.currentChunk + index;\n };\n\n $scope.$watch('totalCount', function() {\n var totalPages = $scope.totalCount / $scope.perPage;\n\n $scope.pages = getPagesArray(totalPages);\n if($scope.currentPage + 1 > totalPages) {\n $scope.setPage(0);\n }\n });\n }\n }\n }\n });\n\nangular.module('guestServices', [\n 'ngResource',\n 'ui.router',\n 'permission',\n 'permission.ui',\n 'ngFileUpload',\n 'components.data-access.api.user-api-service',\n 'components.data-access.api.user-list-service',\n 'components.data-access.user-service',\n 'components.user-login.user-login',\n 'components.catalogue.catalogue',\n 'components.menu.menu',\n 'components.modal.modal',\n 'components.main-menu.main-menu',\n 'components.user-list-table.user-list-table',\n 'components.logout.logout',\n 'angucomplete',\n 'components.data-access.title-service',\n]);\n\nangular.module('guestServices')\n .directive('onClickOutside', function($document) {\n return {\n restrict: 'A',\n link: function($scope, $element, $attrs) {\n function listener(e) {\n if(!$element[0].contains(e.target)) {\n $scope.$eval($attrs.onClickOutside);\n $scope.$applyAsync();\n }\n }\n $document.on('click', listener);\n\n $scope.$on('$destroy', function() {\n $document.off('click', listener);\n });\n }\n };\n}).directive('onKeyup', function() {\n return function(scope, elm, attrs) {\n function applyKeyup() {\n scope.$apply(attrs.onKeyup);\n }\n\n var allowedKeys = attrs.keys.split(',');\n elm.bind('keyup', function(evt) {\n angular.forEach(allowedKeys, function(key) {\n if ((key - 0) === evt.which) {\n applyKeyup();\n }\n });\n });\n };\n});\n\nangular.module('components.nutritions-table.nutritions-table', [])\n .directive('nutritionsTable', function($document, $window) {\n return {\n restrict: 'E',\n scope: {\n mapping: '=?',\n data: '='\n },\n replace: true,\n templateUrl: 'app/components/nutritions-table/nutritions-table.html',\n link: function($scope) {\n var body = angular.element($document[0].body);\n\n $scope.print = function() {\n body.removeClass('nutritions-table-print');\n body.addClass('nutritions-table-print');\n $window.print();\n body.removeClass('nutritions-table-print');\n };\n }\n }\n });\n\n\nangular.module('components.modal.modal', ['ngAnimate'])\n\n .provider('$modal', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n customClass: '',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n templateUrl: 'app/components/modal/modal.html',\n template: '',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true,\n size: null,\n zIndex: null\n };\n\n this.$get = function ($window, $rootScope, $bsCompiler, $animate, $timeout, $sce) {\n\n var forEach = angular.forEach;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n\n var backdropCount = 0;\n var dialogBaseZindex = 1080;\n var backdropBaseZindex = 1040;\n\n var validSizes = {\n lg: 'modal-lg',\n sm: 'modal-sm'\n };\n\n function ModalFactory (config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n var promise = $modal.$promise = $bsCompiler.compile(options);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n if (!options.element && !options.container) {\n options.container = 'body';\n }\n\n if (options.zIndex) {\n dialogBaseZindex = parseInt(options.zIndex, 10);\n backdropBaseZindex = dialogBaseZindex - 10;\n }\n\n // Store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function (key) {\n if (options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function () {\n scope.$$postDigest(function () {\n $modal.hide();\n });\n };\n scope.$show = function () {\n scope.$$postDigest(function () {\n $modal.show();\n });\n };\n scope.$toggle = function () {\n scope.$$postDigest(function () {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Fetch, compile then initialize modal\n var compileData;\n var modalElement;\n var modalScope;\n var backdropElement = angular.element('
');\n backdropElement.css({position: 'fixed', top: '0px', left: '0px', bottom: '0px', right: '0px'});\n promise.then(function (data) {\n compileData = data;\n $modal.init();\n });\n\n $modal.init = function () {\n\n // Options: show\n if (options.show) {\n scope.$$postDigest(function () {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function () {\n\n // Remove element\n destroyModalElement();\n\n // remove backdrop element\n if (backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n };\n\n $modal.show = function () {\n if ($modal.$isShown) return;\n\n var parent;\n var after;\n if (angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // destroy any existing modal elements\n if (modalElement) destroyModalElement();\n\n // create a new scope, so we can destroy it and all child scopes\n // when destroying the modal element\n modalScope = $modal.$scope.$new();\n // Fetch a cloned element linked from template (noop callback is required)\n modalElement = $modal.$element = compileData.link(modalScope, function (clonedElement, scope) {});\n\n if (options.backdrop) {\n // set z-index\n modalElement.css({'z-index': dialogBaseZindex + (backdropCount * 20)});\n backdropElement.css({'z-index': backdropBaseZindex + (backdropCount * 20)});\n\n // increment number of backdrops\n backdropCount++;\n }\n\n if (scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n options.onBeforeShow($modal);\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: customClass\n if (options.customClass) {\n modalElement.addClass(options.customClass);\n }\n\n // Options: size\n if (options.size && validSizes[options.size]) {\n angular.element(findElement('.modal-dialog', modalElement[0])).addClass(validSizes[options.size]);\n }\n\n // Options: animation\n if (options.animation) {\n if (options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if (options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.enter(modalElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(modalElement, parent, after).then(enterAnimateCallback);\n }\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function () {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if (options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n bindBackdropEvents();\n bindKeyboardEvents();\n };\n\n function enterAnimateCallback () {\n scope.$emit(options.prefixEvent + '.show', $modal);\n if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n options.onShow($modal);\n }\n }\n\n $modal.hide = function () {\n if (!$modal.$isShown) return;\n\n if (scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n options.onBeforeHide($modal);\n }\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.leave(modalElement, leaveAnimateCallback);\n } else {\n $animate.leave(modalElement).then(leaveAnimateCallback);\n }\n\n if (options.backdrop) {\n // decrement number of backdrops\n backdropCount--;\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n unbindBackdropEvents();\n unbindKeyboardEvents();\n };\n\n function leaveAnimateCallback () {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n options.onHide($modal);\n }\n if (findElement('.modal').length <= 0) {\n bodyElement.removeClass(options.prefixClass + '-open');\n }\n if (options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function () {\n if ($modal.$isShown) {\n $modal.hide();\n } else {\n $modal.show();\n }\n };\n\n $modal.focus = function () {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function (evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n function bindBackdropEvents () {\n if (options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n }\n\n function unbindBackdropEvents () {\n if (options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n }\n\n function bindKeyboardEvents () {\n if (options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n }\n\n function unbindKeyboardEvents () {\n if (options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n }\n\n // Private helpers\n\n function hideOnBackdropClick (evt) {\n if (evt.target !== evt.currentTarget) return;\n if (options.backdrop === 'static') {\n $modal.focus();\n } else {\n $modal.hide();\n }\n }\n\n function preventEventDefault (evt) {\n evt.preventDefault();\n }\n\n function destroyModalElement () {\n if ($modal.$isShown && modalElement !== null) {\n // un-bind events\n unbindBackdropEvents();\n unbindKeyboardEvents();\n }\n\n if (modalScope) {\n modalScope.$destroy();\n modalScope = null;\n }\n\n if (modalElement) {\n modalElement.remove();\n modalElement = $modal.$element = null;\n }\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest (scope) {\n /* eslint-disable no-unused-expressions */\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n /* eslint-enable no-unused-expressions */\n }\n\n function findElement (query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function ($window, $sce, $parse, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink (scope, element, attr) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'backdropAnimation', 'id', 'prefixEvent', 'prefixClass', 'customClass', 'modalClass', 'size', 'zIndex'], function (key) {\n if (angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Options: alias modalClass to customClass\n if (options.modalClass) {\n options.customClass = options.modalClass;\n }\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function (key) {\n if (attr[key]) {\n attr.$observe(key, function (newValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n }\n });\n\n // Support scope as an object\n if (attr.bsModal) {\n scope.$watch(attr.bsModal, function (newValue) {\n if (angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n }\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n\nangular.module('components.modal.modal')\n .service('$bsCompiler', bsCompilerService);\n\nfunction bsCompilerService ($q, $http, $injector, $compile, $controller, $templateCache, $log) {\n this.compile = function (options) {\n\n if (options.template && /\\.html$/.test(options.template)) {\n $log.warn('Deprecated use of `template` option to pass a file. Please use the `templateUrl` option instead.');\n options.templateUrl = options.template;\n options.template = '';\n }\n\n var templateUrl = options.templateUrl;\n var template = options.template || '';\n var controller = options.controller;\n var controllerAs = options.controllerAs;\n var resolve = angular.copy(options.resolve || {});\n var locals = angular.copy(options.locals || {});\n var transformTemplate = options.transformTemplate || angular.identity;\n var bindToController = options.bindToController;\n\n // Take resolve values and invoke them.\n // Resolves can either be a string (value: 'MyRegisteredAngularConst'),\n // or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {})\n angular.forEach(resolve, function (value, key) {\n if (angular.isString(value)) {\n resolve[key] = $injector.get(value);\n } else {\n resolve[key] = $injector.invoke(value);\n }\n });\n // Add the locals, which are just straight values to inject\n // eg locals: { three: 3 }, will inject three into the controller\n angular.extend(resolve, locals);\n\n if (template) {\n resolve.$template = $q.when(template);\n } else if (templateUrl) {\n resolve.$template = fetchTemplate(templateUrl);\n } else {\n throw new Error('Missing `template` / `templateUrl` option.');\n }\n\n if (options.titleTemplate) {\n resolve.$template = $q.all([resolve.$template, fetchTemplate(options.titleTemplate)])\n .then(function (templates) {\n var templateEl = angular.element(templates[0]);\n findElement('[ng-bind=\"title\"]', templateEl[0])\n .removeAttr('ng-bind')\n .html(templates[1]);\n return templateEl[0].outerHTML;\n });\n }\n\n if (options.contentTemplate) {\n // TODO(mgcrea): deprecate?\n resolve.$template = $q.all([resolve.$template, fetchTemplate(options.contentTemplate)])\n .then(function (templates) {\n var templateEl = angular.element(templates[0]);\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0])\n .removeAttr('ng-bind')\n .html(templates[1]);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if (!options.templateUrl) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n }\n\n // Wait for all the resolves to finish if they are promises\n return $q.all(resolve).then(function (locals) {\n\n var template = transformTemplate(locals.$template);\n if (options.html) {\n template = template.replace(/ng-bind=\"/ig, 'ng-bind-html=\"');\n }\n // var element = options.element || angular.element('
').html(template.trim()).contents();\n var element = angular.element('
').html(template.trim()).contents();\n var linkFn = $compile(element);\n\n // Return a linking function that can be used later when the element is ready\n return {\n locals: locals,\n element: element,\n link: function link (scope) {\n locals.$scope = scope;\n\n // Instantiate controller if it exists, because we have scope\n if (controller) {\n var invokeCtrl = $controller(controller, locals, true);\n if (bindToController) {\n angular.extend(invokeCtrl.instance, locals);\n }\n // Support angular@~1.2 invokeCtrl\n var ctrl = angular.isObject(invokeCtrl) ? invokeCtrl : invokeCtrl();\n // See angular-route source for this logic\n element.data('$ngControllerController', ctrl);\n element.children().data('$ngControllerController', ctrl);\n\n if (controllerAs) {\n scope[controllerAs] = ctrl;\n }\n }\n\n return linkFn.apply(null, arguments);\n }\n };\n });\n\n };\n\n function findElement (query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate (template) {\n if (fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache})\n .then(function (res) {\n return res.data;\n }));\n }\n\n}\n\nangular.module('components.menu.menu',\n ['components.create-menu.create-menu',\n 'components.create-menu-helper.create-menu-helper',\n 'components.popover.popover',\n 'components.data-access.title-service',\n 'ngFileSaver',\n 'ngStorage'])\n .directive('menu',\n function (\n createMenuHelper, moment, menuApiService, titleService,\n $window, $filter, $modal, FileSaver, Blob, $localStorage,\n userService) {\n return {\n restrict: 'E',\n scope: {\n startDate: '=',\n },\n replace: true,\n templateUrl: 'app/components/menu/menu.html',\n link: function ($scope) {\n var SHORT_DAYS = createMenuHelper.getShortDays();\n titleService.setTitle('Menu');\n\n if ($scope.startDate) {\n $localStorage.fromDate = moment($scope.startDate).format('YYYY-MM-DD');\n } else if (typeof $localStorage.fromDate === 'undefined' || $localStorage.fromDate === null) {\n // set Monday only\n $localStorage.fromDate = moment().day(1).format('YYYY-MM-DD');\n }\n\n $scope.tabs = SHORT_DAYS.map(function (day) {\n return { name: day.toLowerCase(), isSelected: false };\n });\n\n $scope.tabs[0].isSelected = true;\n $scope.selectedTab = $scope.tabs[0];\n\n $scope.selectTab = function (selectedTab) {\n $scope.tabs.find(function (tab) {\n return tab.isSelected;\n }).isSelected = false;\n\n selectedTab.isSelected = true;\n\n $scope.selectedTab = selectedTab;\n };\n\n $scope.selectMenu = function (menuItem, $event, clearMenu) {\n $event && $event.stopPropagation();\n if (clearMenu) {\n $scope.menuData = {};\n }\n\n if (menuItem) {\n $scope.menuList.map(function (item) {\n item.isSelected = false;\n return item;\n });\n\n menuItem.isSelected = true;\n\n return menuApiService.getMenu(menuItem.id).then(function (data) {\n $scope.menuData = data;\n });\n } else {\n return false;\n }\n };\n\n $scope.setDate = function (date) {\n if (date) {\n $scope.currentWeek = date;\n $localStorage.fromDate = moment(date).format('YYYY-MM-DD');\n } else if (typeof $localStorage.fromDate !== 'undefined' && $localStorage.fromDate !== null) {\n $scope.currentWeek = moment($localStorage.fromDate, 'YYYY-MM-DD')._d;\n } else {\n var weekMonday = moment().day(1);\n $scope.currentWeek = weekMonday._d;\n $localStorage.fromDate = weekMonday.format('YYYY-MM-DD');\n }\n\n menuApiService.getMenuList($localStorage.fromDate).then(function (data) {\n $scope.menuList = data;\n\n if ($scope.menuList[0]) {\n $scope.menuList[0].isSelected = true;\n menuApiService.getMenu($scope.menuList[0].id).then(function (data) {\n $scope.menuData = data;\n if ($scope.menuList.$resolved && !$scope.menuList.length) {\n $scope.menuData = {};\n }\n $localStorage.fromDate = moment($scope.menuData.start_date).format('YYYY-MM-DD');\n });\n } else {\n $scope.menuData = {};\n }\n });\n };\n\n $scope.setDate();\n\n $scope.print = function () {\n return $window.print();\n };\n\n $scope.openRemoveModal = function (menuId) {\n return $modal({\n title: 'Are you sure want to delete this menu?',\n templateUrl: 'app/components/modal/templates/confirm.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function () {\n menuApiService.deleteMenu(menuId).then(function () {\n var deletedIndex = $scope.menuList.findIndex(function (item) {\n return item.id === menuId;\n });\n\n $scope.menuList.splice(deletedIndex, 1);\n $scope.selectMenu($scope.menuList[0], null, true);\n $scope.$hide();\n });\n };\n },\n });\n };\n\n $scope.downloadMenuSheet = function (menuId) {\n $scope.disableDownload = true;\n return menuApiService.downloadMenuSheet(menuId).then(function (res) {\n $scope.disableDownload = false;\n // $window.location = $window.location.origin + '/' + res.data.path;\n // @todo PAS USE config variable, or built in variable for API HOST!\n $window.location = 'https://recipes-api.zurka.com' + '/' + res.data.path;\n }, function () {\n $scope.disableDownload = false;\n });\n };\n\n $scope.downloadMenuTemplate = function (menuId) {\n $scope.disableDownload = true;\n return menuApiService.downloadMenuTemplate(menuId).then(function (res) {\n $scope.disableDownload = false;\n // $window.location = $window.location.origin + '/' + res.data.path;\n // @todo PAS USE config variable, or built in variable for API HOST!\n $window.location = 'https://recipes-api.zurka.com' + '/' + res.data.path;\n }, function () {\n $scope.disableDownload = false;\n });\n };\n\n $scope.downloadMenuPDF = function (menuId) {\n $scope.disableDownload = true;\n return menuApiService.downloadMenuPDF(menuId).then(function (res) {\n $scope.disableDownload = false;\n return FileSaver.saveAs(new Blob([res.data], { type: 'application/pdf' }), $scope.menuData.title + '.pdf');\n }, function () {\n $scope.disableDownload = false;\n });\n };\n\n $scope.isMenuAuthor = function() {\n var currentUser = userService.getUser();\n\n if (currentUser.role === 'Admin') {\n return true;\n }\n\n return ($scope.menuData ? ($scope.menuData.author_chef_id === currentUser.id) : false);\n };\n },\n };\n }).filter('currencyCustom', function () {\n return function (value) {\n if (!value) return value;\n return value.indexOf('$') + 1 ? value : '$' + value;\n };\n});\n\nangular.module('components.max-length', [])\n .directive('inputMaxLength', function() {\n return {\n scope: {},\n require: '?ngModel',\n link: function($scope, $element, $attrs, ngModel) {\n $scope.maxLength = $attrs.inputMaxLength - 0;\n var val = '';\n\n $scope.$watch(function () {\n return ngModel.$modelValue;\n }, function(newValue) {\n if ((newValue && ((newValue + '').length > $scope.maxLength))) {\n val = (newValue + '').slice(0, $scope.maxLength);\n ngModel.$setViewValue(val);\n $element.val(val);\n }\n });\n }\n }\n }).directive('only', function () {\n return {\n require: 'ngModel',\n restrict: 'A',\n link: function (scope, element, attr, ctrl) {\n function inputInteger(val) {\n if (val) {\n val = val + '';\n var digits = val.replace(/[^0-9.]/g, '');\n\n if (digits.split('.').length > 1 || (val - 0) < attr.min) {\n digits = digits.substring(0, digits.length - 1);\n }\n\n if (digits !== val) {\n ctrl.$setViewValue(digits);\n ctrl.$render();\n }\n return parseFloat(digits);\n }\n return undefined;\n }\n\n function inputFloat(val) {\n if (val) {\n var digits = val.replace(/[^0-9.]/g, '');\n\n if (digits.split('.').length > 2) {\n digits = digits.substring(0, digits.length - 1);\n }\n\n if (digits !== val) {\n ctrl.$setViewValue(digits);\n ctrl.$render();\n }\n return parseFloat(digits);\n }\n return undefined;\n }\n\n function inputCurrency(val) {\n if (val) {\n var digits = val.replace(/[^0-9.|\\/$]/g, '');\n\n if (digits.split('.').length > 3 || digits.split('/').length > 2) {\n digits = digits.substring(0, digits.length - 1);\n }\n\n ctrl.$setViewValue('$' + digits);\n ctrl.$render();\n return '$' + digits;\n }\n return undefined;\n }\n\n if(attr.only === 'integer') {\n ctrl.$parsers.push(inputInteger);\n } else if(attr.only === 'float') {\n ctrl.$parsers.push(inputFloat);\n } else if(attr.only === 'currency') {\n ctrl.$parsers.push(inputCurrency);\n }\n }\n };\n });\n\nangular.module('components.main-menu.main-menu', [])\n .directive('mainMenu', function($state) {\n return {\n restrict: 'E',\n scope: {\n role: '=',\n mapping: '='\n },\n replace: true,\n templateUrl: 'app/components/main-menu/main-menu.html',\n link: function($scope) {\n $scope.isActive = function(routeName) {\n var activeRoute = false;\n routeName.map(function(item) {\n if (!activeRoute) {\n activeRoute = $state.current.name.indexOf(item) > -1;\n }\n });\n return activeRoute;\n }\n }\n }\n });\n\nangular.module('components.logout.logout', [])\n .directive('logout', function($modal, userService) {\n return {\n restrict: 'E',\n scope: {},\n replace: true,\n templateUrl: 'app/components/logout/logout.html',\n link: function($scope) {\n $scope.userService = userService;\n\n $scope.openLogoutModal = function() {\n return $modal({\n title: 'Are you sure want to log out?',\n templateUrl: 'app/components/modal/templates/logout.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function($scope) {\n $scope.logout = function() {\n $scope.$hide();\n return $scope.userService.logout();\n }\n }\n });\n }\n }\n }\n });\n\nangular.module('components.dropdown.dropdown', ['components.tooltip.tooltip'])\n .provider('$dropdown', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n templateUrl: 'app/components/dropdown/dropdown.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function ($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory (element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n /* var scope = */$dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function (evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if (!items.length) return;\n var index;\n angular.forEach(items, function (el, i) {\n if (matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if (evt.keyCode === 38 && index > 0) index--;\n else if (evt.keyCode === 40 && index < items.length - 1) index++;\n else if (angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function () {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function () {\n if (options.keyboard && $dropdown.$element) $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n if (parentEl.hasClass('dropdown')) parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function () {\n if (!$dropdown.$isShown) return;\n if (options.keyboard && $dropdown.$element) $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n if (parentEl.hasClass('dropdown')) parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function () {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick (evt) {\n if (evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function ($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n compile: function (tElement, tAttrs) {\n\n // Support for inlined template (next sibling)\n // It must be fetched before compilation\n if (!tAttrs.bsDropdown) {\n var nextSibling = tElement[0].nextSibling;\n while (nextSibling && nextSibling.nodeType !== 1) {\n nextSibling = nextSibling.nextSibling;\n }\n if (nextSibling && nextSibling.className.split(' ').indexOf('dropdown-menu') >= 0) {\n tAttrs.template = nextSibling.outerHTML;\n tAttrs.templateUrl = undefined;\n nextSibling.parentNode.removeChild(nextSibling);\n }\n }\n\n return function postLink (scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'id', 'autoClose'], function (key) {\n if (angular.isDefined(tAttrs[key])) options[key] = tAttrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // Support scope as an object\n if (attr.bsDropdown) {\n scope.$watch(attr.bsDropdown, function (newValue, oldValue) {\n scope.content = newValue;\n }, true);\n }\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Visibility binding support\n if (attr.bsShow) {\n scope.$watch(attr.bsShow, function (newValue, oldValue) {\n if (!dropdown || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n if (newValue === true) {\n dropdown.show();\n } else {\n dropdown.hide();\n }\n });\n }\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n };\n }\n };\n\n });\n\nangular.module('components.datepicker-tooltip.datepicker-tooltip', ['components.tooltip.dimensions-helper'])\n .provider('$datePickerTooltip', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n templateUrl: 'app/components/tooltip/tooltip.html',\n template: '',\n titleTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n mouseDownPreventDefault: true,\n mouseDownStopPropagation: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function ($window, $rootScope, $bsCompiler, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n var $body = angular.element($window.document);\n\n function TooltipFactory (element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n var promise = $tooltip.$promise = $bsCompiler.compile(options);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n var nodeName = element[0].nodeName.toLowerCase();\n if (options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // Store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if (options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function (isEnabled) {\n scope.$$postDigest(function () {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function () {\n scope.$$postDigest(function () {\n $tooltip.hide();\n });\n };\n scope.$show = function () {\n scope.$$postDigest(function () {\n $tooltip.show();\n });\n };\n scope.$toggle = function () {\n scope.$$postDigest(function () {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout;\n var hoverState;\n\n // Fetch, compile then initialize tooltip\n var compileData;\n var tipElement;\n var tipContainer;\n var tipScope;\n promise.then(function (data) {\n compileData = data;\n $tooltip.init();\n });\n\n $tooltip.init = function () {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if (options.container === 'self') {\n tipContainer = element;\n } else if (angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if (options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if (options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if (options.show) {\n scope.$$postDigest(function () {\n if (options.trigger === 'focus') {\n element[0].focus();\n } else {\n $tooltip.show();\n }\n });\n }\n\n };\n\n $tooltip.destroy = function () {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function () {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function () {\n if (hoverState === 'in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function () {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n promise.then(function (data) {\n compileData = data;\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n options.onBeforeShow($tooltip);\n }\n var parent;\n var after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if (tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = compileData.link(tipScope, function (clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if (options.animation) tipElement.addClass(options.animation);\n // Options: type\n if (options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if (options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n if (after) {\n after.after(tipElement);\n } else {\n parent.prepend(tipElement);\n }\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.enter(tipElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(tipElement, parent, after).then(enterAnimateCallback);\n }\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if (tipElement) tipElement.css({visibility: 'visible'});\n\n // Bind events\n if (options.keyboard) {\n if (options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n });\n\n if (options.autoClose) {\n bindAutoCloseEvents();\n }\n });\n\n };\n\n function enterAnimateCallback () {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n options.onShow($tooltip);\n }\n }\n\n $tooltip.leave = function () {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function (blur) {\n\n if (!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n options.onBeforeHide($tooltip);\n }\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.leave(tipElement, leaveAnimateCallback);\n } else {\n $animate.leave(tipElement).then(leaveAnimateCallback);\n }\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if (options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if (options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback () {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n options.onHide($tooltip);\n }\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if (_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function (evt) {\n if (evt) { evt.preventDefault(); }\n if ($tooltip.$isShown) {\n $tooltip.leave();\n } else {\n $tooltip.enter();\n }\n };\n\n $tooltip.focus = function () {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function (isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function (viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function () {\n if (!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement;\n var autoToken = /\\s?auto?\\s?/i;\n var autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition();\n var tipWidth = tipElement.prop('offsetWidth');\n var tipHeight = tipElement.prop('offsetHeight');\n\n // Refresh viewport position\n $tooltip.$viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var viewportPosition = getPosition($tooltip.$viewport);\n\n if (/bottom/.test(originalPlacement) && elementPosition.bottom + tipHeight > viewportPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (/top/.test(originalPlacement) && elementPosition.top - tipHeight < viewportPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n if (/left/.test(originalPlacement) && elementPosition.left - tipWidth < viewportPosition.left) {\n placement = placement.replace('left', 'right');\n } else if (/right/.test(originalPlacement) && elementPosition.right + tipWidth > viewportPosition.width) {\n placement = placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function (evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function (evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function (evt) {\n if (options.mouseDownPreventDefault) { evt.preventDefault(); }\n if (options.mouseDownStopPropagation) { evt.stopPropagation(); }\n // Some browsers do not auto-focus buttons (eg. Safari)\n if ($tooltip.$isShown) {\n element[0].blur();\n } else {\n element[0].focus();\n }\n };\n\n // bind/unbind events\n function bindTriggerEvents () {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function (trigger) {\n if (trigger === 'click' || trigger === 'contextmenu') {\n element.on(trigger, $tooltip.toggle);\n } else if (trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n if (nodeName === 'button' && trigger !== 'hover') {\n element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n });\n }\n\n function unbindTriggerEvents () {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if (trigger === 'click' || trigger === 'contextmenu') {\n element.off(trigger, $tooltip.toggle);\n } else if (trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n if (nodeName === 'button' && trigger !== 'hover') {\n element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n }\n\n function bindKeyboardEvents () {\n if (options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents () {\n if (options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents () {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function () {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents () {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation (event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition ($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0];\n var isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n /* eslint-disable guard-for-in */\n for (var p in elRect) { // eslint-disable-line\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n /* eslint-enable guard-for-in */\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, {width: elRect.right - elRect.left, height: elRect.bottom - elRect.top});\n }\n var elOffset = isBody ? {top: 0, left: 0} : dimensions.offset(el);\n var scroll = {scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0};\n var outerDims = isBody ? {width: document.documentElement.clientWidth, height: $window.innerHeight} : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset (placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if (!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if (split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n break;\n default:\n break;\n }\n } else if (split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight + position.height;\n break;\n case 'bottom':\n offset.top = position.top;\n break;\n default:\n break;\n }\n }\n\n return offset;\n }\n\n function applyPlacement (offset, placement) {\n var tip = tipElement[0];\n var width = tip.offsetWidth;\n var height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10);\n var marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth;\n var actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement);\n var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight;\n var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n // @source https://github.com/twbs/bootstrap/blob/v3.3.5/js/tooltip.js#L380\n function getViewportAdjustedDelta (placement, position, actualWidth, actualHeight) {\n var delta = {top: 0, left: 0};\n if (!$tooltip.$viewport) return delta;\n\n var viewportPadding = options.viewport && options.viewport.padding || 0;\n var viewportDimensions = getPosition($tooltip.$viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll;\n var bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding;\n var rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow (delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement () {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if ($tooltip.$isShown && tipElement !== null) {\n if (options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if (options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if (tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if (tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest (scope) {\n /* eslint-disable no-unused-expressions */\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n /* eslint-enable no-unused-expressions */\n }\n\n function findElement (query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function ($window, $location, $sce, $parse, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink (scope, element, attr, transclusion) {\n\n var tooltip;\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'titleTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function (key) {\n if (angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) {\n options[key] = false;\n }\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if (angular.isDefined(dataTarget)) {\n if (falseValueRegExp.test(dataTarget)) {\n options.target = false;\n } else {\n options.target = dataTarget;\n }\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')) {\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function (newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n if (angular.isDefined(oldValue)) {\n $$rAF(function () {\n if (tooltip) tooltip.$applyPlacement();\n });\n }\n }\n });\n\n attr.$observe('disabled', function (newValue) {\n if (newValue && tooltip.$isShown) {\n tooltip.hide();\n }\n });\n\n // Support scope as an object\n if (attr.bsTooltip) {\n scope.$watch(attr.bsTooltip, function (newValue, oldValue) {\n if (angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n if (angular.isDefined(oldValue)) {\n $$rAF(function () {\n if (tooltip) tooltip.$applyPlacement();\n });\n }\n }, true);\n }\n\n // Visibility binding support\n if (attr.bsShow) {\n scope.$watch(attr.bsShow, function (newValue, oldValue) {\n if (!tooltip || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n if (newValue === true) {\n tooltip.show();\n } else {\n tooltip.hide();\n }\n });\n }\n\n // Enabled binding support\n if (attr.bsEnabled) {\n scope.$watch(attr.bsEnabled, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if (!tooltip || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n if (newValue === false) {\n tooltip.setEnabled(false);\n } else {\n tooltip.setEnabled(true);\n }\n });\n }\n\n // Viewport support\n if (attr.viewport) {\n scope.$watch(attr.viewport, function (newValue) {\n if (!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n }\n\n // Initialize popover\n tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n\nangular.module('components.datepicker.datepicker', [\n 'components.datepicker.date-parser',\n 'components.datepicker.date-formatter',\n 'components.datepicker-tooltip.datepicker-tooltip'])\n\n .provider('$datepicker', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n // Uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n templateUrl: 'app/components/datepicker/datepicker.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n hasToday: false,\n hasClear: false,\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right',\n disableWeek: false,\n };\n\n this.$get = function ($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $datePickerTooltip, $timeout) {\n\n var isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if (!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory (element, controller, config) {\n\n var $datepicker = $datePickerTooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if (options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n scope.$hasToday = options.hasToday;\n scope.$hasClear = options.hasClear;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function (date, row, index) {\n var selectedRow = scope.rows.find(function(row) {\n return row.isSelected;\n });\n\n selectedRow && (selectedRow.isSelected = false);\n row.isSelected = true;\n scope.selectedRow = {index: index, startDate: row[0].date};\n\n $datepicker.select(date);\n };\n scope.$selectPane = function (value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function () {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n scope.$setToday = function () {\n if (options.autoclose) {\n $datepicker.setMode(0);\n $datepicker.select(new Date());\n } else {\n $datepicker.select(new Date(), true);\n }\n };\n scope.$clear = function () {\n if (options.autoclose) {\n $datepicker.setMode(0);\n $datepicker.select(null);\n } else {\n $datepicker.select(null, true);\n }\n };\n\n // Public methods\n\n $datepicker.update = function (date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if (angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function (dateRanges) {\n options.disabledDateRanges = dateRanges;\n for (var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function (date, keep) {\n if (angular.isDate(date)) {\n if (!angular.isDate(controller.$dateValue) || isNaN(controller.$dateValue.getTime())) {\n controller.$dateValue = new Date(date);\n }\n } else {\n controller.$dateValue = null;\n }\n if (!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(scope.selectedRow.startDate));\n controller.$render();\n if (options.autoclose && !keep) {\n $timeout(function () { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function (mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function (pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if (pristine === true && $picker.built) return;\n if (pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function () {\n for (var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function (date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function (el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function (value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function (evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if (isTouch) {\n var targetEl = angular.element(evt.target);\n if (targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function (evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if (evt.keyCode === 13) {\n if (!scope.$mode) {\n $datepicker.hide(true);\n } else {\n scope.$apply(function () { $datepicker.setMode(scope.$mode - 1); });\n }\n return;\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected (el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement () {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function () {\n if (isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if (isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function () {\n if (isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function () {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function () {\n // if $datepicker is no longer showing, don't setup events\n if (!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if (options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function (blur) {\n if (!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if (options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function ($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n // var defaults = $datepicker.defaults;\n var isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink (scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay',\n 'trigger', 'html', 'animation', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat',\n 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView',\n 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent', 'hasToday',\n 'hasClear', 'disableWeek'], function (key) {\n if (angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'hasToday', 'hasClear'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) {\n options[key] = false;\n }\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if (isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function (date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Visibility binding support\n if (attr.bsShow) {\n scope.$watch(attr.bsShow, function (newValue, oldValue) {\n if (!datepicker || !angular.isDefined(newValue)) return;\n if (angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n if (newValue === true) {\n datepicker.show();\n } else {\n datepicker.hide();\n }\n });\n }\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function (key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n if (angular.isDefined(attr[key])) {\n attr.$observe(key, function (newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n if (!isNaN(datepicker.$options[key])) datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n }\n });\n\n // Observe date format\n if (angular.isDefined(attr.dateFormat)) {\n attr.$observe('dateFormat', function (newValue) {\n datepicker.$options.dateFormat = newValue;\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function (newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges (ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function (disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate (parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if (isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function (viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if (!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if (!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n }\n validateAgainstMinMaxDate(parsedDate);\n\n if (options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if (options.dateType === 'number') {\n return date.getTime();\n } else if (options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if (options.dateType === 'iso') {\n return date.toISOString();\n }\n return new Date(date);\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function (modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if (angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if (angular.isDate(modelValue)) {\n date = modelValue;\n } else if (options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if (options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if (isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function () {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString () {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function () {\n\n // var defaults = this.defaults = {\n // dayFormat: 'dd',\n // daySplit: 7\n // };\n\n // Split array into smaller arrays\n function split (arr, size) {\n var arrays = [];\n while (arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod (n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function ($dateFormatter, $dateParser, $sce) {\n return function (picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function (date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join('') + '');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', picker.$date ? options.startDate : 'today') : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: {month: 1},\n update: function (date, force) {\n if (!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if (date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function () {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1);\n var firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5);\n var firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if (firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [];\n var day;\n for (var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n\n if(scope.selectedRow) {\n scope.rows.forEach(function(row) {\n row.forEach(function(week) {\n if(week.date.getTime() === scope.selectedRow.startDate.getTime()) {\n row.isSelected = true;\n }\n if(week.date.getTime() < scope.startRow.startDate.getTime()) {\n if (options.disableWeek === 'true') {\n row.isDisabled = true;\n }\n }\n });\n });\n }\n\n if(!this.built) {\n var nextWeek = 0;\n\n if (picker.$date) {\n picker.$date.setHours(0, 0, 0, 0);\n }\n\n scope.rows.some(function(row, index) {\n row.some(function(week) {\n if (week.date.getTime() < (picker.$date || startDate).getTime()) {\n nextWeek += 1;\n return true;\n }\n });\n });\n\n if (nextWeek >= scope.rows.length) {\n nextWeek = scope.rows.length - 1;\n }\n\n scope.rows[nextWeek].isSelected = true;\n scope.selectedRow = {index: nextWeek, title: scope.title, startDate: scope.rows[nextWeek][0].date};\n scope.startRow = angular.copy(scope.selectedRow);\n\n if (options.disableWeek === 'true') {\n scope.rows.forEach(function(row) {\n row.forEach(function(week) {\n if(week.date.getTime() < scope.startRow.startDate.getTime()) {\n row.isDisabled = true;\n }\n });\n });\n }\n if(!picker.$date) {\n picker.select(scope.selectedRow.startDate)\n }\n }\n scope.isTodayDisabled = this.isDisabled(new Date());\n this.built = true;\n },\n isSelected: function (date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function (date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function (evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if (evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if (evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if (evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if (evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: {year: 1},\n update: function (date, force) {\n if (!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if (date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function () {\n // var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [];\n var month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function (date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function (date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function (evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if (evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if (evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if (evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if (evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: {year: 12},\n update: function (date, force) {\n if (!this.built || force || parseInt(date.getFullYear() / 20, 10) !== parseInt(viewDate.year / 20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if (date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function () {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [];\n var year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function (date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function (date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function (evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear();\n var newDate = new Date(picker.$date);\n\n if (evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if (evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if (evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if (evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n\n'use strict';\n\nangular.module('components.datepicker.date-parser', [])\n\n .provider('$dateParser', function ($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate () {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function (value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function (value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function (value) { this.minutes = value; };\n ParseDate.prototype.setHours = function (value) { this.hours = value; };\n ParseDate.prototype.getHours = function () { return this.hours; };\n ParseDate.prototype.setDate = function (value) { this.day = value; };\n ParseDate.prototype.setMonth = function (value) { this.month = value; };\n ParseDate.prototype.setFullYear = function (value) { this.year = value; };\n ParseDate.prototype.fromDate = function (value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function () {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop () {\n }\n\n function isNumeric (n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive (array, value) {\n var len = array.length;\n var str = value.toString().toLowerCase();\n for (var i = 0; i < len; i++) {\n if (array[i].toLowerCase() === str) { return i; }\n }\n return -1; // Return -1 per the \"Array.indexOf()\" method.\n }\n\n var defaults = this.defaults = {\n format: 'shortDate',\n strict: false\n };\n\n this.$get = function ($locale, dateFilter) {\n\n var DateParserFactory = function (config) {\n\n var options = angular.extend({}, defaults, config);\n\n var $dateParser = {};\n\n /* eslint-disable key-spacing, quote-props */\n var regExpMap = {\n 'sss' : '[0-9]{3}',\n 'ss' : '[0-5][0-9]',\n 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'mm' : '[0-5][0-9]',\n 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'HH' : '[01][0-9]|2[0-3]',\n 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n 'hh' : '[0][1-9]|[1][012]',\n 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'a' : 'AM|PM',\n 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),\n 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n 'dd' : '0[1-9]|[12][0-9]|3[01]',\n 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),\n 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n 'MM' : '0[1-9]|1[012]',\n 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n 'yy' : '[0-9]{2}',\n 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}'\n };\n\n var setFnMap = {\n 'sss' : proto.setMilliseconds,\n 'ss' : proto.setSeconds,\n 's' : proto.setSeconds,\n 'mm' : proto.setMinutes,\n 'm' : proto.setMinutes,\n 'HH' : proto.setHours,\n 'H' : proto.setHours,\n 'hh' : proto.setHours,\n 'h' : proto.setHours,\n 'EEEE' : noop,\n 'EEE' : noop,\n 'dd' : proto.setDate,\n 'd' : proto.setDate,\n 'a' : function (value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n 'MMMM' : function (value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n 'MMM' : function (value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n 'MM' : function (value) { return this.setMonth(1 * value - 1); },\n 'M' : function (value) { return this.setMonth(1 * value - 1); },\n 'yyyy' : proto.setFullYear,\n 'yy' : function (value) { return this.setFullYear(2000 + 1 * value); },\n 'y' : function (value) { return (1 * value <= 50 && value.length === 2) ? this.setFullYear(2000 + 1 * value) : this.setFullYear(1 * value); }\n };\n /* eslint-enable key-spacing, quote-props */\n\n var regex;\n var setMap;\n\n $dateParser.init = function () {\n $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n regex = regExpForFormat($dateParser.$format);\n setMap = setMapForFormat($dateParser.$format);\n };\n\n $dateParser.isValid = function (date) {\n if (angular.isDate(date)) return !isNaN(date.getTime());\n return regex.test(date);\n };\n\n $dateParser.parse = function (value, baseDate, format, timezone) {\n // check for date format special names\n if (format) format = $locale.DATETIME_FORMATS[format] || format;\n if (angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n var formatRegex = format ? regExpForFormat(format) : regex;\n var formatSetMap = format ? setMapForFormat(format) : setMap;\n var matches = formatRegex.exec(value);\n if (!matches) return false;\n // use custom ParseDate object to set parsed values\n var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n for (var i = 0; i < matches.length - 1; i++) {\n if (formatSetMap[i]) formatSetMap[i].call(date, matches[i + 1]);\n }\n // convert back to native Date object\n var newDate = date.toDate();\n\n // check new native Date object for day values overflow\n if (parseInt(date.day, 10) !== newDate.getDate()) {\n return false;\n }\n\n return newDate;\n };\n\n $dateParser.getDateForAttribute = function (key, value) {\n var date;\n\n if (value === 'today') {\n var today = new Date();\n date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n } else if (angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n date = new Date(value.substr(1, value.length - 2));\n } else if (isNumeric(value)) {\n date = new Date(parseInt(value, 10));\n } else if (angular.isString(value) && value.length === 0) { // Reset date\n date = key === 'minDate' ? -Infinity : +Infinity;\n } else {\n date = new Date(value);\n }\n\n return date;\n };\n\n $dateParser.getTimeForAttribute = function (key, value) {\n var time;\n\n if (value === 'now') {\n time = new Date().setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && value.match(/^\".+\"$/)) {\n time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n } else if (isNumeric(value)) {\n time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && value.length === 0) { // Reset time\n time = key === 'minTime' ? -Infinity : +Infinity;\n } else {\n time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n }\n\n return time;\n };\n\n /* Handle switch to/from daylight saving.\n * Hours may be non-zero on daylight saving cut-over:\n * > 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function (date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function (date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo ? -1 : 1) * date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function regExpForFormat (format) {\n // `format` string can contain literal values.\n // These need to be escaped by surrounding with\n // single quotes (e.g. `\"h 'in the morning'\"`).\n // In order to output a single quote, escape it - i.e.,\n // two single quotes in a sequence (e.g. `\"h 'o''clock'\"`).\n\n var re = buildDateAbstractRegex(format);\n return buildDateParseRegex(re);\n }\n\n function buildDateAbstractRegex (format) {\n var escapedFormat = escapeReservedSymbols(format);\n var escapedLiteralFormat = escapedFormat.replace(/''/g, '\\\\\\'');\n var literalRegex = /('(?:\\\\'|.)*?')/;\n var formatParts = escapedLiteralFormat.split(literalRegex);\n var dateElements = Object.keys(regExpMap);\n var dateRegexParts = [];\n\n angular.forEach(formatParts, function (part) {\n if (isFormatStringLiteral(part)) {\n part = trimLiteralEscapeChars(part);\n } else {\n // Abstract replaces to avoid collisions\n for (var i = 0; i < dateElements.length; i++) {\n part = part.split(dateElements[i]).join('${' + i + '}');\n }\n }\n dateRegexParts.push(part);\n });\n\n return dateRegexParts.join('');\n }\n\n function escapeReservedSymbols (text) {\n return text.replace(/\\\\/g, '[\\\\\\\\]')\n .replace(/-/g, '[-]')\n .replace(/\\./g, '[.]')\n .replace(/\\*/g, '[*]')\n .replace(/\\+/g, '[+]')\n .replace(/\\?/g, '[?]')\n .replace(/\\$/g, '[$]')\n .replace(/\\^/g, '[^]')\n .replace(/\\//g, '[/]')\n .replace(/\\\\s/g, '[\\\\s]');\n }\n\n function isFormatStringLiteral (text) {\n return /^'.*'$/.test(text);\n }\n\n function trimLiteralEscapeChars (text) {\n return text.replace(/^'(.*)'$/, '$1');\n }\n\n function buildDateParseRegex (abstractRegex) {\n var dateElements = Object.keys(regExpMap);\n var re = abstractRegex;\n\n // Replace abstracted values\n for (var i = 0; i < dateElements.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[dateElements[i]] + ')');\n }\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n function setMapForFormat (format) {\n var re = buildDateAbstractRegex(format);\n return buildDateParseValuesMap(re);\n }\n\n function buildDateParseValuesMap (abstractRegex) {\n var dateElements = Object.keys(regExpMap);\n var valuesRegex = new RegExp('\\\\${(\\\\d+)}', 'g');\n var valuesMatch;\n var keyIndex;\n var valueKey;\n var valueFunction;\n var valuesFunctionMap = [];\n\n /* eslint-disable no-cond-assign */\n while ((valuesMatch = valuesRegex.exec(abstractRegex)) !== null) {\n keyIndex = valuesMatch[1];\n valueKey = dateElements[keyIndex];\n valueFunction = setFnMap[valueKey];\n\n valuesFunctionMap.push(valueFunction);\n }\n\n return valuesFunctionMap;\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n });\n\nangular.module('components.datepicker.date-formatter', []).service('$dateFormatter', [ '$locale', 'dateFilter', function($locale, dateFilter) {\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n this.formatDate = function(date, format, lang, timezone) {\n return dateFilter(date, format, timezone);\n };\n} ]);\n\nangular.module('components.data-access.user-service', ['ngStorage'])\n .factory('userService', function($q, $location, $state, $localStorage, userApiService) {\n var userData = {}, LOGIN_STATE = 'login';\n\n return {\n isUserLoggedIn: function() {\n return !!$localStorage.apiToken;\n },\n\n getResetToken: function() {\n return $location.search().resetToken;\n },\n\n getUser: function(field) {\n return field ? userData[field] : userData;\n },\n\n setUser: function(user) {\n if(this.isUserLoggedIn()) {\n if(user) {\n angular.extend(userData, user);\n } else {\n userData = $localStorage.user;\n }\n }\n },\n\n deleteUser: function() {\n userData = {};\n $localStorage.user = '';\n },\n\n getToken: function() {\n return $localStorage.apiToken || '';\n },\n\n clearToken: function() {\n $localStorage.apiToken = '';\n },\n\n checkResetToken: function() {\n\n return userApiService.checkResetToken(this.getResetToken());\n },\n\n login: function(user) {\n\n return userApiService.login(user).then(function(data) {\n userData = data.user;\n userData.firstName = userData.first_name;\n userData.lastName = userData.last_name;\n userData.fullName = userData.firstName + ' ' + userData.lastName;\n if(data.token) {\n $localStorage.apiToken = data.token;\n $localStorage.user = userData;\n $state.go('main.menu');\n }\n });\n },\n\n logout: function() {\n this.deleteUser();\n this.clearToken();\n $state.go(LOGIN_STATE);\n },\n\n resetPassword: function(email) {\n\n return userApiService.resetPassword(email).then(function() {\n $state.go(LOGIN_STATE);\n });\n },\n\n changePassword: function(password) {\n\n return userApiService.changePassword(password, this.getResetToken()).then(function() {\n $state.go(LOGIN_STATE);\n });\n }\n }\n });\n\nangular.module('components.data-access.title-service', [])\n .factory('titleService', function() {\n return {\n setTitle: function(title) {\n var currentTitle = title ? title + ' | ' : '';\n document.querySelector('title').textContent = currentTitle + 'Guest Service';\n },\n }\n });\n\nangular.module('components.catalogue.catalogue', [\n 'components.data-access.api.recipe-api-service',\n 'components.data-access.title-service',\n 'components.catalogue.recipe-list.recipe-list',\n 'components.catalogue.recipe-filters.recipe-filters',\n 'components.catalogue.catalogue-pagination.catalogue-pagination',\n 'components.dropdown.dropdown',\n 'components.catalogue.create-recipe.create-recipe',\n 'components.catalogue.view-recipe.view-recipe',\n])\n .directive('catalogue', function (recipeApiService, titleService, $modal, $state, $location, PermPermissionStore, $sessionStorage) {\n return {\n restrict: 'E',\n scope: {\n filters: '=',\n recipes: '=',\n pagination: '=?',\n collapsed: '=?',\n onSelectRecipe: '=?',\n },\n replace: true,\n templateUrl: 'app/components/catalogue/catalogue.html',\n link: function ($scope) {\n var searchParams = $location.search();\n recipeApiService.saveFilters($scope.filters);\n\n $scope.isLoading = false;\n $scope.isChanged = $scope.noResults = false;\n $scope.categories = searchParams.categories ? JSON.parse(searchParams.categories) : {};\n $scope.filteredRecipes = $scope.recipes;\n $scope.originalPagination = angular.copy($scope.pagination);\n\n if (!$scope.collapsed) {\n titleService.setTitle('Catalogue');\n\n if ($sessionStorage.search) {\n $scope.search = $sessionStorage.search;\n }\n }\n\n $scope.DROPDOWN_MAPPING = [\n { name: 'A-Z', selectedName: 'A-Z', predicate: 'title', dir: 'asc', selected: true },\n { name: 'Z-A', selectedName: 'Z-A', predicate: 'title', dir: 'desc' },\n { name: 'Calories', selectedName: 'calories', predicate: 'calories', dir: 'asc', className: 'asc' },\n { name: 'Calories', selectedName: 'calories', predicate: 'calories', dir: 'desc', className: 'desc' },\n { name: 'Date of creation', selectedName: 'date of creation', predicate: 'created', dir: 'asc', className: 'asc' },\n { name: 'Date of creation', selectedName: 'date of creation', predicate: 'created', dir: 'desc', className: 'desc' }\n ];\n\n if (searchParams.sort) {\n $scope.sort = searchParams.sort ? JSON.parse(searchParams.sort) : {};\n $scope.DROPDOWN_MAPPING.map(function (item) {\n if (item.predicate === $scope.sort.predicate && item.dir === $scope.sort.dir) {\n item.selected = true;\n $scope.selected = item;\n } else {\n item.selected = false;\n }\n });\n } else {\n $scope.selected = $scope.DROPDOWN_MAPPING[0];\n }\n\n $scope.onChange = function (categories) {\n $scope.categories = categories;\n $location.search('page', null);\n\n if (Object.keys(categories).some(function (key) {\n return angular.isArray(categories[key]) && categories[key].length;\n })) {\n $scope.filteredRecipes = [];\n $scope.isLoading = true;\n $scope.noResults = false;\n\n if ($scope.collapsed) {\n return recipeApiService.filterRecipes(categories, 0, $scope.sort).then(function (recipes) {\n $scope.noResults = !recipes.data.length;\n $scope.filteredRecipes = recipes.data;\n $scope.pagination = recipes.meta.pagination;\n });\n } else {\n $location.search('categories', JSON.stringify(categories));\n }\n } else {\n $scope.noResults = false;\n $scope.filteredRecipes = $scope.recipes;\n $scope.pagination = $scope.originalPagination;\n $location.search('categories', null);\n }\n };\n\n $scope.setOrder = function (link) {\n $scope.DROPDOWN_MAPPING.find(function (item) {\n return item.selected;\n }).selected = false;\n link.selected = true;\n $scope.sort = link;\n\n if (($scope.selected.predicate !== link.predicate) || ($scope.selected.dir !== link.dir)) {\n $scope.selected = link;\n $location.search('sort', JSON.stringify(link));\n }\n };\n\n $scope.onSetPage = function (offset) {\n $scope.offset = offset;\n if ($scope.collapsed) {\n return recipeApiService.filterRecipes($scope.categories, offset, $scope.sort).then(function(recipes) {\n $scope.filteredRecipes = recipes.data;\n $scope.pagination = recipes.meta.pagination;\n $scope.isChanged = false;\n var el = document.querySelector('.recipe-list');\n el.scrollTo(0, 0);\n })\n } else {\n $location.search('page', offset);\n }\n };\n\n $scope.$watch('search', function (search) {\n if (search && search.length >= 3) {\n $scope.filteredRecipes = [];\n $scope.isLoading = true;\n $scope.noResults = false;\n recipeApiService.searchRecipe(search).then(function (recipes) {\n $scope.noResults = !recipes.length;\n $scope.filteredRecipes = recipes;\n $scope.isChanged = true;\n $sessionStorage.search = search;\n });\n } else if ($scope.isChanged) {\n $scope.filteredRecipes = [];\n $scope.isLoading = true;\n $scope.noResults = false;\n\n if (Object.keys($scope.categories).length) {\n recipeApiService.filterRecipes($scope.categories, 0, $scope.sort).then(onSuccess);\n } else {\n recipeApiService.getRecipe().then(onSuccess);\n }\n }\n });\n\n function onSuccess(recipes) {\n $scope.noResults = !recipes.data.length;\n $scope.filteredRecipes = recipes.data;\n $scope.pagination = recipes.meta.pagination;\n $scope.isChanged = false;\n delete $sessionStorage.search;\n }\n\n $scope.openImportModal = function () {\n return $modal({\n title: 'Import URL',\n templateUrl: 'app/components/modal/templates/import.html',\n customClass: 'user-create-modal',\n scope: $scope,\n controller: function ($scope) {\n $scope.action = function (url) {\n $scope.disableSubmit = true;\n return recipeApiService.importRecipe(url).then(function (recipe) {\n PermPermissionStore\n .definePermission('canEditRecipe', function () {\n return true;\n });\n\n $state.go('main.edit-recipe', { recipe: recipe, recipeId: recipe.id });\n $scope.$hide();\n }, function () {\n $scope.disableSubmit = false;\n });\n };\n },\n });\n };\n },\n };\n });\n\n/**\n * Angucomplete\n * Autocomplete directive for AngularJS\n * By Daryl Rowland\n */\n\nangular.module('angucomplete', [])\n .directive('angucomplete', function ($parse, $http, $sce, $timeout) {\n return {\n restrict: 'EA',\n scope: {\n \"id\": \"@id\",\n \"placeholder\": \"@placeholder\",\n \"selectedObject\": \"=selectedobject\",\n \"url\": \"@url\",\n \"inputChange\": \"=inputChange\",\n 'inputChangeParams': '=?',\n 'onBlur': '=?',\n 'onBlurParams': '=?',\n \"ngReadonly\": \"=ngReadonly\",\n \"dataField\": \"@datafield\",\n \"titleField\": \"@titlefield\",\n \"descriptionField\": \"@descriptionfield\",\n \"imageField\": \"@imagefield\",\n \"imageUri\": \"@imageuri\",\n \"inputClass\": \"@inputclass\",\n \"inputName\": \"@\",\n \"userPause\": \"@pause\",\n \"localData\": \"=localdata\",\n \"searchFields\": \"@searchfields\",\n \"minLengthUser\": \"@minlength\",\n \"matchClass\": \"@matchclass\",\n },\n template:\n '
' +\n '' +\n '
' +\n '
Searching...
' +\n '
No results found
' +\n '
' +\n '
' +\n '' +\n '
' +\n '
' +\n '
' +\n '
{{ result.title }}
' +\n '
{{result.description}}
' +\n '
',\n\n link: function ($scope, elem, attrs) {\n $scope.lastSearchTerm = null;\n $scope.currentIndex = null;\n $scope.justChanged = false;\n $scope.searchTimer = null;\n $scope.hideTimer = null;\n $scope.searching = false;\n $scope.pause = 500;\n $scope.inputName = $scope.inputName || 'IngName';\n $scope.minLength = 3;\n $scope.searchStr = $scope.selectedObject.name || $scope.selectedObject.title || null;\n\n if ($scope.minLengthUser && $scope.minLengthUser != \"\") {\n $scope.minLength = $scope.minLengthUser;\n }\n\n if ($scope.userPause) {\n $scope.pause = $scope.userPause;\n }\n\n var isNewSearchNeeded = function (newTerm, oldTerm) {\n return newTerm.length >= $scope.minLength && newTerm != oldTerm;\n };\n\n $scope.processResults = function (responseData, str) {\n if (responseData && responseData.length > 0) {\n $scope.results = [];\n\n var titleFields = [];\n if ($scope.titleField && $scope.titleField != \"\") {\n titleFields = $scope.titleField.split(\",\");\n }\n\n for (var i = 0; i < responseData.length; i++) {\n // Get title variables\n var titleCode = [];\n\n for (var t = 0; t < titleFields.length; t++) {\n titleCode.push(responseData[i][titleFields[t]]);\n }\n\n var description = \"\";\n if ($scope.descriptionField) {\n description = responseData[i][$scope.descriptionField];\n }\n\n var imageUri = \"\";\n if ($scope.imageUri) {\n imageUri = $scope.imageUri;\n }\n\n var image = \"\";\n if ($scope.imageField) {\n image = imageUri + responseData[i][$scope.imageField];\n }\n\n var text = titleCode.join(' ');\n if ($scope.matchClass) {\n var re = new RegExp(str, 'i');\n var strPart = text.match(re)[0];\n text = $sce.trustAsHtml(text.replace(re, '' + strPart + ''));\n }\n\n var resultRow = {\n title: text,\n description: description,\n image: image,\n originalObject: responseData[i],\n };\n\n $scope.results[$scope.results.length] = resultRow;\n }\n\n\n } else {\n $scope.results = [];\n }\n };\n\n $scope.searchTimerComplete = function (str) {\n // Begin the search\n\n if (str && str.length >= $scope.minLength) {\n if ($scope.localData) {\n var searchFields = $scope.searchFields.split(\",\");\n\n var matches = [];\n\n for (var i = 0; i < $scope.localData.length; i++) {\n var match = false;\n\n for (var s = 0; s < searchFields.length; s++) {\n var isString = typeof $scope.localData[i][searchFields[s]] === 'string';\n var isFound = $scope.localData[i][searchFields[s]].toLowerCase().indexOf(str.toLowerCase()) >= 0;\n match = match || (isString && typeof str === 'string' && isFound);\n }\n\n if (match) {\n matches[matches.length] = $scope.localData[i];\n }\n }\n\n $scope.searching = false;\n $scope.processResults(matches, str);\n\n } else {\n $http.get($scope.url + str, {}).then(function (responseData, status, headers, config) {\n $scope.searching = false;\n $scope.processResults((($scope.dataField) ? responseData.data[$scope.dataField] : responseData.data ), str);\n }).catch(function (data, status, headers, config) {\n });\n }\n }\n };\n\n $scope.hideResults = function () {\n $scope.onBlur && $scope.onBlur.apply(null, [$scope.selectedObject, $scope.searchStr].concat($scope.onBlurParams));\n\n $scope.hideTimer = $timeout(function () {\n $scope.showDropdown = false;\n }, $scope.pause);\n };\n\n $scope.resetHideResults = function () {\n if ($scope.hideTimer) {\n $timeout.cancel($scope.hideTimer);\n }\n };\n\n $scope.hoverRow = function (index) {\n $scope.currentIndex = index;\n };\n\n $scope.keyPressed = function (event) {\n if (!(event.which == 38 || event.which == 40 || event.which == 13)) {\n if (!$scope.searchStr || $scope.searchStr == \"\") {\n $scope.showDropdown = false;\n $scope.lastSearchTerm = null;\n } else if (isNewSearchNeeded($scope.searchStr, $scope.lastSearchTerm)) {\n $scope.lastSearchTerm = $scope.searchStr;\n $scope.showDropdown = true;\n $scope.currentIndex = -1;\n $scope.results = [];\n\n if ($scope.searchTimer) {\n $timeout.cancel($scope.searchTimer);\n }\n\n $scope.searching = true;\n\n $scope.searchTimer = $timeout(function () {\n $scope.searchTimerComplete($scope.searchStr);\n }, $scope.pause);\n }\n } else {\n event.preventDefault();\n }\n };\n\n $scope.selectResult = function (result) {\n if ($scope.matchClass) {\n result.title = result.title.toString().replace(/(<([^>]+)>)/ig, '');\n }\n $scope.searchStr = $scope.lastSearchTerm = result.title;\n $scope.selectedObject = result;\n $scope.showDropdown = false;\n $scope.results = [];\n $scope.inputChange.apply(null, [result, $scope.selectedObject].concat($scope.inputChangeParams));\n //$scope.$apply();\n };\n\n var inputField = elem.find('input');\n\n inputField.on('keyup', $scope.keyPressed);\n\n elem.on(\"keyup\", function (event) {\n if (event.which === 40) {\n // key arrow down\n if ($scope.results && ($scope.currentIndex + 1) < $scope.results.length) {\n $scope.currentIndex++;\n $scope.$apply();\n event.preventDefault();\n event.stopPropagation();\n }\n\n $scope.$apply();\n } else if (event.which == 38) {\n // key arrow up\n if ($scope.currentIndex >= 1) {\n $scope.currentIndex--;\n $scope.$apply();\n event.preventDefault();\n event.stopPropagation();\n }\n\n } else if (event.which == 13) {\n // key enter\n if ($scope.results && $scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) {\n $scope.selectResult($scope.results[$scope.currentIndex]);\n $scope.$apply();\n event.preventDefault();\n event.stopPropagation();\n } else {\n $scope.results = [];\n $scope.$apply();\n event.preventDefault();\n event.stopPropagation();\n }\n\n } else if (event.which == 27) {\n // key escape\n $scope.results = [];\n $scope.showDropdown = false;\n $scope.$apply();\n } else if (event.which == 8) {\n // key backspace\n $scope.selectedObject = {};\n $scope.$apply();\n }\n });\n\n },\n };\n });\n\n\nangular.module('components.alert.alert', ['components.modal.modal'])\n .provider('$alert', function () {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n templateUrl: 'app/components/alert/alert.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function ($modal, $timeout) {\n\n function AlertFactory (config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if (options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if (options.duration) {\n $alert.show = function () {\n show();\n $timeout(function () {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function ($window, $sce, $alert) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink (scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function (key) {\n if (angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function (key) {\n if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // bind functions from the attrs to the show and hide events\n angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n if (angular.isDefined(attr[bsKey])) {\n options[key] = scope.$eval(attr[bsKey]);\n }\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')) {\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function (key) {\n if (attr[key]) {\n attr.$observe(key, function (newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n }\n });\n\n // Support scope as an object\n if (attr.bsAlert) {\n scope.$watch(attr.bsAlert, function (newValue, oldValue) {\n if (angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n }\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function () {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n\nangular.module('guestServices')\n .directive('guestServices', function(userService, TABLES_MAPPING, $state) {\n return {\n restrict: 'E',\n scope: true,\n templateUrl: 'app/guest-services/guest-services.html',\n link: function($scope) {\n $scope.user = userService.getUser();\n\n $scope.TABLES_MAPPING = TABLES_MAPPING;\n }\n }\n });\n\nangular.module('guestServices')\n .config(['$qProvider', function ($qProvider) {\n $qProvider.errorOnUnhandledRejections(false);\n }])\n .run(function ($rootScope, $log, $state, $modal, $window, userService, PermRoleStore, PermPermissionStore) {\n function defineRole(roleName) {\n return userService.getUser('role') === roleName;\n }\n\n PermRoleStore.defineManyRoles({\n 'Admin': defineRole,\n 'Main Chef': defineRole,\n 'Local Chef': defineRole\n });\n\n PermPermissionStore.definePermission('authorized', function () {\n return userService.isUserLoggedIn();\n });\n\n userService.setUser();\n\n $rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from) {\n $rootScope.router = {\n prevState: from.name || 'login'\n };\n $window.scroll(0, 0);\n });\n\n $rootScope.$on('requestFailed', function (e, error) {\n $modal({\n title: 'An Error Was Encountered ...',\n content: 'This issue has been logged, and we are looking into it. If you require further assistance, please contact the System Administrator.',\n templateUrl: 'app/components/modal/templates/err.tpl.html'\n });\n $log.log(error);\n });\n\n $rootScope.$on('notFound', function (e, error) {\n $modal({\n title: error.message,\n templateUrl: 'app/components/modal/templates/err.tpl.html'\n });\n\n $log.log(error);\n });\n\n $rootScope.$on('noAuth', function (e, error) {\n userService.logout();\n $state.go(error.toState);\n $log.log(error.error);\n });\n\n });\n\nangular.module('guestServices')\n .config(function ($stateProvider, $urlRouterProvider) {\n $stateProvider\n .state('login', {\n url: '/login',\n template: '',\n data: {\n permissions: {\n except: ['authorized', 'Admin'],\n redirectTo: {\n Admin: 'main.users',\n default: 'main.menu'\n }\n }\n }\n })\n .state('forgot-password', {\n url: '/forgot-password',\n template: '',\n data: {\n permissions: {\n except: ['authorized', 'Admin'],\n redirectTo: {\n Admin: 'main.users',\n default: 'main.menu'\n }\n }\n }\n })\n .state('change-password', {\n url: '/change-password?:resetToken',\n template: '',\n data: {\n permissions: {\n except: ['authorized', 'Admin'],\n redirectTo: {\n Admin: 'main.users',\n default: 'main.menu'\n }\n }\n }\n })\n\n\n .state('main', {\n url: '/',\n template: '',\n abstract: true,\n data: {\n permissions: {\n only: ['authorized'],\n redirectTo: 'login'\n }\n }\n })\n .state('main.menu', {\n url: 'menu',\n template: '',\n params: {\n startDate: null\n },\n data: {\n permissions: {\n only: ['authorized'],\n redirectTo: 'login'\n }\n },\n controller: function($scope, $stateParams) {\n $scope.startDate = $stateParams.startDate;\n }\n })\n .state('main.create-menu', {\n url: 'create-menu',\n template: '',\n data: {\n permissions: {\n only: ['authorized'],\n redirectTo: 'login'\n },\n }\n })\n .state('main.edit-menu', {\n url: 'edit-menu/:menuId',\n template: '',\n data: {\n permissions: {\n only: ['authorized'],\n redirectTo: 'login'\n },\n },\n resolve: {\n menuData: function(menuApiService, $stateParams) {\n return menuApiService.getMenu($stateParams.menuId);\n }\n },\n controller: function($scope, menuData) {\n $scope.menuData = menuData;\n }\n })\n\n .state('main.catalogue', {\n url: 'catalogue?page&categories&sort',\n template: '',\n data: {\n permissions: {\n only: ['authorized'],\n redirectTo: 'login'\n }\n },\n resolve: {\n filters: function(recipeApiService) {\n return recipeApiService.getDefaultFilters();\n },\n recipes: function(recipeApiService, $stateParams) {\n if ($stateParams.page > 0 || $stateParams.categories || $stateParams.sort) {\n var page = $stateParams.page ? $stateParams.page : 0;\n var categories = $stateParams.categories ? JSON.parse($stateParams.categories) : [];\n var sort = $stateParams.sort ? JSON.parse($stateParams.sort) : {};\n return recipeApiService.filterRecipes(categories, page, sort);\n }\n return recipeApiService.getRecipe();\n }\n },\n controller: function($scope, recipes, filters) {\n $scope.recipes = recipes.data;\n $scope.pagination = recipes.meta ? recipes.meta.pagination : [];\n $scope.filters = filters;\n }\n })\n .state('main.create-recipe', {\n url: 'create-recipe',\n template: '',\n data: {\n permissions: {\n only: ['authorized'],\n redirectTo: 'login'\n },\n },\n resolve: {\n options: function(recipeApiService) {\n return recipeApiService.getFilters();\n }\n },\n controller: function($scope, options) {\n $scope.options = options;\n }\n })\n .state('main.edit-recipe', {\n url: 'edit-recipe/:recipeId',\n template: '',\n data: {\n permissions: {\n only: ['Main Chef','Local Chef', 'Admin', 'canEditRecipe'],\n redirectTo: 'main.menu'\n }\n },\n params: {\n recipe: null\n },\n resolve: {\n recipe: function(recipeApiService, $stateParams) {\n if($stateParams.recipe) {\n $stateParams.recipe.id = undefined;\n }\n return $stateParams.recipe ? $stateParams.recipe : recipeApiService.getRecipe($stateParams.recipeId);\n },\n options: function(recipeApiService) {\n return recipeApiService.getFilters();\n }\n },\n controller: function($scope, recipe, options) {\n $scope.recipe = recipe;\n $scope.options = options;\n }\n })\n .state('main.view-recipe', {\n url: 'view-recipe/:recipeId',\n template: '',\n resolve: {\n recipe: function(recipeApiService, $stateParams) {\n return recipeApiService.calculateRecipe({id: $stateParams.recipeId});\n }\n },\n controller: function($scope, recipe) {\n $scope.recipe = recipe;\n }\n })\n .state('main.users', {\n url: 'users',\n template: '',\n resolve: {\n users: function(userListApiService) {\n return userListApiService.getAllUsers();\n }\n },\n data: {\n permissions: {\n only: ['Admin'],\n redirectTo: 'main.menu'\n }\n },\n controller: function($scope, users) {\n $scope.users = users.data;\n }\n });\n\n\n $urlRouterProvider.otherwise(function($injector) {\n var $state = $injector.get(\"$state\");\n $state.go('login');\n });\n });\n\n/* global moment:false */\n\n// @todo pas REMOVE\n\n// console.log('PARAMS: ');\n// console.log(window.location.protocol);\n// console.log(window.location.hostname);\n// console.log(window.location.port);\n\n// END remove\n\nangular.module('guestServices')\n \n // @todo PAS CHANGE THIS TO A SERVER/ENVIRONMENT VARIABLE!!!\n .constant('API_URL', 'https://recipes-api.zurka.com/api/v1')\n\n/*\n @todo pas use this line, once proper env parameters are set.\n .constant('API_URL', /local/.test(window.location.hostname) ? 'http://api.recipes.com/api/v1' : '/api/v1')\n*/\n\n .constant('CONFIRM_URL', window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port : '') + '/#/change-password?resetToken=:reset-token:')\n\n .constant('moment', moment)\n\n .constant('TABLES_MAPPING', {\n userList: [\n {title: 'Name', value: 'fullName'},\n {title: 'Email', value: 'email'},\n {title: 'Role', value: 'role'}\n ]\n });\n\nangular.module('guestServices')\n .config(function config($httpProvider, $modalProvider, $alertProvider, $datepickerProvider, $logProvider, $locationProvider) {\n $logProvider.debugEnabled(true);\n\n $locationProvider.html5Mode(false);\n $locationProvider.hashPrefix('');\n\n angular.extend($modalProvider.defaults, {\n animation: 'am-fade-and-scale',\n placement: 'center',\n backdrop: 'static',\n keyboard: false\n });\n\n angular.extend($alertProvider.defaults, {\n animation: 'am-fade-and-slide-top',\n duration: 5,\n dismissable: false\n });\n\n angular.extend($datepickerProvider.defaults, {\n trigger: 'manual',\n dateFormat: 'dd/MM/yyyy',\n startWeek: 1\n });\n\n $httpProvider.interceptors.push(function ($q, $rootScope, $localStorage) {\n return {\n request: function(config) {\n if($localStorage.apiToken) {\n config.headers['X-Authorization'] = 'Bearer ' + $localStorage.apiToken;\n }\n\n return config;\n },\n responseError: function (error) {\n if(error.status === 500) {\n $rootScope.$broadcast('requestFailed', error);\n } else if(error.status === 401) {\n $rootScope.$broadcast('noAuth', {toState: 'login', error: error});\n } else if(error.status === 404) {\n $rootScope.$broadcast('notFound', error.data);\n }\n\n return $q.reject(error);\n }\n };\n });\n });\n\nangular.module(\"guestServices\").run([\"$templateCache\", function($templateCache) {$templateCache.put(\"app/guest-services/guest-services.html\",\"
{{user.fullName}}
{{user.role}}
\");\n$templateCache.put(\"app/components/alert/alert.html\",\"   \");\n$templateCache.put(\"app/components/catalogue/catalogue.html\",\"
\");\n$templateCache.put(\"app/components/dropdown/dropdown.html\",\"\");\n$templateCache.put(\"app/components/datepicker/datepicker.html\",\"
\");\n$templateCache.put(\"app/components/logout/logout.html\",\"
\");\n$templateCache.put(\"app/components/main-menu/main-menu.html\",\"\");\n$templateCache.put(\"app/components/menu/menu.html\",\"

No menus added
{{menuData.title}}
{{tab.name}}
{{station.name}}
Select week
Schedule of meal
{{station.name}}
{{station.start + \\' - \\' + station.end}}

\");\n$templateCache.put(\"app/components/modal/modal.html\",\"\");\n$templateCache.put(\"app/components/nutritions-table/nutritions-table.html\",\"

Total Nutrition Facts

Portion Size {{data.portion.size + \\' \\' + data.portion.unit}}
{{ nutrition.key }}{{ data.nutrition_report[nutrition.value] | number: 1 }}{{ nutrition.unit }}
\");\n$templateCache.put(\"app/components/popover/popover.html\",\"

\");\n$templateCache.put(\"app/components/tooltip/tooltip.html\",\"
\");\n$templateCache.put(\"app/components/pagination/pagination.html\",\"\");\n$templateCache.put(\"app/components/user-list-table/user-list-table.html\",\"
{{th.title}}
{{user[td.value]}}

No users added
\");\n$templateCache.put(\"app/components/user-login/change-password.html\",\"
Change Password
\");\n$templateCache.put(\"app/components/user-login/forgot-password.html\",\"
Forgot your password?
Please enter your email and we will send
you password reset instructions
\");\n$templateCache.put(\"app/components/user-login/login.html\",\"\");\n$templateCache.put(\"app/components/user-login/user-login.html\",\"\");\n$templateCache.put(\"app/components/catalogue/catalogue-pagination/catalogue-pagination.html\",\"
data.per_page\\\"> 1\\\" ng-click=\\\"currentChunk > 0 && setChunk(-1, $event)\\\">« {{page + 1}} 1\\\" ng-click=\\\"currentChunk < pages.length - 1 && setChunk(1, $event)\\\">»
\");\n$templateCache.put(\"app/components/catalogue/create-recipe/create-recipe.html\",\"

{{recipe ? \\'Edit\\' : \\'Create\\'}} Recipe

Recipe title is required

Categories

{{category.name}}
    = 7 && getColumnsCount(category.categories.length, 7)}\\\">

Allergens

    = 2 && getColumnsCount(options.allergens.length, 2)}\\\">

Dietary

    = 4 && getColumnsCount(options.dietary.length, 4)}\\\">
Amount is required Nutritional facts are required Ingredients are required
FatCarbsProtCal
IngredientsAmountUnits{{ recipe.nutritionsSum.total_fat | number: 1 }}{{ recipe.nutritionsSum.carbohydrate | number: 1 }}{{ recipe.nutritionsSum.protein | number: 1 }}{{ recipe.nutritionsSum.calories | number: 0 }}

Nutrition Facts

{{ nutrition.key }}{{ recipe.nutritionsSum[nutrition.value] | number: 1 }}{{ nutrition.unit }}

Nutrition Facts

{{ nutrition.key }}{{ ingredient.nutritionSum[nutrition.value] | number: 1 }}{{ nutrition.unit }}
Add ingredient
  • 1\\\" ng-click=\\\"removeByIndex(recipe.methods, $index, {}, \\'step\\')\\\">
    Add step
Add new sub recipe
200 || $height > 200\\\" ngf-max-size=5MB> Add photo
200 || $height > 200\\\" ngf-max-size=5MB>
Photo must be no less than 200 pixels tall and wide. Photo size must be no more than 5 MB. Jpeg or PNG formats are supported.

Total Nutrition Facts

per serving
{{ nutrition.key }}{{ totalNutritionsWithServing[nutrition.value] | number: 1 }}{{ nutrition.unit }}
\");\n$templateCache.put(\"app/components/catalogue/recipe-filters/recipe-filters.html\",\"
Cuisine
Categories
Dietary

\");\n$templateCache.put(\"app/components/catalogue/recipe-list/recipe-list.html\",\"
{{recipe.title | truncate : 65 : true}}
cal: {{recipe.calories}}
{{recipe.cuisine.name}}

No recipes added

No results
\");\n$templateCache.put(\"app/components/catalogue/view-recipe/view-recipe.html\",\"
{{recipe.cuisine.name}}
{{category.group_name + \\': \\' + category.name}}
{{\\'Dietary: \\' + dietary.name}}
{{recipe.title}}
Author
{{recipe.chef.name}}
Servings Apply
Reset to default
{{subrecipe.title}}
Ingredients
{{ingredient.user_title}}{{ingredient.user_title || ingredient.name}}{{ingredient.amount}}{{ingredient.unit.name}}
Method
Step {{$index + 1}}
{{method.desc}}
Allergens
{{allergen.name}}

{{recipe.title}}

Serving Size: {{recipe.portion.unit !== \\'quantity\\' ? (recipe.portion.size + \\' \\' + recipe.portion.unit) : 1}}.
Calories: {{recipe.nutrition_report.calories | number : 0}}
{{nutrition.key}}: {{recipe.nutrition_report[nutrition.value] | number : 1}} {{nutrition.unit}}
{{category.key}}: {{recipe.nutrition_report[category.value] | number : 1}} {{category.unit}}
{{nutrition.key}}: {{recipe.nutrition_report[nutrition.value] | number : 1}} {{nutrition.unit}}
Ingredients:
{{ getIngredientsForPrint(subrecipe.ingredients)}}
Allergens (Our kitchen is not an allergen-free environment):
{{allergen.name}}
\");\n$templateCache.put(\"app/components/menu/create-menu/create-menu.html\",\"

{{menuData ? \\'Edit\\' : \\'Create\\'}} Menu

{{tab.name}}
1\\\" style=\\\"margin-top: 8px;float: right\\\">
{{recipe.title}}
Add Recipe
Add New Station
Select Week
Schedule of Meal Edit Schedule
{{station.name}}
{{station.start + \\' - \\' + station.end}}

Assigned to Add Chefs
{{selectedChef.first_name + \\' \\' + selectedChef.last_name}}
\");\n$templateCache.put(\"app/components/modal/templates/catalogue.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/confirm.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/edit-ingredient.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/edit-nutritions.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/err.tpl.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/import.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/local-chefs.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/logout.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/schedule.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/user-create.tpl.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/user-edit.tpl.html\",\"\");\n$templateCache.put(\"app/components/modal/templates/user-remove.tpl.html\",\"\");\n$templateCache.put(\"app/components/popover/templates/download.html\",\"\");}]);"],"sourceRoot":"/source/"}