{"version":3,"sources":["../../../../app/script/model/categoriesCatalog.js","../../../../app/script/model/measurementsCatalog.js","../../../../app/script/wrapper.js","../../../../app/script/app.js","../../../../app/script/interceptorConfig.js","../../../../app/script/securityConfig.js","../../../../app/script/translateConfig.js","../../../../app/script/routeConfig.js","../../../../app/script/facebookConfig.js","../../../../app/script/prodConfig.js","../../../../app/script/controller/deleteHistoryItemController.js","../../../../app/script/controller/deleteProductListController.js","../../../../app/script/controller/editProductListItemController.js","../../../../app/script/controller/homepageController.js","../../../../app/script/controller/loginController.js","../../../../app/script/controller/newProductListController.js","../../../../app/script/controller/shareListController.js","../../../../app/script/controller/shoppingListController.js","../../../../app/script/controller/userProductsController.js","../../../../app/script/controller/userSettingsController.js","../../../../app/script/directive/cancelBtn.js","../../../../app/script/directive/focus.js","../../../../app/script/directive/footer.js","../../../../app/script/directive/notification.js","../../../../app/script/directive/okBtn.js","../../../../app/script/directive/pmAlert.js","../../../../app/script/directive/scroll.js","../../../../app/script/directive/selectOnClick.js","../../../../app/script/directive/googleSignIn.js","../../../../app/script/directive/homepageAdvantages.js","../../../../app/script/directive/homepageDescription.js","../../../../app/script/directive/homepageDownload.js","../../../../app/script/directive/homepageFooter.js","../../../../app/script/directive/homepageHeader.js","../../../../app/script/directive/homepageIdea.js","../../../../app/script/directive/homepageMain.js","../../../../app/script/component/header.js","../../../../app/script/component/productList.js","../../../../app/script/component/productListSelect.js","../../../../app/script/component/productListSelectItem.js","../../../../app/script/component/productSearch.js","../../../../app/script/component/productListItem.js","../../../../app/script/component/productListItems.js","../../../../app/script/component/historyList.js","../../../../app/script/component/historyListItem.js","../../../../app/script/component/historySortPanel.js","../../../../app/script/component/userProductEditRow.js","../../../../app/script/component/categoryDropdown.js","../../../../app/script/component/dropdown.js","../../../../app/script/service/broadcastingService.js","../../../../app/script/service/dialogService.js","../../../../app/script/service/loginService.js","../../../../app/script/service/measurementService.js","../../../../app/script/service/motivationPhraseService.js","../../../../app/script/service/navigationService.js","../../../../app/script/service/notificationService.js","../../../../app/script/service/productCategoryService.js","../../../../app/script/service/productListItemService.js","../../../../app/script/service/productListService.js","../../../../app/script/service/productService.js","../../../../app/script/service/purchaseHistoryEntryService.js","../../../../app/script/service/sessionService.js","../../../../app/script/service/userService.js","../../../../app/script/service/userSettingsService.js","../../../../app/script/service/webSocketService.js","../../../../app/script/util/listUtil.js"],"names":["CategoriesCatalog","categoriesList","measurementsCatalog","getImgId","pmId","getIconById","findMatchingCategoryById","categories","category","i","length","c","upperCategoryIds","this","defaultCategory","upperCategories","processData","data","constructor","Array","forEach","icon","push","indexOf","getColorById","getById","defaultColor","getUpperCategoryById","getUpperCategory","upperCategory","parentCategory","getMeasurements","containsMeasurement","a","obj","some","e","shortcut","measurements","emptyMeasurement","unshift","measurement","name","MeasurementsCatalog","measurementsList","comment","plural","isEmptyMeasurement","find","WrapperController","$scope","isNotIE","test","navigator","userAgent","toLowerCase","dependencies","angular","module","run","$rootScope","$location","$window","unregisterViewContentLoaded","$on","ga","page","url","controller","$inject","$anchorScroll","unregisterLocationChangeSuccess","HttpInterceptor","$q","$injector","request","config","headers","Session","get","token","responseError","rejection","status","method","path","error","reject","factory","$httpProvider","interceptors","securityConfig","defaults","withCredentials","translateConfig","$translateProvider","useStaticFilesLoader","prefix","suffix","uniformLanguageTag","registerAvailableLanguageKeys","en-US","en-DE","en-UK","en-GB","en-au","en-ca","de-DE","de-CH","de-at","de-lu","de-li","ru_RU","determinePreferredLanguage","fallbackLanguage","useSanitizeValueStrategy","useCookieStorage","routeConfig","$locationProvider","$routeProvider","html5Mode","when","templateUrl","resolveRedirectTo","init","resolve","Measurements","MeasurementService","Categories","ProductCategoryService","Auth","LoginService","isAuthenticated","otherwise","redirectTo","then","facebookConfig","ezfbProvider","setInitParams","appId","xfbml","version","$compileProvider","debugInfoEnabled","commentDirectivesEnabled","cssClassDirectivesEnabled","DeleteHistoryItemController","$log","purchaseHistoryEntryService","confirmDelete","deleteByPmId","purchase","closeThisDialog","response","cancel","DeleteProductListController","productListService","listToDelete","EditProductListItemController","categoriesCatalog","dialogTitle","draftListItem","ctrl","apply","onMeasurementSelect","measurementPmId","select","categoryPmId","categoryName","HomepageController","$http","$httpParamSerializerJQLike","$routeParams","loginService","userService","navigationService","notificationService","dialogService","session","$timeout","$translate","setControllerScope","showWarn","passwordchanged","showSuccess","showError","credentials","email","password","Content-Type","scrollToPosition","hash","openForgotPasswordDialog","mode","dialog","openLoginDialog","closePromise","dialogOpened","$root","onPasswordReseted","openRegistrationDialog","onRegistrationCompleted","onLoggedIn","loginFailed","loginInProgress","navigateToShoppingList","onLoginFailed","submit","login","create","fbLogin","socialLogin","googleSignIn","post","germanFlag","englishFlag","russianFlag","selectedLang","img","languageOptions","id","selectedLanguage","localStorage","getItem","use","language","includes","setItem","enableListItems","enableList","languageSelection","LoginController","expired","addWatch","success","res","changeMode","resetNotification","resetPassword","warn","NewProductListController","showNotification","notificationClass","notificationMsg","listName","ShareListController","joinListUrl","activeList","share","successCallback","errorCallback","absUrl","replace","ShoppingListController","userSettingsService","WebSocketService","dialogState","opened","dialogClosing","$onInit","$watch","newVal","currentUserEmail","join","joinProductList","getSettings","connectWebSocket","loginExpired","search","$emit","reloadMeasurementsAndCategories","all","responses","unbindTranslate","unbindOpen","unbindClose","closeWebSocket","getDialogState","itemToInsert","insertListItem","item","removedProduct","removeProduct","product","historyItemToRemove","removeHistoryItem","errorMessage","openAlertDialog","UserProductsController","productService","broadcastingService","loadProducts","products","getOwn","result","color","log","setName","update","sendBroadcastMessage","broadcastMessages","listItemChanged","setCategory","deleteProduct","idx","splice","hoverIn","hoverEdit","hoverOut","UserSettingsController","userNewInfo","currentPassword","newPassword","repeatPassword","currentLanguageText","getLanguageKey","languages","LANGUAGE_EN","LANGUAGE_DE","LANGUAGE_RU","showBought","SHOW_BOUGHT_PREFIX","settings","userSettings","showBoughtValue","showBoughtItemsInTheList","TRANSLATION_KEY_PREFIX","getLanguage","key","showPasswordFields","showPassword","closePasswordFields","showAccountDeleteFields","showAccountDelete","closeAccountDeleteFields","user","firstName","lastName","changePassword","deleteUser","destroy","logout","navigateToAccountDeleted","passwordValidationError","isUndefined","newPasswordValidationError","showBoughtSettings","onLanguageChanged","onShowBoughtValueChanged","value","newValue","repeatPasswordValidationError","cancelBtn","restrict","scope","directive","focusOn","$parse","element","attrs","model","focus","footer","NotificationFn","notifclass","notifmsg","notifshow","okBtn","pmAlert","type","scrollFn","scroll","link","bind","selectOnClick","on","getSelection","toString","setSelectionRange","postLink","elem","auth2","gapiPromise","gapi","load","CLIENT_ID","cookiepolicy","ID_TOKEN_PARAM","attachClickHandler","googleUser","getAuthResponse","getUserLanguage","$document","$el","rect","getBoundingClientRect","div","document","querySelector","top","bottom","style","position","right","hideOnTop","description","querySelectorAll","header","descriptionTop","visibility","HeaderController","onSettingSelect","setting","click","openProductsDialog","openSettingsDialog","separator","navigateToHome","component","bindings","ProductListController","MotivationPhraseService","ProductListService","ProductListItemService","UserSettingsService","ListUtil","loadProductListItemsFromServer","productList","Object","keys","getProductListItems","syncProductItems","errorHandler","message","serverItems","localItems","items","sync","itemToId","updateItem","sortFn","insertFn","localItem","productPmId","serverItem","copy","localList","serverList","index","getIndexOfItemWithProductPmId","swap","processed","newItem","newItemIndex","array","oldIndex","newIndex","k","undefined","tmp","itemIndex","findIndex","removedItem","updateItemsCount","onDeleteProduct","itemsCount","filter","el","state","toUpperCase","showMotivationPhrase","motivationPhrase","getRandom","phrase","errorHandlerForChildren","unbindProductCreate","unbindProductListUpdate","event","unbindProductListItemUpdate","found","amount","unbindDeleteProduct","$onDestroy","$watchCollection","$onChanges","changes","mail","currentValue","equals","setActiveList","list","updateActiveListName","newName","tmpList","itemObj","createProductListItem","onAddProduct","removeListItem","ProductListSelectController","DialogService","loadProductLists","productLists","enrichList","active","errorHander","events","unbind","noop","fn","ev","users","listIndex","shareProductList","openShareListDialog","deleteProductList","openDeleteListDialog","addNewProductList","addProductList","updateListName","activateList","ProductListSelectItemController","shareList","deleteList","activateProductList","selectActiveList","listsSize","ProductSearchController","ProductService","createProduct","dialogValue","productName","selectProduct","resolves","selectSearchResult","localSearch","searchWord","searchTerm","split","isArray","searchResults","remoteSearch","hashtags","hashTags","hashTagArray","productArray","ht","isHashtag","productPromises","map","productCategoryPromise","userDefined","getProductById","productWithCategory","Math","floor","productCategory","isDisabled","isProduct","concat","addNewProductListItem","newProductListItem","searchProducts","charAt","childHashtags","triggerHandler","insertSelectedItem","ProductListItemController","editItem","onEdit","deleteItem","onDelete","showItemAmount","ProductListItemsController","updateProduct","updateProductListItem","editProductListItem","isDefined","internalState","removeItem","buyItem","HistoryListController","PurchaseHistoryEntryService","loadPurchaseHistory","waitForSorter","promise","syncPurchases","historyList","purchaseHistory","purchaseHistoryFromServer","count","sortedList","activeSorter","purchaseFromServer","categoryColor","updateHistoryListItemOrders","historyItem","historyListCopy","slice","sort","b","order","sortedHistoryList","j","opacity","getOpacity","hidden","minOpacity","historyListItemsSelector","historyListItemSelector","fullHeight","prop","itemHeight","totalPossibleElements","abs","totalVisibleElements","opacityStep","scrollPos","showHistory","defer","arg","stopPropagation","isFirstChange","itemToRemove","showHidePurchases","addItemToProductList","executeSort","setOpacity","$digest","HistoryListItemController","addProductListItem","historyListItem","deleteHistoryListItem","openDeleteHistoryItemDialog","SortPanelController","initSortOptions","catalog","sortOptions","purchasesToSort","sortByCategory","imageName","sortByCount","sortByName","sortList","sortOption","arrayToSort","localeCompare","sortByOrder","parseInt","countDiff","sortCategoryPmId","restPurchases","categoryPurchases","UserProductEditRowController","setProductName","setCategoryOfProduct","setProductCategory","CategoryDropDownController","onSelect","selectedCategory","disabled","onItemSelect","BroadcastingService","args","$broadcast","addBroadcastListener","callback","BroadcastMessages","updateSession","categoriesArrived","listsChanged","connectionLost","service","ngDialog","open","template","$new","controllerAs","copyItem","className","itemToDelete","alertType","alertMessage","getOpenDialogs","ezfb","userResult","userSettingsResult","providerId","$ready","socialLogout","window","googleLogout","getAuthInstance","signOut","getLoginStatus","authResponse","accessToken","deferred","$","Deferred","NavigationService","navigateTo","LOCATION_ALREADY_THERE","sharingListToken","LOCATION_SET","navigateToPasswordForget","navigateBack","history","back","_navigateTo","NotificationService","controllerScope","info","msg","show","notifClass","notifMsg","checkScope","parameter","showInfo","updated","Date","now","put","activeListId","created","_delete","getActiveList","lists","pop","shouldNotify","productListDto","returnWebDto","webItems","delete","baseUri","encodeURI","getUserDefined","delete_","historySize","random","substr","UserService","createDefaults","proposedLanguage","oldPassword","encodeURIComponent","activeProductListId","$websocket","s","l","location","protocol","host","onCreate","subject","onUpdate","dataStream","close","self","send","toJson","os","onMessage","fromJson","onOpen","onClose","readyState","onError","listUtil","oldList","newList","oldItem"],"mappings":"AACA,QAASA,mBAAkBC,eAAgBC,qBAC1C,YASG,SAASC,UAAUC,MACf,MAAOA,MAAO,IAGlB,QAASC,aAAaD,MAClB,MAAO,YAAcD,SAASC,MAAQ,mBAgD1C,QAASE,0BAAyBC,WAAYH,MAG1C,IAAK,GAFDI,UAAW,KAENC,EAAI,EAAGA,EAAIF,WAAWG,OAAQD,IAAK,CACxC,GAAIE,GAAIJ,WAAWE,EACnB,IAAGE,EAAEP,OAASA,KAAM,CAChBI,SAAWG,CACX,QAIR,MAAOH,UAvEX,GAAII,mBAAoB,IAAQ,IAAQ,IAAQ,IAAQ,IAAQ,IAAQ,IAExEC,MAAKN,cACLM,KAAKC,mBACLD,KAAKE,mBACLF,KAAKX,oBAAsBA,oBAU3BW,KAAKG,YAAc,SAAUC,MACzB,GAAIV,eACAQ,kBACCE,OAAQA,KAAKC,cAAgBC,QAGlCF,KAAKG,QAAQ,SAAUZ,UACnBA,SAASa,KAAOhB,YAAYG,SAASJ,MAErCG,WAAWe,KAAKd,UACZI,iBAAiBW,QAAQf,SAASJ,UAClCW,gBAAgBO,KAAKd,YAG7BK,KAAKN,WAAaA,WAClBM,KAAKE,gBAAkBA,gBACvBF,KAAKC,gBAAkBD,KAAKE,gBAAgB,KAGhDF,KAAKG,YAAYf,gBAEjBY,KAAKR,YAAcA,YAEnBQ,KAAKW,aAAe,SAAUpB,MAC1B,GAAII,UAAWK,KAAKY,QAAQrB,KAC5B,OAAOI,UAAWA,SAASkB,aAAe,eAG9Cb,KAAKY,QAAU,SAASrB,MACpB,MAAKS,MAAKN,YAAcM,KAAKN,gBAItBD,yBAAyBO,KAAKN,WAAYH,MAHtC,MA6BfS,KAAKc,qBAAuB,SAAUvB,MAClC,GAAII,UAAWK,KAAKY,QAAQrB,KAC5B,OAAOS,MAAKe,iBAAiBpB,WAGjCK,KAAKe,iBAAmB,SAAUpB,UAC9B,GAAIqB,eAAgBrB,QACpB,KAAKqB,cACD,MAAO,KAEX,MAAOA,cAAcC,gBAEjB,GADAD,cAAgBhB,KAAKY,QAAQI,cAAcC,iBACtCD,cACD,MAAO,KAGf,OAAOA,gBAGXhB,KAAKkB,gBAAkB,SAAUvB,UAC7B,QAASwB,qBAAoBC,EAAGC,KAC5B,MAAOD,GAAEE,KAAK,SAASC,GAAK,MAAOA,GAAEC,WAAaH,IAAIG,WAK1D,GAAIC,cAAgB9B,UAA6C,IAAjCA,SAAS8B,aAAa5B,OAAkDF,SAAS8B,aAA5CpC,oBAAoBoC,YAUzF,OATKN,qBAAoBM,aAAcpC,oBAAoBqC,mBACvDD,aAAaE,QAAQtC,oBAAoBqC,kBAI7CD,aAAalB,QAAQ,SAASqB,aAC1BA,YAAYC,KAAOD,YAAYJ,WAG5BC,cCjHf,QAASK,qBAAoBC,kBAC5B,YAEG/B,MAAKyB,gBACLzB,KAAK0B,oBAEL1B,KAAKG,YAAc,SAAUC,MACzB,GAAIqB,gBACCrB,OAAQA,KAAKC,cAAgBC,QAIlCN,KAAK0B,kBACDM,QAAS,GACTH,KAAM,IACNI,OAAQ,IACRT,SAAU,WAEdC,aAAahB,KAAKT,KAAK0B,kBAEvBtB,KAAKG,QAAQ,SAAUqB,aACnBA,YAAYC,KAAOD,YAAYJ,SAC/BC,aAAahB,KAAKmB,eAEtB5B,KAAKyB,aAAeA,eAGxBzB,KAAKG,YAAY4B,kBAEjB/B,KAAKkC,mBAAqB,SAAUN,aAChC,OAAKA,aAGEA,cAAgB5B,KAAK0B,kBAGhC1B,KAAKY,QAAU,SAAUrB,MACrB,GAAIqC,aAAc5B,KAAKyB,aAAaU,KAAK,SAAUP,aAC/C,MAAOA,aAAYrC,OAASA,MAEhC,OAAOqC,aAAcA,YAAc5B,KAAK0B,mBCzChD,WACI,YAuBA,SAASU,mBAAiBC,QACtBA,OAAOC,SAAU,qBAAsBC,KAAKC,UAAUC,UAAUC,eAtBvE,GAAIC,eACG,YACA,OAGJC,SACEC,OAAM,UAAYF,cACrBG,IAAI,SAASC,WAAaC,UAAWC,SAErC,GAAIC,6BAA8BH,WAAUI,IAAI,qBAAuB,WACtEF,QAAQG,GAAE,OAAS,YAAaC,KAAML,UAAUM,SAGjDP,YAAUI,IAAI,WAAa,WAC1BD,kCAGKK,WAAU,oBAAsBnB,mBAErCA,kBAAiBoB,SAAW,aCtBhC,WACI,YAEH,IAAIb,eACG,YACA,yBACA,UACA,cACA,WACA,YACA,UACA,eACA,WAGJC,SACEC,OAAM,YAAcF,cACvBG,IAAI,SAASC,WAAaC,UAAWC,QAASQ,eAE9C,GAAIC,iCAAkCX,WAAUI,IAAI,yBAA2B,WAC9EM,iBAGDV,YAAUI,IAAI,WAAa,WAC1BO,yCCxBJ,WACC,YAWG,SAASC,iBAAeC,GAAKb,WAAYC,UAAWa,WAChD,OACIC,QAAW,SAASC,QAChB,GAAIA,OAAOT,IAAI5C,QAAO,aAAiB,CAC9BqD,OAAOC,UACRD,OAAOC,WAGX,IAAIC,SAAUJ,UAAUK,IAAG,UAE3BH,QAAOC,QAAQG,MACXJ,OAAOC,QAAQG,MACXJ,OAAOC,QAAQG,MACfF,QAAQE,MAGpB,MAAOJ,SAGXK,cAAiB,SAAUC,WACvB,GAAIC,QAASD,UAAUC,OACnBP,OAASM,UAAUN,OACnBQ,OAASR,OAAOQ,OAChBjB,IAAMS,OAAOT,GAQjB,OANyB,MAAtBN,UAAWwB,QAA6B,MAAXF,OAC5BtB,UAAUwB,KAAI,iBAEdzB,WAAW0B,MAAQF,OAAS,OAASjB,IAAM,uBAAyBgB,OAGjEV,GAAGc,OAAOL,aAxChCzB,QACEC,OAAM,aACA8B,QAAO,kBAAoBhB,iBAC3BI,QAAM,gBAAmB,SAASa,eAC/BA,cAAcC,aAAapE,KAAI,sBAGvCkD,gBAAeH,SAAW,KAAO,aAAc,YAAa,gBCVhE,WACI,YAQA,SAASsB,gBAAcF,eACnBA,cAAcG,SAASC,iBAAkB,EAP7CpC,QACKC,OAAM,aACNkB,OAAOe,gBAEZA,eAActB,SAAW,oBCP7B,WACI,YAMA,SAASyB,iBAAeC,oBACpBA,mBACKC,sBACGC,OAAQ,aACRC,OAAQ,UAEXC,mBAAkB,SAClBC,+BAA6B,KAAQ,KAAM,OACxCC,QAAS,KACTC,QAAS,KACTC,QAAS,KACTC,QAAS,KACTC,QAAS,KACTC,QAAS,KAETC,QAAS,KACTC,QAAS,KACTC,QAAS,KACTC,QAAS,KACTC,QAAS,KAETC,MAAS,OAEZC,6BACAC,iBAAgB,MAChBC,yBAAwB,oBACxBC,mBA9BT3D,QACKC,OAAM,aACNkB,OAAOkB,oBCLhB,WACI,YAMA,SAASuB,aAAWC,kBAAoBC,gBACpCD,kBAAkBE,WAAU,GAC5BD,eACKE,KAAI,KACDC,YAAa,iCACbtD,WAAY,qBACZuD,kBAAmBC,OAEtBH,KAAI,iBACDC,YAAa,qCACbtD,WAAY,yBACZyD,SACIC,cAAc,qBAAuB,SAASC,oBAC1C,MAAOA,oBAAmBhD,QAE9BiD,YAAY,yBAA2B,SAASC,wBAC5C,MAAOA,wBAAuBlD,QAElCmD,MAAM,eAAiB,SAASC,cAC5B,MAAOA,cAAaC,uBAI/BX,KAAI,iBACDC,YAAa,iCACbtD,WAAY,uBAEfqD,KAAI,YACDC,YAAa,gCACbtD,WAAY,uBAEfqD,KAAI,UACDC,YAAa,8BACbtD,WAAY,uBAEfqD,KAAI,YACDC,YAAa,gCACbtD,WAAY,uBAEfqD,KAAI,SACDC,YAAa,mCACbtD,WAAY,uBAEfqD,KAAI,mBACDC,YAAa,iCACbtD,WAAY,uBAEfiE,WACGC,WAAY,MAMxB,QAASV,MAAKO,cACV,MAAOA,cACFC,kBACAG,KAAK,WAAc,MAAO,kBAFxBJ,SAGI,cA9Df1E,QACKC,OAAM,aACNkB,OAAOyC,aAsDZO,KAAIvD,SAAW,mBC3DnB,WACI,YAQA,SAASmE,gBAAeC,cACpBA,aAAaC,eACTC,MAAO,kBACPC,OAAO,EACPC,QAAS,SAVjBpF,QACKC,OAAM,WACNkB,OAAO4D,gBAEZA,eAAcnE,SAAW,mBCP7B,WACI,YACAZ,SACKC,OAAM,WACNkB,QAAM,mBAAsB,SAASkE,kBAClCA,iBAAiBC,kBAAiB,GAClCD,iBAAiBE,0BAAyB,GAC1CF,iBAAiBG,2BAA0B,SCPvD,WACI,YAQA,SAASC,6BAA2BhG,OAASiG,KAAMC,6BAK/C,QAASC,iBAELD,4BAA4BE,aAAYpG,OAAQqG,SAAU,WAElDrG,OAAOsG,mBAEX,SAAUC,UACNN,KAAK7D,MAAK,uBAA0BpC,OAAOqG,SAAW,uBAAyBE,YAI3F,QAASC,UACLxG,OAAOsG,kBAfXtG,OAAOmG,cAAgBA,cACvBnG,OAAOwG,OAASA,OATpBjG,QACKC,OAAM,aACNU,WAAU,8BAAgC8E,6BAE/CA,4BAA2B7E,SAAW,SAAW,OAAQ,kCCP7D,WACI,YAQA,SAASsF,6BAA2BzG,OAASiG,KAAMS,oBAI/C,QAASP,iBACLO,mBAAAA,UAAyB1G,OAAQ2G,aAAc3G,OAAOsG,gBAAiB,SAAUC,UAC7EN,KAAK7D,MAAK,sBAAyBpC,OAAO2G,aAAe,wBAA0BJ,YAI3F,QAASC,UACLxG,OAAOsG,kBAVXtG,OAAOmG,cAAgBA,cACvBnG,OAAOwG,OAASA,OARpBjG,QACKC,OAAM,aACNU,WAAU,8BAAgCuF,6BAE/CA,4BAA2BtF,SAAW,SAAW,OAAQ,yBCP7D,WACI,YAMA,SAASyF,+BAA6B5G,OAAS6G,kBAAmBtH,YAAauH,YAAaC,eACxF,GAAIC,MAAOrJ,IAEXqJ,MAAKF,YAAcA,YACnBE,KAAKH,kBAAoBA,kBACzBG,KAAKzH,YAAcA,YACnByH,KAAKD,cAAgBA,cACrBC,KAAKC,MAAQ,WACTjH,OAAOsG,gBAAgBS,gBAE3BC,KAAKR,OAASxG,OAAOsG,gBAErBU,KAAKE,oBAAsB,SAAU3H,aACjCyH,KAAKzH,YAAcA,YACnBwH,cAAcxH,YAAcA,YAAYrC,KACxC6J,cAAcI,gBAAkB5H,YAAYrC,MAGhD8J,KAAKI,OAAS,SAAU9J,UACpByJ,cAAczJ,SAAWA,SACzByJ,cAAcM,aAAe/J,SAASJ,KACtC6J,cAAcO,aAAehK,SAASkC,KACtCuH,cAAcpI,cAAgBrB,SAC9ByJ,cAAcvI,aAAewI,KAAKH,kBAAkBvI,aAAahB,SAASJ,OA3BlFqD,QACKC,OAAM,aACNU,WAAU,gCAAkC0F,kCCLrD,WACI,YASA,SAASW,oBAAkBvH,OAASwH,MAAOC,2BAA4B9G,UAAW+G,aAAcC,aAAcC,YAAaC,kBAC/FC,oBAAqBC,cAAeC,QAASC,SAAU7G,cAAe8G,YAC9FJ,oBAAoBK,mBAAkBnI,QAEb,kBAAtBW,UAAWwB,OACV2F,oBAAoBM,SAAQ,mBACY,SAAlCV,aAAcW,gBACpBP,oBAAoBQ,YAAW,oCACS,UAAlCZ,aAAcW,gBACpBP,oBAAoBS,UAAS,wCACD,oBAAtB5H,UAAWwB,QACjB2F,oBAAoBQ,YAAW,qDAGnCtI,OAAOwI,aACHC,MAAO,GACPC,SAAU,GAEjB,IAAIhH,SACHC,SACCgH,eAAgB,oDAGf3I,QAAO4I,iBAAmB,SAASC,MACjCzH,cAAcyH,OAEhB7I,OAAO8I,yBAA2B,WAC9B9I,OAAO+I,KAAO,iBACd,IAAIC,QAAUjB,cAAckB,gBAAejJ,OAC3CgJ,QAAOE,aAAa7D,KAAK,WACrBrF,OAAOmJ,cAAe,EACtBnJ,OAAOwI,YAAYC,MAAQT,QAAQS,MACjCzI,OAAOoJ,MAAOC,oBACZvB,oBAAoBK,mBAAkBnI,QACtC8H,oBAAoBQ,YAAW,+CAK3CtI,OAAOsJ,uBAAyB,WAC5BtJ,OAAO+I,KAAO,cACd,IAAIC,QAASjB,cAAckB,gBAAejJ,OAC1CgJ,QAAOE,aAAa7D,KAAK,WACrBrF,OAAOmJ,cAAe,EACtBnJ,OAAOwI,YAAYC,MAAQT,QAAQS,MACjCzI,OAAOoJ,MAAOG,0BACZzB,oBAAoBK,mBAAkBnI,QACtC8H,oBAAoBQ,YAAW,yDAI3CtI,OAAOwJ,WAAa,WAChBxJ,OAAOyJ,aAAc,EACrBzJ,OAAO0J,iBAAkB,EACzB7B,kBAAkB8B,0BAGzB3J,OAAO4J,cAAgB,WAChB5J,OAAOyJ,aAAc,EACrBzJ,OAAO0J,iBAAkB,EAEzB5B,oBAAoBS,UAAS,6BAGjCvI,OAAO6J,OAAS,SAAUrB,aACtBxI,OAAO0J,iBAAkB,EACzB/B,aAAamC,MAAMtB,aACdnD,KAAK,SAAUoD,OACZT,QAAQ+B,OAAOtB,OAClBzI,OAAOwJ,cACLxJ,OAAO4J,gBAGlB5J,OAAOgK,QAAU,WACbhK,OAAO0J,iBAAkB,EACzB/B,aACKsC,YAAW,YACX5E,KAAKsC,aAAazC,iBAClBG,KAAIrF,OAAQwJ,YAHjB7B,SAIU3H,OAAQ4J,gBAEtB5J,OAAOkK,aAAe,SAASnM,MAC9ByJ,MAAM2C,KAAI,iBAAmB1C,2BAA2B1J,MAAO2D,QAC7D2D,KAAKsC,aAAazC,iBAClBG,KAAIrF,OAAQwJ,YAFdhC,SAGOxH,OAAQ4J,gBAEhB5J,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBtK,OAAOuK,cAAgB/K,KAAI,GAAKgL,IAAG,IACnCxK,OAAOyK,kBACFC,GAAE,KAAOlL,KAAM,kBAAmBgL,IAAK,eACvCE,GAAE,KAAMlL,KAAM,kBAAmBgL,IAAK,eACtCE,GAAE,KAAMlL,KAAM,kBAAmBgL,IAAK,eAG3CxK,OAAO2K,iBAAmB,WAClBC,aAAaC,QAAO,SA0BgB,OAAjCD,aAAaC,QAAO,UACnB7K,OAAOuK,aAAevK,OAAOyK,gBAAgB,GAC7CzK,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBpC,WAAW4C,IAAG,OAEkB,OAAjCF,aAAaC,QAAO,UACnB7K,OAAOuK,aAAevK,OAAOyK,gBAAgB,GAC7CzK,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBpC,WAAW4C,IAAG,OAEkB,OAAjCF,aAAaC,QAAO,UACnB7K,OAAOuK,aAAevK,OAAOyK,gBAAgB,GAC7CzK,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBpC,WAAW4C,IAAG,QA5Cf3K,UAAU4K,SAASC,SAAQ,OAC1BJ,aAAaK,QAAO,OAAM,MAC1BjL,OAAOuK,aAAevK,OAAOyK,gBAAgB,GAC7CzK,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBpC,WAAW4C,IAAG,OAEV3K,UAAU4K,SAASC,SAAQ,OAC/BJ,aAAaK,QAAO,OAAM,MAC1BjL,OAAOuK,aAAevK,OAAOyK,gBAAgB,GAC7CzK,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBpC,WAAW4C,IAAG,QAGdF,aAAaK,QAAO,OAAM,MAC1BjL,OAAOuK,aAAevK,OAAOyK,gBAAgB,GAC7CzK,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EACrBpC,WAAW4C,IAAG,QA0B1B9K,OAAO2K,mBACP3K,OAAOkL,iBAAkB,EACzBlL,OAAOmL,WAAa,WAChBnL,OAAOkL,iBAAkB,GAE7BlL,OAAOoL,kBAAoB,SAASL,UAIhC,OAHA/K,OAAOkL,iBAAkB,EACzBN,aAAaK,QAAO,OAASF,SAASL,IACtC1K,OAAOuK,aAAeQ,SACdA,SAASL,IACb,IAAK,KACDE,aAAaK,QAAO,OAAS,MAC7BjL,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,CACrB,MACJ,KAAK,KACDM,aAAaK,QAAO,OAAM,MAC1BjL,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,CACrB,MACJ,KAAK,KACDM,aAAaK,QAAO,OAAM,MAC1BjL,OAAOoK,YAAa,EACpBpK,OAAOqK,aAAc,EACrBrK,OAAOsK,aAAc,EAI7BpC,WAAW4C,IAAIC,SAASL,KAxLhCnK,QACKC,OAAM,aACNU,WAAU,qBAAuBqG,oBAEtCA,mBAAkBpG,SAAW,SAAW,QAAS,6BAA8B,YAAa,eAAgB,eAAgB,cAAe,oBACvI,sBAAuB,gBAAc,UAAU,WAAc,gBAAiB,iBCRtF,WACI,YAiBA,SAASkK,iBACR3K,WACAV,OACAkI,WACAjC,KACA0B,aACAC,YACGC,kBACAC,qBACAA,oBAAoBK,mBAAkBnI,QAGnCA,OAAQsL,SACPxD,oBAAoBS,UAAS,uBAGjCT,oBAAoByD,SAAQ,qBAC5BzD,oBAAoByD,SAAQ,uBAE5B,IAAIC,SAAU,WACV5D,YAAY/F,MAAMwD,KAAK,SAAUoG,KAC7BvD,WAAW4C,IAAIW,IAAI1N,KAAKgN,YAG5B/K,OAAOsG,kBACPuB,kBAAkB8B,yBAItB3J,QAAO+I,KAAO/I,OAAO+I,MAAQ,QAC7B/I,OAAOwI,aACHC,MAAO,GACPC,SAAU,IAGd1I,OAAO0L,WAAa,WACI,UAAjB1L,OAAQ+I,MACP/I,OAAO+I,KAAO,kBACdjB,oBAAoB6D,qBAEpB3L,OAAO+I,KAAO,SAUtB/I,OAAO6J,OAAS,SAAUrB,aACF,UAAjBxI,OAAQ+I,KACPpB,aAAamC,MAAMtB,aACdnD,KAAK,WACFmG,WACD,WACC1D,oBAAoBS,UAAS,8BAEd,iBAAjBvI,OAAQ+I,KACdnB,YAAYmC,OAAM/J,OAAQwI,YAAYC,MAAO,WACzCzI,OAAMoJ,MAAOG,yBAA0B,EACvCvJ,OAAOsG,mBACR,SAASC,UACRvG,OAAMoJ,MAAOG,yBAA0B,EACf,MAApBhD,SAAStE,OACT6F,oBAAoBS,UAAS,sEAE7BT,oBAAoBS,UAAS,qDAGf,oBAAjBvI,OAAQ+I,KACbnB,YAAYgE,cAAa5L,OAAQwI,YAAYC,MAAO,WAChDzI,OAAMoJ,MAAOC,mBAAoB,EACjCrJ,OAAOsG,mBACR,WACCwB,oBAAoBS,UAAS,2CAGjCtC,KAAK4F,KAAI,gBAAmB7L,OAAO+I,OAO3C/I,OAAOgK,QAAU,WACbrC,aACKsC,YAAW,YACX5E,KAAKsC,aAAazC,iBAClBG,KAAKmG,SAHV7D,SAIW,WACHG,oBAAoBS,UAAS,+BAIzCvI,OAAOwG,OAASxG,OAAOsG,gBA9G3B/F,QACKC,OAAM,aACNU,WAAU,kBAAoBmK,iBAEnCA,gBAAelK,SACd,aACA,SACA,aACA,OACA,eACA,cACG,oBACA,sBACA,cChBR,WACI,YAQA,SAAS2K,0BAAwB7F,KAAOjG,OAAQ0G,oBAC5C1G,OAAOwG,OAASxG,OAAOsG,gBACvBtG,OAAO+L,kBAAmB,EAC1B/L,OAAOgM,kBAAoB,eAC3BhM,OAAOiM,gBAAkB,mCAEzBjM,OAAOiH,MAAQ,SAASiF,UACpBxF,mBACKqD,OAAOmC,UACP7G,KAAIrF,OAAQwG,QAFjBE,SAGW,SAAUH,UACdvG,OAAO+L,kBAAmB,EAC1B9F,KAAK7D,MAAMmE,aAlB1BhG,QACKC,OAAM,aACNU,WAAU,2BAA6B4K,0BAE5CA,yBAAwB3K,SAAW,OAAS,SAAU,yBCP1D,WACI,YAQA,SAASgL,qBAAmBnM,OAASW,UAAWmH,oBAAqBpB,oBAejE,QAAShC,QACd1E,OAAOoM,YAAc,GACrBpM,OAAOkM,SAAWlM,OAAOqM,WAAW7M,KAG/B,QAASgH,UACLxG,OAAOsG,kBApBX5B,OAEA1E,OAAOwG,OAASA,OAEhBsB,oBAAoBK,mBAAkBnI,QACtC8H,oBAAoB6D,oBAE1B3L,OAAMc,IAAI,kBAAoB,WACpB4F,mBACK4F,MAAKtM,OAAQqM,WAAW3B,IACxBrF,KAAKkH,iBAFV7F,SAGW8F,gBAYrB,IAAID,iBAAkB,SAAUhG,UAC/BvG,OAAOoM,YAAczL,UAAU8L,SAASC,QAAO/L,UAAWM,MAAO,IACpD,sBAAwBsF,SAASxI,KAAK+D,OAGhD0K,cAAgB,SAAUjG,UAC7BuB,oBAAoBS,UAAS,iCAAmChC,WApC/DhG,QACKC,OAAM,aACNU,WAAU,sBAAwBiL,qBAEvCA,oBAAmBhL,SAAW,SAAW,YAAa,sBAAuB,yBCNjF,WACI,YAwBA,SAASwL,wBACLhM,UACAsF,KACA1E,GACAvB,OACAiI,SACAvH,WACHgH,aACAkF,oBACGlG,mBACAqB,cACAC,QACAnD,mBACAE,uBACAH,aACAE,WACA+H,kBAmBI,QAAS1D,gBACLnJ,OAAO8M,aAAgBC,QAAQ,GAGnC,QAASC,iBACL/E,SAAS,WACLjI,OAAO8M,aAAgBC,QAAQ,IAChC,GA6BP,QAASE,WACL,MAAMjF,SAAQS,OAIVzI,OAAMkN,OACF,WAAa,MAAOlF,SAAQS,OAC5B,SAAS0E,QAAUnN,OAAOoN,iBAAmBD,SAC7C,GAGLzF,aAAc2F,MAEbC,gBAAe5F,aAAc2F,MAGjCT,oBAAoBW,cACpBV,iBAAiBW,mBAEjBxN,OAAOhD,oBAAsB,GAAIyC,qBAAoBmF,mBACrD5E,OAAO6G,kBAAoB,GAAI/J,mBAAkBgI,WAAY9E,OAAOhD,2BAlBhEyQ,gBA0BR,QAASA,gBACL9M,UAAUwB,KAAI,iBAMlB,QAASmL,iBAAgBxL,OACrB4E,mBAAmB2G,KAAKvL,OAAOuD,KAAK,WAChC1E,UAAUwB,KAAI,iBAAkBuL,OAAM,IACtChN,WAAUiN,MAAM,cAFpBjH,SAGS,SAAUH,UACfvG,OAAOoC,MAAMmE,SAAU,mCAI/B,QAASqH,mCACLrM,GAAGsM,KACChJ,mBAAmBhD,MACnBkD,uBAAuBlD,QACxBwD,KAAK,SAASyI,WACb9N,OAAOhD,oBAAsB,GAAIyC,qBAAoBqO,UAAU,IAC/D9N,OAAO6G,kBAAoB,GAAI/J,mBAAkBgR,UAAU,GAAI9N,OAAOhD,uBAvG9E,GAAI+Q,iBAAkBrN,WAAUI,IAAI,0BAA4B8M,iCAC5DI,WAAatN,WAAUI,IAAI,kBAAoBqI,cAC/C8E,YAAcvN,WAAUI,IAAI,mBAAqBkM,cAErDhN,QAAMc,IAAI,WAAa,WACnBiN,kBACAE,cACAD,aACAnB,iBAAiBqB,mBAOrBlO,OAAO8M,aAAgBC,QAAQ,GAY/B/M,OAAOmO,eAAiB,WAAa,MAAOnO,QAAO8M,YAAYC,QAK/D/M,OAAOoO,gBACPpO,OAAOqO,eAAiB,SAASC,MAC7BtO,OAAOoO,aAAeE,MAG1BtO,OAAOuO,kBACPvO,OAAOwO,cAAgB,SAASC,SAC5BzO,OAAOuO,eAAiBE,SAM5BzO,OAAO0O,uBACP1O,OAAO2O,kBAAoB,SAASL,MAChCtO,OAAO0O,oBAAsBJ,MA6BjCrB,UA+BAjN,OAAOoC,MAAQ,SAASmE,SAAUqI,cAC9B,GAAuB,MAApBrI,SAAStE,OAAgB,CACxB,GAAI+G,QAASjB,cAAc8G,gBAAgBD,aAC3C5F,QAAOE,aAAa7D,KAAK,WACrB1E,UAAU+M,OAAM,MAIxBzH,KAAK7D,MAAK,UAAYmE,WA3JlChG,QACKC,OAAM,aACNU,WAAU,yBAA2ByL,wBAE1CA,uBAAsBxL,SAClB,YACA,OACA,KACA,SACA,WACA,aACA,eACA,sBACA,qBACA,gBACA,UACA,qBACA,yBACA,eACA,aACA,uBCxBR,WACI,YAQA,SAAS2N,wBAAsB9O,OAASiG,KAAM8I,eAAgBC,qBAiB1D,QAASC,gBACLjP,OAAOkP,YACPH,eAAeI,OAAO,SAASC,QAC3BpP,OAAOkP,SAAWE,OAAOrR,IACzB,KAAK,GAAIR,KAAKyC,QAAOkP,SAAU,CAC3B,GAAIT,SAAUzO,OAAOkP,SAAS3R,GAC1BD,SAAW0C,OAAO6G,kBAAkBtI,QAAQkQ,QAAQnR,SACvC,QAAbA,WACAmR,QAAQY,MAAQ/R,SAASkB,gBAGlC,WACCyH,KAAKqJ,IAAG,0CAMhB,QAASC,SAAQd,QAASjP,MACtBiP,QAAQjP,KAAOA,KACfuP,eAAeS,OAAOf,QAAS,WAE3BO,oBAAoBS,qBAAqBT,oBAAoBU,kBAAkBC,kBAChF,WACC1J,KAAKqJ,IAAG,kCAIhB,QAASM,aAAYnB,QAASnR,UAC1BmR,QAAQnR,SAAWA,SAASJ,KAC5B6R,eAAeS,OAAOf,QAAS,WAE3BA,QAAQY,MAAQ/R,SAASkB,aACzBwQ,oBAAoBS,qBAAqBT,oBAAoBU,kBAAkBC,kBAChF,WACC1J,KAAKqJ,IAAG,sCAIhB,QAASO,eAAcpB,SACnBM,eAAAA,UAAsBN,QAAS,WAE3B,GAAIqB,KAAM9P,OAAOkP,SAAS7Q,QAAQoQ,QAClCzO,QAAOkP,SAASa,OAAOD,IAAK,GAC5Bd,oBAAoBS,qBAAqBT,oBAAoBU,kBAAkBC,kBAChF,WACC1J,KAAKqJ,IAAG,6BA7DhBtP,OAAOkP,YAEPlP,OAAOgQ,QAAU,SAAUvB,SACvBA,QAAQwB,WAAY,GAGxBjQ,OAAOkQ,SAAW,SAAUzB,SACxBA,QAAQwB,WAAY,GAGxBjQ,OAAOuP,QAAUA,QACjBvP,OAAO4P,YAAcA,YACrB5P,OAAO6P,cAAgBA,cAkBvBZ,eAtCJ1O,QACKC,OAAM,aACNU,WAAU,yBAA2B4N,wBAE1CA,uBAAsB3N,SAAW,SAAW,OAAQ,iBAAkB,0BCP1E,WACI,YAyBA,SAASgP,wBAAsBnQ,OACCkI,WACAD,SACAhC,KACArE,QACAgG,YACAgF,oBACA9E,oBACAE,QACAL,aACAE,mBAoB5B,QAASnD,QACL1E,OAAOoQ,YAAc,KACrBpQ,OAAOqQ,gBAAkB,KACzBrQ,OAAOsQ,YAAc,KACrBtQ,OAAOuQ,eAAiB,KACxBvQ,OAAOoN,iBAAmBxL,QAAQ6G,MAElCb,YAAY/F,MAAMwD,KAAK,SAAUoG,KAC7BzL,OAAOwQ,oBAAsBC,eAAehF,IAAI1N,KAAKgN,YAGzD/K,OAAO0Q,YACHlR,KAASiR,eAAeE,eACxBnR,KAASiR,eAAeG,eACxBpR,KAASiR,eAAeI,eAG5B7Q,OAAO8Q,aACHtR,KAAUuR,mBAAqB,QAC/BvR,KAAUuR,mBAAqB,OAGnCnE,oBAAoBW,cAAclI,KAAK,SAAS2L,UAC5CC,aAAeD,SACfhR,OAAOkR,gBACHF,SAASG,yBACLnR,OAAO8Q,WAAW,GAAGtR,KACrBQ,OAAO8Q,WAAW,GAAGtR,OAqBrC,QAASiR,gBAAe1F,UACpB,MAAOqG,wBAAyBrG,SAGpC,QAASsG,aAAYC,KACjB,MAAOA,KAAI5E,QAAQ0E,uBAAwB,IAG/C,QAASG,sBACLvR,OAAOwR,cAAe,EAG1B,QAASC,uBACLzR,OAAOwR,cAAe,EAG1B,QAASE,2BACL1R,OAAO2R,mBAAoB,EAG/B,QAASC,4BACL5R,OAAO2R,mBAAoB,EAG/B,QAAS1K,SAEL,GAAI8D,UAAWsG,YAAWrR,OAAQwQ,qBAC9BqB,MACApJ,MAAOzI,OAAOoN,iBACd0E,UAAW,GACXC,SAAU,GACVhH,SAAUA,SAGdkG,cAAalG,SAAWA,SAExBnD,YAAY4H,OAAOqC,MAAMxM,KAAK,WAC1B6C,WAAW4C,IAAIC,UAEZ/K,OAAQwR,eAAgBxR,OAAQqQ,iBAAmBrQ,OAAOsQ,cACzD0B,iBACApF,oBAAoB4C,OAAOyB,cAAc5L,KAAKmG,SAA9CoB,SAA6DxK,QACvDpC,OAAQ2R,mBAAqB3R,OAAOqQ,gBAC1CzI,YAAYqK,WAAUjS,OAAQqQ,gBAAiB,WAC3C7E,UACAxD,QAAQkK,UACRvK,aAAawK,OAAOtK,kBAAkBuK,2BAA4B,WAC9DnM,KAAKqJ,IAAG,qBAEb,WACCxH,oBAAoBS,UAAS,8BAC7BvI,OAAOqS,yBAA0B,KAGrC7G,UACAoB,oBAAoB4C,OAAOyB,cAAc5L,KAAKmG,SAA9CoB,SAA6DxK,SAElEA,OAGP,QAAS4P,kBACFhS,OAAQsQ,cAAgBtQ,OAAOuQ,eAC1BhQ,QAAQ+R,YAAWtS,OAAQsQ,cAAuC,KAAvBtQ,OAAOsQ,aAClDxI,oBAAoBS,UAAS,yBAC7BvI,OAAOqS,yBAA0B,EACjCrS,OAAOuS,4BAA6B,GAEpC3K,YAAYoK,eAAchS,OAAQqQ,gBAAiBrQ,OAAOsQ,YAAa9E,QAAS,WAC5E1D,oBAAoBS,UAAS,8BAC7BvI,OAAOqS,yBAA0B,EACjCrS,OAAOuS,4BAA6B,IAI5CzK,oBAAoBS,UAAS,iCAiBrC,QAAS/B,UACLxG,OAAOsG,kBA/JX,GAAI2K,gBACJvM,QAEA1E,OAAOuR,mBAAqBA,mBAC5BvR,OAAOyR,oBAAsBA,oBAC7BzR,OAAOwR,cAAe,EACtBxR,OAAO0R,wBAA0BA,wBACjC1R,OAAO4R,yBAA2BA,yBAClC5R,OAAO2R,mBAAoB,EAC3B3R,OAAOwS,oBAAqB,EAC5BxS,OAAOiH,MAAQA,MACfjH,OAAOwG,OAASA,OAEhBsB,oBAAoBK,mBAAkBnI,QACtC8H,oBAAoByD,SAAQ,mBAC5BzD,oBAAoByD,SAAQ,eAC5BzD,oBAAoByD,SAAQ,kBAC5BzD,oBAAoByD,SAAQ,uBAiC5BvL,OAAOyS,kBAAoB,SAAU1H,UACjC/K,OAAOwQ,oBAAsBzF,SAASvL,MAG1CQ,OAAO0S,yBAA2B,SAASC,OACvC3S,OAAOkR,gBAAkByB,MAAMnT,KAC/ByR,aAAaE,yBAA2BwB,MAAMnT,OAASQ,OAAO8Q,WAAW,GAAGtR,KAGhF,IAAI4C,OAAQ,SAAUmE,UAClBuB,oBAAoBS,UAAS,6BAA+BhC,WAG5DiF,QAAU,WACVxL,OAAOsG,kBAiFXtG,QAAMkN,OAAO,kBAAoB,WAC7BlN,OAAOqS,yBAA0B,IAGrCrS,OAAMkN,OAAO,cAAgB,SAAU0F,UACnC5S,OAAOuS,4BAA6B,EACpCvS,OAAO6S,gCAAgC7S,OAAOuQ,gBAAiBqC,WAAa5S,OAAOuQ,iBAGvFvQ,OAAMkN,OAAO,iBAAmB,SAAU0F,UACtC5S,OAAO6S,8BAAgC7S,OAAOsQ,cAAgBsC,WA7LtErS,QACKC,OAAM,aACNU,WAAU,yBAA2BiP,wBAE1CA,uBAAsBhP,SAAW,SAC7B,aACA,WACA,OACA,UACA,cACA,sBACA,sBACA,UACA,eACA,oBAEJ,IAAIiQ,wBAAyB,gBACzBL,mBAAqB,kBAErBH,YAAc,KACdD,YAAc,KACdE,YAAc,QCxBtB,WACI,YAMA,SAASiC,aACL,OACIC,SAAU,IACVvO,YAAa,oCACbwO,OACIxM,OAAQ,MATpBjG,QACKC,OAAM,aACNyS,UAAS,YAAcH,cCLhC,WACI,YAQA,SAASI,SAAOC,OAASlL,UACrB,MAAO,UAAS+K,MAAOI,QAASC,OAC5B,GAAIC,OAAQH,OAAOE,MAAMH,QACzBF,OAAK9F,OAAQoG,MAAO,SAASX,OACtBA,SAAU,GACT1K,SAAS,WACLmL,QAAQ,GAAGG,SACZ,QAbnBhT,QACKC,OAAM,aACNyS,UAAS,UAAYC,SAE1BA,QAAO/R,SAAW,SAAW,eCPjC,WACI,YAMA,SAASqS,UACL,OACIhP,YAAa,kCANrBjE,QACKC,OAAM,aACNyS,UAAS,aAAeO,WCLjC,WACC,YAMC,SAASC,kBACR,OACCV,SAAU,KACVvO,YAAa,uCACbwO,OACCU,WAAY,IACZC,SAAU,IACVC,UAAW,MAXfrT,QACEC,OAAM,aACNyS,UAAS,eAAiBQ,mBCL7B,WACI,YAMA,SAASI,SACL,OACId,SAAU,IACVvO,YAAa,gCACbwO,OACI/L,MAAO,MATnB1G,QACKC,OAAM,aACNyS,UAAS,QAAUY,UCL5B,WACI,YAMA,SAASC,WACL,OACIf,SAAU,IACVvO,YAAa,kCACbwO,OACIe,KAAM,MATlBxT,QACKC,OAAM,aACNyS,UAAS,UAAYa,YCL9B,WACI,YAMA,SAASE,YACL,OACIjB,SAAU,IACVC,OACIiB,OAAQ,KAEZC,KAAM,SAASlB,MAAOI,SAClBA,QAAQe,KAAI,SAAW,WACnBnB,MAAMiB,aAZtB1T,QACKC,OAAM,aACNyS,UAAS,SAAWe,aCL7B,WACI,YAQA,SAASI,eAAaxT,SAClB,OACImS,SAAU,IACVmB,KAAM,SAAUlB,MAAOI,SACnBA,QAAQiB,GAAE,QAAU,WACbzT,QAAU0T,eAAeC,YAExB5W,KAAK6W,kBAAkB,EAAG7W,KAAKgV,MAAMnV,YAbzD+C,QACKC,OAAM,aACNyS,UAAS,gBAAkBmB,eAEhCA,cAAajT,SAAW,cCP5B,WACC,YACAZ,SACEC,OAAM,aACNyS,UAAS,gBAAc,cAAkB,eACzC,SAAWrL,YAAaD,cAKvB,QAAS8M,UAASzB,MAAM0B,MACvB,GAAIC,MACJhN,cAAaiN,cAAcvP,KAAM,SAAUwP,MAC1CA,KAAKC,KAAI,QAAU,WAClBH,MAAQE,KAAKF,MAAMjQ,MAClBqQ,UAAW,2EACXC,aAAc,qBACdhC,MAAO,iBAER,IAAII,SAAUsB,KAAK,GACfO,eAAiB,UACrBN,OAAMO,mBAAmB9B,WAAa,SAAS+B,YAC9C,GAAIpX,OACH+D,MAAOqT,WAAWC,kBAAkBH,gBACpClK,SAAUnD,YAAYyN,kBAEvBrC,OAAM9I,aAAanM,YApBvB,OACCgV,SAAU,IACVmB,KAAMO,gBCRX,WACI,YACAlU,SACKC,OAAM,aACNyS,UAAS,qBAAuB,WAC7B,OACIF,SAAU,IACVvO,YAAa,mDCP7B,WACI,YACAjE,SACKC,OAAM,aACNyS,UAAS,sBAAwB,WAC9B,OACIF,SAAU,IACVvO,YAAa,oDCP7B,WACI,YACAjE,SACKC,OAAM,aACNyS,UAAS,oBAAqB,YAAc,SAASqC,WAClD,OACIvC,SAAU,IACVvO,YAAa,2CACb0P,KAAM,SAASlB,MAAOI,SAClB,GAAImC,KAAMnC,QAAQ,EAClBkC,WAAUjB,GAAE,SAAW,WAEnB,GAAImB,MAAOD,IAAIE,wBACXC,IAAMC,SAASC,cAAa,2BAC5BF,OACIF,KAAKK,KAAO,GAAKL,KAAKM,OAAS,GAC/BJ,IAAIK,MAAMC,SAAW,QACrBN,IAAIK,MAAMF,IAAM,EAChBH,IAAIK,MAAME,MAAQ,SAElBP,IAAIK,MAAMC,SAAW,WACrBN,IAAIK,MAAME,MAAQ,cCrBlD,WACI,YACA1V,SACKC,OAAM,aACNyS,UAAS,iBAAmB,WACzB,OACIF,SAAU,IACVvO,YAAa,+CCP7B,WACI,YACAjE,SACKC,OAAM,aACNyS,UAAS,kBAAmB,YAAc,SAASqC,WAChD,OACIvC,SAAU,IACVvO,YAAa,yCACb0P,KAAM,SAAUlB,MAAOI,QAASC,OAC5B,GAAIA,MAAM6C,UAAW,CACjB,GAAIC,aAAcR,SAASS,iBAAgB,eAC3Cd,WAAUjB,GAAE,SAAW,WAEnB,GAAIgC,QAASV,SAASC,cAAa,mBACnC,IAAIS,OAAQ,CAER,GAAIC,gBAAiBH,aAAeA,YAAY3Y,OAAS,EAAI2Y,YAAY,GAAGV,wBAAwBI,IAAM,CAC1GQ,QAAON,MAAMQ,WAAaD,gBAAkB,EAAI,UAAY,gBAInEX,UAASC,cAAa,oBAAqBG,MAAMQ,WAAa,kBCrBvF,WACI,YACAhW,SACKC,OAAM,aACNyS,UAAS,eAAiB,WACvB,OACIF,SAAU,IACVvO,YAAa,6CCP7B,WACI,YACAjE,SACKC,OAAM,aACNyS,UAAS,eAAiB,WACvB,OACIF,SAAU,IACVvO,YAAa,6CCP7B,WACI,YAoBA,SAASgS,kBAAgBvQ,KAAO4B,kBAAmBE,cAAeJ,aAAcK,SAC5E,GAAIhB,MAAOrJ,IAEXqJ,MAAKiC,gBAAkBlB,cAAckB,gBACrCjC,KAAKyP,gBAAkB,SAASC,SAAUA,QAAQC,SAElD3P,KAAKgK,WAEGxR,KAAQ,yCACRmX,MAAS,WAAc5O,cAAc6O,mBAAmB5P,KAAKH,sBAG7DrH,KAAQ,4CACRmX,MAAS,WAAc5O,cAAc8O,wBAGrCrX,KAAQ,kCACRsX,WAAa,EACbH,MAAS,WACL3O,QAAQkK,UACRvK,aAAawK,OAAOtK,kBAAkBkP,eAAgB,WAClD9Q,KAAKqJ,IAAG,uBAvC5B/O,QACKC,OAAM,aACNwW,UAAS,cACNxS,YAAa;AACbtD,WAAYsV,iBACZS,UACIpQ,kBAAmB,IACnBuG,iBAAkB,OAI9BoJ,iBAAgBrV,SACZ,OACA,oBACA,gBACA,eACA,cCnBR,WACI,YA2BA,SAAS+V,uBACLlX,OACAU,WACAyW,wBACAC,mBACAC,uBACAC,oBACAC,SACA3V,SAqFI,QAAS4V,gCAA+BC,aAChCC,OAAOC,KAAKF,aAAaja,OAAS,GAAKia,YAAYzZ,cAAgB0Z,QACnEN,mBACKQ,oBAAoBH,aACpBpS,KAAKwS,kBAFVT,SAGW,SAAU7Q,UACbS,KAAK8Q,cACDvR,SAAUA,SACVwR,QAAS,oCAwC7B,QAASF,kBAAiBG,aACtB,GAAIC,YAAajR,KAAKqF,WAAW6L,KAEjCX,UAASY,KACLF,WACAD,YACAI,SACAC,WACAC,OACAC,UAGR,QAASH,UAASI,WACd,MAAOA,WAAUC,YAGrB,QAASJ,YAAWG,UAAWE,YAC3BnY,QAAQoY,KAAKD,WAAYF,WAG7B,QAASF,QAAOM,UAAWC,YACvBD,UAAU1a,QAAQ,SAAUsa,UAAWM,OACnC,GAAIhJ,KAAMyH,SAASwB,8BAA8BF,WAAYL,UAAUC,YAEnEK,OAAQhJ,KACRkJ,KAAKJ,UAAWE,MAAOhJ,KAE3B+I,WAAW/I,KAAKmJ,WAAY,IAIpC,QAASV,UAASK,UAAWM,QAASC,cAC7BD,QAAQD,WACTL,UAAU7I,OAAOoJ,aAAc,EAAGD,SAI1C,QAASF,MAAKI,MAAOC,SAAUC,UAE3B,GAAIA,UAAYF,MAAM5b,OAElB,IADA,GAAI+b,GAAID,SAAWF,MAAM5b,OACjB+b,IAAO,GACXH,MAAMhb,KAAKob,OAInB,IAAIC,KAAML,MAAME,SAChBF,OAAME,UAAYF,MAAMC,UACxBD,MAAMC,UAAYI,IAWtB,QAAS5J,eAAc3S,MACnB,GAAIwc,WAAY1S,KAAKqF,WAAW6L,MAAMyB,UAAU,SAAUrL,MACtD,MAAOA,MAAKmK,cAAgBvb,OAE5B0c,YAAc5S,KAAKqF,WAAW6L,MAAMnI,OAAO2J,UAAW,EAC1DG,kBAAiB7S,KAAKqF,WAAW6L,OACjClR,KAAK8S,iBAAiBrL,QAASmL,YAAY,KAInD,QAASC,kBAAiB3B,OAClBR,OAAOC,KAAK3Q,KAAKqF,YAAY7O,OAAS,GAAKwJ,KAAKqF,WAAWrO,cAAgB0Z,SAC3E1Q,KAAKqF,WAAW0N,WACZxZ,QAAQ+R,YAAY4F,OAChB,EACAA,MAAM8B,OAAO,SAAUC,IACnB,MAAkC,QAA3BA,GAAGC,MAAMC,gBACjB3c,QAGf4c,uBAGJ,QAASA,wBAEL,GADApT,KAAKqT,iBAAmB,GACpBrT,KAAKqF,WAAW0N,YAAc,EAC9B,MAAO5C,yBACFmD,YACAjV,KAAK,SAAUtH,MACRA,OACAiJ,KAAKqT,iBAAmBtc,KAAKwc,UA5N7C,GAAIvT,MAAOrJ,IACXqJ,MAAKqF,cACLrF,KAAKqT,iBAAmB,GAExBrT,KAAKwT,wBAA0B,SAASjU,SAAUwR,SAE9C/Q,KAAK8Q,cAAevR,SAAUA,SAAUwR,QAASA,UAGrD,IAAI0C,qBAAsB/Z,WAAUI,IAAI,oBAAsB,WAC1D0W,+BAA+BxQ,KAAKqF,cAGpCqO,wBAA0Bha,WAAUI,IAAI,wBACxC,SAAS6Z,MAAO5c,MACRA,KAAK2M,KAAO1D,KAAKqF,WAAW3B,IAE5B8M,+BAA+BxQ,KAAKqF,cAI5CuO,4BAA8Bla,WAAUI,IAAI,4BAC5C,SAAS6Z,MAAO5c,MAEZ,IAAK,GADD8c,QAAQ,EACHtd,EAAI,EAAGyJ,KAAKqF,WAAW6L,MAAM1a,OAAQD,IAAK,CAC/C,GAAI+Q,MAAOtH,KAAKqF,WAAW6L,MAAM3a,EACjC,IAAG+Q,MAAQA,KAAK5D,IAAM3M,MAAQA,KAAK2M,IAC3B4D,KAAK5D,KAAO3M,KAAK2M,IAAmC,QAA7B4D,KAAK4L,MAAMC,cAAyB,CAC3D7L,KAAK4L,MAAQnc,KAAKmc,MAClB5L,KAAKwM,OAAS/c,KAAK+c,OACnBxM,KAAKnH,gBAAkBpJ,KAAKwB,YAC5B+O,KAAK6H,YAAcpY,KAAKoY,YAExB0E,OAAQ,CACR,QAKPA,OACDrD,+BAA8BxX,OAAQqM,cAI9C0O,oBAAsBra,WAAUI,IAAI,oBACpC,SAAS6Z,MAAOzd,MAAQ2S,cAAc3S,OAE1C8J,MAAIgU,WAAc,WACdP,sBACAC,0BACAE,8BACAG,uBAGJ/a,OAAMib,iBAAiB,yBAA2B,SAAU/C,OACxD2B,iBAAiB3B,SAGrBlR,KAAIkU,WAAc,SAASC,SACvB,GAAGA,QAAQ/M,cAAiC,OAAjBxM,QAAQwZ,KAAe,CAC9C,GAAIlC,SAAUiC,QAAQ/M,aAAaiN,YAC5BnC,WAAW3Y,QAAQ+a,OAAOpC,aAC7BlS,KAAKqH,eAAe6K,SAMzBiC,QAAQne,qBAAwC,OAAjB4E,QAAQwZ,MACtC5D,+BAA+BxQ,KAAKqF,aAI5CrF,KAAKuU,cAAgB,SAASC,MAC1BlE,oBACKiE,cAAcC,MACdnW,KAAK,WACF2B,KAAKqF,WAAamP,KAClB9a,WAAUiN,MAAM,qBAChB6J,+BAA+BgE,SAkB3CxU,KAAKyU,qBAAuB,SAASC,SACjC1U,KAAKqF,WAAW7M,KAAOkc,QAEvBtE,mBACK5H,OAAOxI,KAAKqF,YADjB+K,SAEW,SAAU7Q,UACbS,KAAK8Q,cACDvR,SAAUA,SACVwR,QAAS,sCAKzB/Q,KAAKqH,eAAiB,SAAU6K,SAC5B,GAAIyC,WACJpb,SAAQoY,KAAK3R,KAAKqF,WAAYsP,QAE9B,IAAIC,SAAUvE,uBAAuBwE,sBAAsB3C,SAASlS,KAAKqF,WAAW3B,GACpFiR,SAAQzD,OAAS0D,SACjBxE,mBACKe,KAAKwD,SAAS,GACdtW,KAAK,SAASkB,UAEX,MADAS,MAAK8U,cAAcrN,QAASmN,UACrBrV,WAEVlB,KAAKwS,kBANVT,SAOW,SAAU7Q,UACbS,KAAK8Q,cACDvR,SAAUA,SACVwR,QAAS,+BAwDzB/Q,KAAK+U,eAAiB,SAASzN,MACT,WAAfA,KAAK4L,MACJlT,KAAK8S,iBAAiBrL,QAASH,OACV,YAAfA,KAAK4L,OACXrK,cAAcvB,KAAKmK,cA7NnClY,QACKC,OAAM,aACNwW,UAAS,eACNxS,YAAa,sCACbtD,WAAYgW,sBACZD,UACI6C,gBAAiB,IACjBgC,aAAc,IACdhE,aAAc,IACd9a,oBAAqB,IACrB6J,kBAAmB,IACnBuH,aAAc,OAI1B8I,sBAAqB/V,SACjB,SACA,aACA,0BACA,qBACA,yBACA,sBACA,WACA,cC1BR,WACI,YAiBA,SAAS6a,6BAA2Btb,WAAa0W,mBAAoB6E,eA4D7D,QAASC,oBACL9E,mBACKvV,MACAwD,KAAK,SAAS8W,cACXnV,KAAKmV,gBACLA,aAAaje,QAAQ,SAAUsd,MAC3BY,WAAWZ,MACXxU,KAAKmV,aAAa/d,KAAKod,MAEpBA,KAAKa,UAAW,IACfrV,KAAKuU,eAAeC,KAAMA,OAC1BxU,KAAKqF,YAAe7M,KAAMgc,KAAKhc,WAV/C4X,SAcW,SAAS7Q,UACZS,KAAKsV,aACD/V,SAAUA,SACVwR,QAAS,qCAKzB,QAASqE,YAAWZ,MAChBA,KAAKzB,WAAayB,KAAKtD,MAAM1a,OAC7Bge,KAAKtD,SApFT,GAAIlR,MAAOrJ,IACXqJ,MAAKmV,gBACLnV,KAAKqF,YAAe7M,KAAM,GAE1B,IAAI+c,UACE/c,KAAM,WAAYgd,OAAQjc,QAAQkc,OAClCjd,KAAM,oBAAqBgd,OAAQjc,QAAQkc,OAC3Cjd,KAAM,wBAAyBgd,OAAQjc,QAAQkc,OAC/Cjd,KAAM,wBAAyBgd,OAAQjc,QAAQkc,OAC/Cjd,KAAM,wBAAyBgd,OAAQjc,QAAQkc,OAC/Cjd,KAAM,4BAA6Bgd,OAAQjc,QAAQkc,MAGzDzV,MAAIgU,WAAc,WACdza,QAAQrC,QAAQqe,OAAQ,SAAS5B,OAC7BA,MAAM6B,YAIdxV,KAAIiG,QAAW,WACXiP,mBAEA3b,QAAQrC,QAAQqe,OAAQ,SAAS5B,OAC7B,GAAI+B,IAAKnc,QAAQkc,IAGbC,IADc,0BAAf/B,MAAMnb,KACA,SAASmd,GAAI5e,MACd,IAAK,GAAIR,KAAKyJ,MAAKmV,aAAc,CAC7B,GAAIX,MAAOxU,KAAKmV,aAAa5e,EAC7B,IAAIie,KAAK9Q,KAAO3M,KAAK2M,GAGjB,MAFA8Q,MAAKhc,KAAOzB,KAAKyB,UACjBgc,KAAKoB,MAAQ7e,KAAK6e,SAKT,0BAAfjC,MAAMnb,KACP,SAASmb,MAAOjQ,IACjB,GAAImS,WAAY7V,KAAKmV,aAAaxC,UAAU,SAAU6B,MAClD,MAAOA,MAAK9Q,KAAOA,IAGpBmS,YACC7V,KAAKmV,aAAapM,OAAO8M,UAAW,GAGpC7V,KAAKqF,WAAW3B,KAAOA,KACvB1D,KAAKuU,eAAeC,KAAMxU,KAAKmV,aAAa,KAC5CnV,KAAKqF,YAAe7M,KAAMwH,KAAKmV,aAAa,GAAG3c,QAIlD0c,iBAGTvB,MAAM6B,OAAS9b,WAAUI,IAAK6Z,MAAMnb,KAAMkd,OAgClD1V,KAAK8V,iBAAmB,SAAStB,MAC7BS,cAAcc,oBAAoBvB,OAGtCxU,KAAKgW,kBAAoB,SAASxB,MAC3BxU,KAAKmV,aAAa3e,OAAS,GAC1Bye,cACKgB,qBAAqBzB,MACrBtS,aACA7D,KAAK6W,mBAIlBlV,KAAKkW,kBAAoB,WACrBjB,cACKkB,iBACAjU,aACA7D,KAAK6W,mBAGdlV,KAAKoW,eAAiB,WAClBpW,KAAKyU,sBAAsBC,QAAS1U,KAAKqF,WAAW7M,QAGxDwH,KAAKqW,aAAe,SAAS7B,MACzBxU,KAAKuU,eAAeC,KAAMA,QAhItCjb,QACKC,OAAM,aACNwW,UAAS,qBACNxS,YAAa,4CACbtD,WAAY8a,4BACZ/E,UACI5K,WAAY,IACZkP,cAAe,IACfE,qBAAsB,IACtB3D,aAAc,OAI1BkE,4BAA2B7a,SAAW,aAAe,qBAAsB,oBChB/E,WACI,YAgBA,SAASmc,mCACL,GAAItW,MAAOrJ,IAEXqJ,MAAK8V,iBAAmB,WACpB9V,KAAKuW,WAAW/B,KAAMxU,KAAKwU,QAG/BxU,KAAKgW,kBAAoB,WACrBhW,KAAKwW,YAAYhC,KAAMxU,KAAKwU,QAGhCxU,KAAKyW,oBAAsB,WACvBzW,KAAK0W,kBAAkBlC,KAAMxU,KAAKwU,QA1B1Cjb,QACKC,OAAM,aACNwW,UAAS,yBACNxS,YAAa,gDACbtD,WAAYoc,gCACZrG,UACIuE,KAAM,IACNmC,UAAW,IACXJ,UAAW,IACXC,WAAY,IACZE,iBAAkB,UCblC,WACI,YAwBA,SAASE,yBACL5d,OACAuB,GACA0G,SACAgU,cACA4B,eACAzG,oBAmCI,QAAS0G,eAAcC,aACnB,GAAyB,iBAAtBA,YAAYpL,MAA2B,MAAOpR,IAAGgD,MAEpD,IAAIwC,eAAgBgX,YAAYpL,MAE5BlE,SACAjP,KAAQuH,cAAciX,YACtB1gB,SAAYyJ,cAAczJ,SAASJ,KAGvC,OAAOqE,IAAGsM,KAAKgQ,eAAe9T,OAAO0E,SAAUlN,GAAGgD,KAAKwC,iBAG3D,QAASkX,eAAcC,UACnB,GAAGA,SAAU,CACT,GAAI9O,QAAS8O,SAAS,GAAGngB,KACrBgJ,cAAgBmX,SAAS,EAC7BnX,eAAc7J,KAAOkS,OAAOlS,KAC5B6J,cAAczJ,SAAW8R,OAAO9R,SAChC0J,KAAKmX,mBAAmBpX,eAG5B,MAAOxF,IAAGgD,OAYd,QAAS6Z,aAAYC,YACjB,GAAIC,YAAaD,WAAWE,MAAK,MAAO,EAOxC,OANID,aAAc/d,QAAQie,QAAQC,iBAC9BA,cAAgBA,cAAczE,OAAO,SAAU1L,MAC3C,MAAOA,MAAK9O,KAAKa,cAAchC,QAAQigB,WAAWje,gBAAkB,KAIrEkB,GAAGoD,QAAQ8Z,eAGtB,QAASC,cAAaL,YAClB,MAAOR,gBACFnQ,OAAO2Q,YACPhZ,KAAK,SAAUtH,MAEZ,MADA0gB,eAAgB3gB,YAAYC,KAAK4gB,SAAU5gB,KAAKmR,YAO5D,QAASpR,aAAY8gB,SAAU1P,UAC3B,GAAI2P,cAA4B,OAAbD,SAAoBA,YACnCE,aAA4B,OAAb5P,SAAoBA,WAEvC2P,cAAa3gB,QAAQ,SAAU6gB,IAAMA,GAAGC,WAAY,GAEpD,IAAIC,iBAAkBH,aAAaI,IAAI,SAAUzQ,SAC7C,GAAI0Q,uBAWJ,OARIA,wBADA1Q,QAAQ2Q,YACiBpY,KAAKqY,eAAe5Q,QAAQvR,MAChDmI,KAAK,SAASia,qBACX,MAAOA,qBAAoBhiB,WAGViE,GAAGoD,QAA6C,IAArC4a,KAAKC,MAAM/Q,QAAQvR,KAAO,MAG3DiiB,uBAAuB9Z,KAAK,SAAUoa,iBACzC,GAAI3P,KAAMsH,mBAAmB2B,8BAA8B/R,KAAKqF,WAAW6L,MAAOzJ,QAAQvR,KAC1F,IAAG4S,OAAU,CACT,GAAIxB,MAAOtH,KAAKqF,WAAW6L,MAAMpI,IAC7BxB,MAAKG,UAAYA,QAAQvR,OACzBuR,QAAQiR,YAAa,GAI7BjR,QAAQkR,WAAY,EACpBlR,QAAQjQ,aAAewI,KAAKH,kBAAkBvI,aAAamhB,oBAInE,OAAOle,IAAGsM,IAAIoR,iBAAiB5Z,KAAK,WAChC,MAAOwZ,cAAae,OAAOd,gBA3HnC,GAAI9X,MAAOrJ,KACP8gB,gBAEJzX,MAAKqX,WAAa,GAElBrX,KAAK6Y,sBAAwB,WACzB,GAAI7W,QAASiT,cAAc6D,mBACvB9Y,KAAKqX,YACL,EACArX,KAAKH,kBACLG,KAAKhK,oBAETgM,QACKE,aACA7D,KAAKyY,eACLzY,KAAK4Y,eAHVjV,SAIW,SAASzC,UACZS,KAAKsV,aACD/V,SAAUA,SACVwR,QAAS,iCAKzB/Q,KAAKqY,eAAiB,SAAS3U,IAC3B,MAAOnJ,IAAG,SAASoD,QAAStC,QACxBwb,eAAetf,QAAQmM,GAAI/F,QAAStC,UACrCgD,KAAK,SAASkB,UACb,MAAOA,UAASxI,OAHbwD,SAIE,SAASa,OACd,KAAMA,UA8BdpC,OAAO+f,eAAiB,WACpB,MAAiC,MAA9B/Y,KAAKqX,WAAW2B,OAAO,GACf5B,YAAYpX,KAAKqX,YAEjBK,aAAa1X,KAAKqX,aA+DjCrX,KAAKmX,mBAAqB,SAAU7P,MAC3BA,KAAKoR,WAYN1Y,KAAKqX,WAAa,GAXd/P,KAAK0Q,WACLP,cAAgB3gB,YAAYwQ,KAAK2R,cAAe3R,KAAKY,UACrDlI,KAAKqX,WAAa,IAAM/P,KAAK9O,KAAO,KACpCyI,SAAS,WACL1H,QAAQ6S,QAAQuC,SAASC,cAAa,eAAgBsK,eAAc,aAGxElZ,KAAKqX,WAAa,GAClBrX,KAAKmZ,oBAAoB7R,KAAMA,SAtKnD/N,QACKC,OAAM,aACNwW,UAAS,iBACNxS,YAAa,wCACbtD,WAAY0c,wBACZ3G,UACI5K,WAAY,IACZxF,kBAAmB,IACnB7J,oBAAqB,IACrBmjB,mBAAoB,IACpBrI,aAAc,OAI1B8F,wBAAuBzc,SACnB,SACA,KACA,WACA,gBACA,iBACA,yBCvBR,WACI,YAeA,SAASif,6BACL,GAAIpZ,MAAOrJ,IAEXqJ,MAAKqZ,SAAW,WACyB,QAAlCrZ,KAAKsH,KAAK4L,MAAMC,eACfnT,KAAKsZ,QAAQhS,KAAMtH,KAAKsH,QAIhCtH,KAAKuZ,WAAa,WACdvZ,KAAKwZ,UAAUlS,KAAMtH,KAAKsH,QAG9BtH,KAAKyZ,eAAiB,WAClB,GAAI3F,QAAS9T,KAAKhK,oBAAoBuB,QAAQyI,KAAKsH,KAAKnH,gBACxD,OAAK2T,SAA4B,MAAlBA,OAAOlb,QAAsC,YAApBkb,OAAO3b,SACvB,IAArB6H,KAAKsH,KAAKwM,OACFA,OAAO3b,SAEP2b,OAAOlb,OAJ8D,IA5BxFW,QACKC,OAAM,aACNwW,UAAS,mBACNxS,YAAa,0CACbtD,WAAYkf,0BACZnJ,UACI3I,KAAM,IACNgS,OAAQ,IACRE,SAAU,IACVxjB,oBAAqB,UCZrC,WACI,YA0BA,SAAS0jB,4BAA0Bnf,GACCb,WACAuH,SACAgU,cACA4B,eACAxG,uBACAC,qBAuChC,QAASqJ,eAAc5C,aACnB,GAAIxd,QAAQ+R,YAAYyL,YAAYpL,QAAgC,iBAAtBoL,YAAYpL,MACtD,MAAOpR,IAAGgD,MAGd,IAAIwC,eAAgBgX,YAAYpL,KAChC,IAAI5L,cAAcqY,YAAa,CAE3B,GAAI3Q,UACAvR,KAAM6J,cAAc0R,YACpBjZ,KAAMuH,cAAciX,YACpB1gB,SAAUyJ,cAAczJ,SAASJ,KACjCkiB,aAAa,EAGjB,OAAOvB,gBACFrO,OAAOf,SACPpJ,KAAK,WAEF,MAAO0B,iBAGf,MAAOxF,IAAGgD,KAAKwC,eAIvB,QAAS6Z,uBAAsB7Z,eAC3B,MAAIxG,SAAQ+R,YAAYvL,eACbxF,GAAGgD,OAEP8S,uBACF7H,OAAOzI,eACP1B,KAAK,WACF,MAAO0B,iBAvEnB,GAAIC,MAAOrJ,IACXqJ,MAAK8J,YAAa,CAElB,IAAI0L,QAAS9b,WAAUI,IAAI,sBAAwB,SAAU6b,GAAI3L,UAC7DhK,KAAK8J,WAAaE,SAASG,0BAG/BnK,MAAIgU,WAAc,WACdwB,UAGJxV,KAAIiG,QAAW,WACXqK,oBAAoB/J,cAAclI,KAAK,SAAU2L,UAC7ChK,KAAK8J,WAAaE,SAASG,4BAInCnK,KAAKqZ,SAAW,SAAU/R,MACtB,GAAItF,QAASiT,cAAc4E,oBAAoBvS,KAC3CtH,KAAKH,kBAAmBG,KAAKhK,oBAEjCgM,QACKE,aACA7D,KAAKsb,eACLtb,KAAKub,uBACLvb,KAAK,SAAU0B,eACRxG,QAAQugB,UAAU/Z,gBAClBxG,QAAQoY,KAAK5R,cAAeuH,QANxCtF,SASW,SAAUzC,UACbS,KAAK8Q,cACDvR,SAAUA,SACVwR,QAAS,kCA0CzB/Q,KAAKuZ,WAAa,SAAUjS,MACxBA,KAAKyS,cAAgB,kBACrB9Y,SAAS,WACLqG,KAAK4L,MAAQ,UACb7C,uBACK7H,OAAOlB,MACPjJ,KAAK,WACF2B,KAAKga,YAAY1S,KAAMA,UAEhC,MAGPtH,KAAKia,QAAU,SAAU3S,MACrBA,KAAKyS,cAAgB,iBACrB9Y,SAAS,WAC4B,QAA7BqG,KAAK4L,MAAMC,cACX7L,KAAK4L,MAAQ,SACuB,WAA7B5L,KAAK4L,MAAMC,gBAClB7L,KAAK4L,MAAQ,WAGjB7C,uBACK7H,OAAOlB,MACPjJ,KAAK,WACiB,YAAfiJ,KAAK4L,OAAsC,WAAf5L,KAAK4L,OACjClT,KAAKga,YAAY1S,KAAMA,UAGpC,MAtIX/N,QACKC,OAAM,aACNwW,UAAS,oBACNxS,YAAa,2CACbtD,WAAYwf,2BACZzJ,UACI5K,WAAY,IACZxF,kBAAmB,IACnB7J,oBAAqB,IACrBgkB,WAAY,IACZlJ,aAAc,OAI1B4I,2BAA0Bvf,SACtB,KACA,aACA,WACA,gBACA,iBACA,yBACA,0BCxBR,WACI,YAyBA,SAAS+f,uBACL3f,GACAvB,OACAU,WACAkB,QACA0V,oBACAF,mBACA+J,6BAkEI,QAASC,uBACLC,cACKC,QACAjc,KAAK8b,4BAA4Btf,KACjCwD,KAAK,SAAU+J,QACRA,OAAOrR,MAAQqR,OAAOrR,KAAKC,cAAgBC,OAC3CsjB,cAAcva,KAAKwa,YAAapS,OAAOrR,QALnDsjB,SAQW,SAAU9a,UACbS,KAAK8Q,cACDvR,SAAUA,SACVwR,QAAS,iCAKzB,QAASwJ,eAAcE,gBAAiBC,2BACpC,IAAK,GAAInkB,GAAI,EAAGA,EAAIkkB,gBAAgBjkB,OAAQD,IAAK,CAC7C,GAAIuS,KAAMsH,mBAAmB2B,8BACzB2I,0BACAD,gBAAgBlkB,GAAGkR,QAAQvR,KAE3B4S,KAAM,EAEN2R,gBAAgB1R,OAAOxS,IAAK,IAG5BkkB,gBAAgBlkB,GAAGkR,QAAUiT,0BAA0B5R,KAAKrB,QAC5DgT,gBAAgBlkB,GAAGokB,MAAQD,0BAA0B5R,KAAK6R,MAC1DD,0BAA0B3R,OAAOD,IAAK,IAK9C,GAAI8R,YAAa5a,KAAK6a,aAAaJ,gBAAgB7B,OAAO8B,2BAE1DA,2BAA0BxjB,QAAQ,SAAU4jB,oBACxC,GAAIvkB,GAAIqkB,WAAWvjB,QAAQyjB,mBAC3BL,iBAAgB1R,OAAOxS,EAAG,EAAGukB,sBAKjCL,gBAAgBvjB,QAAQ,SAAUmI,UAC9BA,SAAS0b,cAAgB/a,KAAKH,kBAAkBvI,aAAa+H,SAASoI,QAAQnR,YAGlF0kB,4BAA4BJ,YAyBhC,QAASjT,mBAAkBsT,aACvB,GAAInS,KAAMsH,mBAAmB2B,8BAA8B/R,KAAKwa,YAAaS,YAAYxT,QAAQvR,KACjG,IAAI4S,OAAU,CACV9I,KAAKwa,YAAYzR,OAAOD,IAAK,EAE7B,IAAIoS,iBAAkBlb,KAAKwa,YAAYW,OACvCD,iBAAgBE,KAAK,SAAUrjB,EAAGsjB,GAC9B,MAAOtjB,GAAEujB,MAAQD,EAAEC,QAEvBN,4BAA4BE,kBAIpC,QAASF,6BAA4BO,mBACjC,IAAK,GAAIhlB,GAAI,EAAGA,EAAIglB,kBAAkB/kB,OAAQD,IAAK,CAC/C,GAAIilB,GAAIxb,KAAKwa,YAAYnjB,QAAQkkB,kBAAkBhlB,GACnDyJ,MAAKwa,YAAYgB,GAAGF,MAAQ/kB,EAC5ByJ,KAAKwa,YAAYgB,GAAGC,QAAUC,WAAWnlB,GACzCyJ,KAAKwa,YAAYgB,GAAGG,QAAS,GAOrC,QAASD,YAAWJ,OAChB,GAAIM,YAAa,GAEbC,yBAA2BtiB,QAAQ6S,QAAQuC,SAASC,cAAa,wBACjEkN,wBAA0BviB,QAAQ6S,QAAQuC,SAASC,cAAa,uBAEhEmN,WAAaF,yBAAyBG,KAAI,gBAC1CC,WAAaH,wBAAwBE,KAAI,gBACzCF,wBAAwBE,KAAI,gBAAmB,GAE/CE,sBAAwB3D,KAAK4D,IAAIJ,WAAaE,YAC9CG,qBACIF,sBAAwBlc,KAAKwa,YAAYhkB,OACrCwJ,KAAKwa,YACL0B,sBAERG,aAAe,EAAMT,aAAeQ,qBAAuB,GAE3DE,UAAYT,yBAAyBG,KAAI,YAS7C,OANAV,QAAS/C,KAAK4D,IAAIG,UAAYL,YAMvBX,MAAQc,qBAAuB,EAAI,EAAI,IAAMC,YAAcf,MA9LtE,GAAItb,MAAOrJ,IAEXqJ,MAAKwa,eACLxa,KAAKuc,aAAc,EACnBvc,KAAK6a,aAAe,WAAa,MAAO,GAExC,IAAIR,eAAgB9f,GAAGiiB,OACvBxjB,QAAMc,IAAI,eAAiB,SAAS6Z,MAAO8I,KACvC9I,MAAM+I,kBACN1c,KAAK6a,aAAe4B,IAAIrB,KACxBf,cAAc1c,WAGlB,IAAI4X,UACE/c,KAAM,wBAAyBgd,OAAQjc,QAAQkc,OAC/Cjd,KAAM,4BAA6Bgd,OAAQjc,QAAQkc,OACnDjd,KAAM,oBAAqBgd,OAAQjc,QAAQkc,OAC3Cjd,KAAM,wBAAyBgd,OAAQjc,QAAQkc,OAC/Cjd,KAAM,4BAA6Bgd,OAAQjc,QAAQkc,OACnDjd,KAAM,yBAA0Bgd,OAAQjc,QAAQkc,OAChDjd,KAAM,oBAAqBgd,OAAQjc,QAAQkc,MAGjDzV,MAAIgU,WAAc,WACdza,QAAQrC,QAAQqe,OAAQ,SAAS5B,OAC7BA,MAAM6B,YAIdxV,KAAIiG,QAAW,WAEXjG,KAAKuc,cAAc3hB,QAAQoP,UAAWpP,QAAQoP,SAASuS,YACvDnC,sBAEA7gB,QAAQrC,QAAQqe,OAAQ,SAAS5B,OACX,2BAAfA,MAAMnb,KACLmb,MAAM6B,OAAS9b,WAAUI,IAAK6Z,MAAMnb,KAAM,SAASmb,MAAO5c,MACtD4Q,kBAAkB5Q,QAGtB4c,MAAM6B,OAAS9b,WAAUI,IAAK6Z,MAAMnb,KAAM4hB,wBAKtDpa,KAAIkU,WAAc,SAASC,SACpBA,QAAQtU,mBACPsU,QAAQtU,kBAAkB8c,iBAC1BxI,QAAQ5M,gBACR4M,QAAQ5M,eAAeoV,iBACvBxI,QAAQyI,cACRzI,QAAQyI,aAAaD,mBAKrBxI,QAAQtU,mBAAqBsU,QAAQ5M,iBAAoC,OAAjB3M,QAAQwZ,MAChEgG,sBAGDjG,QAAQyI,cACPjV,mBAAmBF,SAAUvR,KAAMie,QAAQyI,aAAavI,aAAa5M,aAuD7EzH,KAAK6c,kBAAoB,WACrB7c,KAAKuc,aAAevc,KAAKuc,YAEzBjM,oBACK9H,QAAQ+T,YAAavc,KAAKuc,cAD/BjM,SAEW,SAAS/Q,UACZS,KAAK8Q,cACDvR,SAAUA,SACVwR,QAAS,QAKzB/Q,KAAK8c,qBAAuB,SAAS7B,aACjCA,YAAYU,QAAS,EACrBV,YAAYnH,OAAS,EAErB9T,KAAKqH,gBAAgBC,KAAM2T,cAC3BtT,kBAAkBsT,cA2DtBjb,KAAK+c,YAAc,SAASzL,QACxBtR,KAAK6a,aAAevJ,MACpB,IAAI4J,iBAAkBlb,KAAKwa,YAAYW,QACnCI,kBAAoBjK,OAAO4J,gBAC/BF,6BAA4BO,oBAGhCvb,KAAKgd,WAAa,WACd,IAAK,GAAIzmB,KAAKyJ,MAAKwa,YAAa,CAC5B,GAAInb,UAAWW,KAAKwa,YAAYjkB,EAChC8I,UAASoc,QAAUC,WAAWrc,SAASic,OAI3CtiB,OAAMikB,WA9OlB1jB,QACKC,OAAM,aACNwW,UAAS,eACNxS,YAAa,sCACbtD,WAAYggB,sBACZjK,UACIpQ,kBAAmB,IACnB0H,eAAgB,IAChBqV,aAAc,IACdvV,eAAgB,IAChByJ,aAAc,OAI1BoJ,sBAAqB/f,SACjB,KACA,SACA,aACA,UACA,sBACA,qBACA,kCCxBR,WACI,YAcA,SAAS+iB,2BAA0BjI,eAC/B,GAAIjV,MAAOrJ,IAEXqJ,MAAKmd,mBAAqB,WACtBnd,KAAK8c,sBAAsB7B,YAAajb,KAAKod,mBAGjDpd,KAAKqd,sBAAwB,WACzBpI,cAAcqI,4BAA4Btd,KAAKod,kBArBvD7jB,QACKC,OAAM,aACNwW,UAAS,mBACNxS,YAAa,0CACbtD,WAAYgjB,0BACZjN,UACImN,gBAAiB,IACjBN,qBAAsB,OAIlCI,0BAAyB/iB,SAAW,oBCbxC,WACI,YAeA,SAASojB,qBAAmBvkB,QAYxB,QAASwkB,mBACL,GAAIC,SAAUzd,KAAKH,kBACfiJ,IAAM,CAEV2U,SAAQ5mB,gBAAgBK,QAAQ,SAAUZ,UACtC,GAAIJ,MAAOI,SAASJ,IAEpB8J,MAAK0d,YAAYtmB,MACbgkB,KAAM,SAASuC,iBACX,MAAOC,gBAAeD,gBAAiBF,QAASvnB,OAEpD2nB,UAAWJ,QAAQtnB,YAAYD,MAC/BmS,MAAOoV,QAAQnmB,aAAapB,MAC5BolB,MAAOxS,UAIf9I,KAAK0d,YAAYtmB,MACbgkB,KAAM0C,YACND,UAAW,qBACXvC,MAAOxS,QAEX9I,KAAK0d,YAAYtmB,MACbgkB,KAAM2C,WACNF,UAAW,sBACXvC,MAAOxS,QAGX9P,OAAM2N,MAAM,gBAAkByU,KAAM0C,cAvCxC,GAAI9d,MAAOrJ,IACXqJ,MAAK0d,eAEL1d,KAAIiG,QAAW,WACXuX,mBAGJxd,KAAKge,SAAW,SAASC,YACrBje,KAAKob,MAAM9J,OAAQ2M,WAAW7C,QAmCtC,QAAS2C,YAAWG,aAIhB,MAHAA,aAAY9C,KAAK,SAAUrjB,EAAGsjB,GAC1B,MAAOtjB,GAAE0P,QAAQjP,KAAK2lB,cAAc9C,EAAE5T,QAAQjP,QAE3C0lB,YAGX,QAASE,aAAYF,aAMjB,MALAA,aAAY9C,KAAK,SAAUrjB,EAAGsjB,GAC1B,MAAIgD,UAAStmB,EAAEujB,OAAS+C,SAAShD,EAAEC,UAC/B+C,SAAStmB,EAAEujB,OAAS+C,SAAShD,EAAEC,OAAiB,EAC7C,IAEJ4C,YAGX,QAASJ,aAAYI,aA6BjB,MA5BAA,aAAY9C,KAAK,SAAUrjB,EAAGsjB,GAE1B,GAAIiD,WAAYjD,EAAEV,MAAQ5iB,EAAE4iB,KAC5B,OAAkB,KAAd2D,UACOA,UAIHvmB,EAAEgjB,cAAgBM,EAAEN,cACb,EAEFhjB,EAAEgjB,cAAgBM,EAAEN,iBAKrBhjB,EAAE0P,QAAQjP,KAAO6iB,EAAE5T,QAAQjP,KACpB,EAEFT,EAAE0P,QAAQjP,KAAO6iB,EAAE5T,QAAQjP,QAIzB,IAKhB0lB,YAGX,QAASN,gBAAeD,gBAAiB9d,kBAAmB0e,kBACxD,GAAIC,kBACAC,oBAiBJ,OAfAd,iBAAgBzmB,QAAQ,SAAUmI,UAC9B,GAAI/I,UAAWuJ,kBAAkBtI,QAAQ8H,SAASoI,QAAQnR,UAEtDqB,cAAgBkI,kBAAkBnI,iBAAiBpB,SACnDqB,gBAAiBA,cAAczB,OAASqoB,iBACxCE,kBAAkBrnB,KAAKiI,UAGvBmf,cAAcpnB,KAAKiI,YAI3B0e,WAAWU,mBACXL,YAAYI,eACZb,gBAAkBc,kBAAkB7F,OAAO4F,eA3H/CjlB,QACKC,OAAM,aACNwW,UAAS,oBACNxS,YAAa,2CACbtD,WAAYqjB,oBACZtN,UACIpQ,kBAAmB,IACnBub,KAAM,OAIlBmC,oBAAmBpjB,SAAW,aCdlC,WACI,YAgBA,SAASukB,gCACL,GAAI1e,MAAOrJ,IAEXqJ,MAAKuI,QAAU,SAAS/P,MACpBwH,KAAK2e,gBACDlX,QAASzH,KAAKyH,QACdjP,KAAMA,QAIdwH,KAAKwH,cAAgB,WACjBxH,KAAK6I,eAAepB,QAASzH,KAAKyH,WAGtCzH,KAAK4e,qBAAuB,SAAStoB,UACjC0J,KAAK6e,oBACDpX,QAASzH,KAAKyH,QACdnR,SAAUA,YA/BtBiD,QACKC,OAAM,aACNwW,UAAS,sBACNxS,YAAa,6CACbtD,WAAYwkB,6BACZzO,UACIxI,QAAS,IACT5H,kBAAmB,IACnBgf,mBAAoB,IACpBF,eAAgB,IAChB9V,cAAe,UCb/B,WACC,YAeC,SAASiW,8BACR,GAAI9e,MAAOrJ,IAEXqJ,MAAKI,OAAS,SAAUkH,MACvBtH,KAAK+e,UAAUzoB,SAAUgR,QAjB5B/N,QACEC,OAAM,aACNwW,UAAS,oBACAxS,YAAa,2CACtBtD,WAAY4kB,2BACZ7O,UACU5Z,WAAY,IACT2oB,iBAAkB,IAC9BC,SAAU,IACVF,SAAU,UCZd,WACC,YAEAxlB,SACEC,OAAM,aACNwW,UAAS,YACTxS,YAAa,mCACbyS,UACCtE,MAAO,IACP6I,KAAM,IACNyK,SAAU,IACVC,aAAc,UCXlB,WACI,YAUA,SAASC,qBAAmBzlB,YAgBxB,QAAS+O,sBAAqBsI,QAASqO,MACnC1lB,WAAU2lB,WAAYtO,QAASqO,MAGnC,QAASE,sBAAqBtT,MAAO+E,QAASwO,UAC1CvT,MAAKlS,IAAKiX,QAASwO,UApBvB,GAAIC,oBACAC,cAAe,iBACfC,kBAAmB,qBACnBC,aAAc,gBACdhX,gBAAiB,oBACjBiX,eAAgB,kBAChBzU,OAAQ,SAGZ,QACIzC,kBAAoB8W,kBACpB/W,qBAAsBA,qBACtB6W,qBAAsBA,sBArB9B/lB,QACKC,OAAM,aACNqmB,QAAO,sBAAwBV,qBAEpCA,oBAAmBhlB,SAAW,iBCPlC,WACI,YAQA,SAAS8a,eAAavb,WAAaomB,UAgB/B,QAAS3J,kBACL,GAAInU,QAAS8d,SAASC,MAClBC,SAAU,mCACV9lB,WAAY,2BACZ8R,MAAOtS,WAAUumB,QAErB,OAAOje,QAGX,QAAS8W,oBAAmB9B,YAAaoB,YAAavY,kBAAmB7J,qBACrE,GAAIkhB,WACArX,kBAAmB,WAAc,MAAOA,oBACxCtH,YAAa,WAAY,MAAOvC,qBAAoBuB,WACpDuI,YAAa,WAAY,MAAO,6BAChCC,cAAe,WACX,OACIiX,YAAaA,YACboB,YAAaA,YACb9hB,SAAUuJ,kBAAkBjJ,gBAC5Be,cAAekI,kBAAkBjJ,mBAIzCoL,OAAS8d,SAASC,MAClBC,SAAU,uCACV9lB,WAAY,gCACZgmB,aAAc,QACdviB,QAASuZ,SACTle,OAAQU,WAAUumB,QAEtB,OAAOje,QAGX,QAAS6X,qBAAoBvS,KAAMzH,kBAAmB7J,qBAClD,GAAIkhB,WACArX,kBAAmB,WAAc,MAAOA,oBACxCC,YAAa,WAAY,MAAO,8BAChCvH,YAAa,WAAY,MAAOvC,qBAAoBuB,QAAQ+P,KAAKnH,kBACjEJ,cAAe,WACX,GAAIogB,UAAW5mB,QAAQoY,KAAKrK,KAG5B,OAFA6Y,UAAS7pB,SAAWuJ,kBAAkBtI,QAAQ+P,KAAKjH,cACnD8f,SAASxoB,cAAgBkI,kBAAkBpI,qBAAqB6P,KAAKjH,cAC9D8f,WAIXne,OAAS8d,SAASC,MAClBC,SAAU,uCACV9lB,WAAY,gCACZgmB,aAAc,QACdviB,QAASuZ,SACTlL,MAAOtS,WAAUumB,QAErB,OAAOje,QAGX,QAASiU,sBAAqBzB,MAC1B,GAAIxI,OAAQtS,WAAUumB,MACtBjU,OAAMrM,aAAe6U,IAErB,IAAIxS,QAAS8d,SAASC,MAClBC,SAAU,yCACV9lB,WAAY,8BACZ8R,MAAOA,OAEX,OAAOhK,QAGX,QAAS+T,qBAAoBvB,MACzB,GAAIxI,OAAQtS,WAAUumB,MACtBjU,OAAM3G,WAAamP,IAEnB,IAAIxS,QAAS8d,SAASC,MAClBC,SAAU,iCACV9lB,WAAY,sBACZ8R,MAAOA,OAEX,OAAOhK,QAGX,QAASC,iBAAgB+J,OACrB,GAAIhK,QAAS8d,SAASC,MAClBC,SAAU,6BACV9lB,WAAY,kBACZ8R,MAAOA,OAEX,OAAOhK,QAGX,QAAS4N,oBAAmB/P,mBACxB,GAAImM,OAAQtS,WAAUumB,MACtBjU,OAAMnM,kBAAoBA,iBAE1B,IAAImC,QAAS8d,SAASC,MAClBC,SAAU,oCACVI,UAAW,8CACXlmB,WAAY,yBACZ8R,MAAOA,OAEX,OAAOhK,QAGX,QAAS6N,sBACL,GAAI7N,QAAS8d,SAASC,MAClBC,SAAU,oCACV9lB,WAAY,yBACZ8R,MAAOtS,WAAUumB,QAErB,OAAOje,QAGX,QAASsb,6BAA4B+C,cACjC,GAAIrU,OAAQtS,WAAUumB,MACtBjU,OAAM3M,SAAWghB,YACjB,IAAIre,QAAS8d,SAASC,MAClBC,SAAU,yCACV9lB,WAAY,8BACZ8R,MAAOA,OAEX,OAAOhK,QAGX,QAAS6F,iBAAgBkJ,QAAShE,MAC9B,GAAIf,OAAQtS,WAAUumB,MACtBjU,OAAMsU,UAAYvT,KAAOA,KAAO,gBAChCf,MAAMuU,aAAexP,OAErB,IAAI/O,QAAS8d,SAASC,MAClBC,SAAU,6BACVhU,MAAOA,OAGX,OAAOhK,QAGX,QAASwe,kBACL,MAAOV,UAASU,iBAvJpB,OACIrK,eAAgBA,eAChB2C,mBAAoBA,mBACpBe,oBAAqBA,oBACrB5D,qBAAsBA,qBACtBF,oBAAqBA,oBACrB9T,gBAAiBA,gBACjB2N,mBAAoBA,mBACpBC,mBAAoBA,mBACpByN,4BAA6BA,4BAC7BzV,gBAAiBA,gBAEjB2Y,eAAgBA,gBAnBxBjnB,QACKC,OAAM,aACNqmB,QAAO,gBAAkB5K,eAE9BA,cAAa9a,SAAW,aAAe,eCP3C,WACI,YAeA,SAAS8D,cACLuC,MACAC,2BACAlG,GACA0E,KACA+B,QACAyf,KACA7f,YACAgF,qBAgBA,QAAS1H,mBACL,GAAIwiB,YAAanmB,GAAGiiB,QAChBmE,mBAAqBpmB,GAAGiiB,OA0B5B,OAxBKxb,SAAQS,OAqBTif,WAAW/iB,UACXgjB,mBAAmBhjB,WArBnBiD,YACK/F,MACAwD,KAAK,SAAUoG,KACZ,MAAIA,KAAI1N,MAAQ0N,IAAI1N,KAAK0K,OACrBT,QAAQ+B,OAAO0B,IAAI1N,KAAK0K,OACjBmE,oBAAoB/K,OAEpBN,GAAGc,WAGjBgD,KAAK,SAAUoG,KACZzD,QAAQwH,OAAO/D,IAAI1N,MACnB2pB,WAAW/iB,UACXgjB,mBAAmBhjB,YAb3BiD,SAeW,WACH8f,WAAWrlB,SACXslB,mBAAmBtlB,WAMxBd,GAAGsM,KAAK6Z,WAAWpG,QAASqG,mBAAmBrG,UAA/C/f,SAA+D,WAElE,MADA0E,MAAKqJ,IAAG,mCACD/N,GAAGc,WAIlB,QAASyH,OAAMtB,aACX,MAAOhB,OAAM2C,KAAI,UAAY1C,2BAA2Be,aAAc9G,QAAQ2D,KAAK,WAK/E,MAJA2C,SAAQ+B,OAAOvB,YAAYC,OAC3BmE,oBAAoB/K,MAAMwD,KAAK,SAAUoG,KACrCzD,QAAQwH,OAAO/D,IAAI1N,QAEhByK,YAAYC,QAI3B,QAASwB,aAAY2d,YACjB,MAAmB,aAAfA,WACO5d,UAAU3E,KAAK,SAAUvD,OAC5B,GAAI/D,OACA+D,MAAOA,MACPiJ,SAAUnD,YAAYyN,kBAE1B,OAAO7N,OAAM2C,KAAI,mBAAqB1C,2BAA2B1J,MAAO2D,UAGrEH,GAAGc,SAIlB,QAAS8P,QAAO3G,QAASpJ,OACjBqlB,KAAII,UAAY,GAChBC,eAEAC,OAAOlT,MACPmT,aAAaxc,QAASpJ,OAE1BoF,MAAM2C,KAAI,YAAa9E,KAAKmG,QAASpJ,OAEzC,QAAS4lB,cAAaxc,QAASpJ,OAC3B,GAAIuS,MACJoT,QAAOlT,KAAKC,KAAI,QAAU,WACtBH,MAAQE,KAAKF,MAAMsT,kBACnBtT,MAAMuT,UAAU7iB,KAAKmG,QAASpJ,SAGtC,QAAS0lB,gBACDL,KAAKrS,mBACLqS,KAAKtV,SAOb,QAASnI,WACL,MAAOyd,MACFU,iBACA9iB,KAAK,SAAUkB,UACZ,MAAwB,cAApBA,SAAStE,OACFV,GAAGgD,KAAKgC,UAERkhB,KAAK3d,MAAMvJ,QAAQkc,MAAQzJ,MAAO,YAGhD3N,KAAK,SAAUkB,UACZ,MAAwB,cAApBA,SAAStE,OACFV,GAAGgD,KAAKgC,SAAS6hB,aAAaC,aAE9B9mB,GAAGc,WAbfolB,SAgBI,SAAUrlB,OACb6D,KAAK7D,MAAK,QAAUA,SAIhC,QAASwS,eACL,GAAI0T,UAAWC,EAAEC,UAIjB,OAHI3T,OACAyT,SAAS3jB,QAAQkQ,MAEdyT,SAAShH,UA5HpB,GAAI5f,SACAC,SACIgH,eAAgB,oDAIxB,QACIzD,gBAAiBA,gBACjB4E,MAAOA,MACPG,YAAaA,YACbkI,OAAQA,OACRyC,YAAaA,aAlCrBrU,QAAQC,OAAM,aAAcqmB,QAAO,eAAiB5hB,cAEpDA,aAAY9D,SACR,QACA,6BACA,KACA,OACA,UACA,OACA,cACA,0BCbR,WACI,YAQA,SAAS0D,oBAAkB2C,MAAQI,aAK/B,QAAS/F,OACL,GAAIZ,KAAM,iCAAmC2G,YAAYyN,iBACzD,OAAO7N,OACF3F,IAAIZ,KACJoE,KAAK,SAAU+J,QACZ,MAAOA,QAAOrR,OAT1B,OACI8D,IAAKA,KARbtB,QACKC,OAAM,aACNqmB,QAAO,qBAAuBhiB,oBAEnCA,mBAAkB1D,SAAW,QAAU,kBCP3C,WACI,YAQA,SAASgW,yBAAuB3P,OAK5B,QAAS8S,aACL,GAAIrZ,KAAM,kCAEV,OAAOuG,OACL3F,IAAIZ,KACJoE,KAAK,SAAU+J,QACT,MAAOA,QAAOrR,OAV1B,OACIuc,UAAWA,WARnB/Z,QACKC,OAAM,aACNqmB,QAAO,0BAA4B1P,yBAExCA,wBAAuBhW,SAAW,YCPtC,WACI,YAQA,SAASsnB,mBAAiB9nB,UAAYC,SAmBlC,QAAS8nB,YAAWvmB,MAChB,GAAGxB,UAAWwB,SAAWA,KACrB,MAAOwmB,uBAEP,IAAIC,kBAAmBjoB,UAAU+M,SAASL,IAM1C,OALIub,kBACAjoB,UAAUwB,KAAKA,MAAMuL,QAASL,KAAMub,mBAEpCjoB,UAAUwB,KAAKA,MAAMuL,WAElBmb,aAIf,QAASlf,0BACL+e,WAAU,iBAGd,QAASI,4BACLJ,WAAU,2BAGd,QAAS3R,kBACL2R,WAAU,KAGd,QAASK,gBACLnoB,QAAQooB,QAAQC,OAGpB,QAAS7W,4BACLsW,WAAU,mBAjDd,GAAIC,wBAAyB,EACzBE,aAAe,CAEnB,QACIlf,uBAAwBA;AACxBmf,yBAA0BA,yBAC1B/R,eAAgBA,eAChBgS,aAAcA,aACd3W,yBAA0BA,yBAE1B8W,YAAaR,YAjBrBnoB,QACKC,OAAM,aACNqmB,QAAO,oBAAsB4B,mBAElCA,kBAAiBtnB,SAAW,YAAc,cCP9C,WACI,YAQA,SAASgoB,qBAAmBljB,MAaxB,QAASkC,oBAAmBihB,iBACxBpW,MAAQoW,gBAGZ,QAASC,MAAKC,KACVC,KAAI,aAAeD,KAGvB,QAAS9d,SAAQ8d,KACbC,KAAI,gBAAkBD,KAG1B,QAASlnB,OAAMknB,IAAK/iB,UAChBgjB,KAAI,eAAiBD,IAAK/iB,UAG9B,QAASsF,MAAKyd,IAAK/iB,UACfgjB,KAAI,gBAAkBD,IAAK/iB,UAG/B,QAASoF,qBACLqH,MAAMjH,kBAAmB,EACzBiH,MAAM/G,gBAAkB,GACxB+G,MAAMhH,kBAAoB,KAG9B,QAASud,MAAKC,WAAYC,SAAUljB,UAC5BmjB,eACA/d,oBACAqH,MAAMhH,kBAAoBwd,WAC1BxW,MAAM/G,gBAAkBwd,SACpBljB,UACAN,KAAKqJ,IAAI/I,UAEbyM,MAAMjH,kBAAmB,GAKjC,QAASR,UAASoe,WACVD,cACA1W,MAAK9F,OAAQyc,UAAWhe,mBAIhC,QAAS+d,cACL,QAAK1W,QACD/M,KAAK7D,MAAK,uFACH,GA5Df,GAAI4Q,MAEJ,QACIrH,kBAAmBA,kBACnBxD,mBAAoBA,mBACpByhB,SAAUP,KACV/gB,YAAakD,QACbjD,UAAWnG,MACXgG,SAAUyD,KACVN,SAAUA,UAhBlBhL,QACKC,OAAM,aACNqmB,QAAO,sBAAwBsC,qBAEvCA,oBAAmBhoB,SAAW,WCP/B,WACI,YAQA,SAAS4D,wBAAsByC,MAAQI,aAKnC,QAAS/F,OACL,GAAIZ,KAAM,+BAAiC2G,YAAYyN,iBACvD,OAAO7N,OACF3F,IAAIZ,KACJoE,KAAK,SAAU+J,QAAU,MAAOA,QAAOrR,OARhD,OACI8D,IAAKA,KARbtB,QACKC,OAAM,aACNqmB,QAAO,yBAA2B9hB,wBAEvCA,uBAAsB5D,SAAW,QAAU,kBCP/C,WACI,YAQA,SAASkW,wBAAsB7P,MAAQjG,IAMnC,QAASiO,QAAOlB,MACZ,GAAIrN,KAAM,iBAAmBqN,KAAK5D,EAClC4D,MAAKub,QAAUC,KAAKC,KAEpB,IAAIzB,UAAW/mB,GAAGiiB,OAOlB,OANAhc,OAAMwiB,IAAI/oB,IAAKqN,MAAMjJ,KAAK,SAAU+J,QAChCkZ,SAAS3jB,QAAQyK,OAAOrR,OACzB,WACCuqB,SAASjmB,WAGNimB,SAAShH,QAGpB,QAASzF,uBAAsBvN,MAC3B,MAAO,UAAS2b,cACZ,OACIxS,YAAawS,aACbxb,QAASH,KAAKpR,MAAQoR,KAAKG,QAAQvR,KACnCgd,MAAO,MACPY,OAAQxM,KAAKwM,OAASxM,KAAKwM,OAAS,EACpCvb,YAAa+O,KAAK/O,YAAc+O,KAAK/O,YAAc,KACnD4W,YAAa7H,KAAK6H,YAAc7H,KAAK6H,YAAc,GACnD+T,QAASJ,KAAKC,MACdF,QAASC,KAAKC,QA7B1B,OACIva,OAAQA,OACRqM,sBAAuBA,uBAT/Btb,QACKC,OAAM,aACNqmB,QAAO,yBAA2BxP,wBAEvCA,uBAAsBlW,SAAW,QAAU,SCP/C,WACI,YAQA,SAASiW,oBAAkB5P,MAAQjG,GAAIyG,SAmBnC,QAAS+B,QAAOvK,MACZ,GAAIyB,KAAM,gBAENwW,aACA/M,GAAI,KACJlL,KAAMA,KACN0Y,MAAO,KACPmE,QAAQ,EACRO,MAAO,GACPiN,QAASC,KAAKC,MAGlB,OAAOviB,OAAM2C,KAAKlJ,IAAKwW,aAS3B,QAAS5V,OACL,GAAIZ,KAAM,eAEV,OAAOuG,OACF3F,IAAIZ,KACJoE,KAAK,SAAU+J,QACZ,MAAOA,QAAOrR,OAU1B,QAASyR,QAAOiI,aACZ,GAAIxW,KAAM,iBAAmBwW,YAAY/M,EAGzC,OADA+M,aAAYoS,QAAUC,KAAKC,MACpBviB,MAAMwiB,IAAI/oB,IAAKwW,aAU1B,QAAS0S,SAAQ1S,YAAajM,QAASpJ,OACnC,GAAInB,KAAM,iBAAmBwW,YAAY/M,EAEzC+M,aAAYoS,QAAUC,KAAKC,MAC3BviB,MAAAA,UAAavG,KAAKoE,KAAKmG,QAASpJ,OAMpC,QAASgoB,iBACL,GAAI9B,UAAW/mB,GAAGiiB,OAmBlB,OAlBA3hB,OACKwD,KAAK,SAAUglB,OACPA,OAA0B,IAAjBA,MAAM7sB,QAChB8qB,SAASjmB,QAGb,IAAIgK,YAAage,MAAMrQ,OAAO,SAAUwB,MACpC,MAAOA,MAAKa,SACbiO,KAEAje,YACCic,SAAS3jB,QAAQ0H,YAEjBic,SAASjmB,WAbrBR,SAgBWymB,SAASjmB,QAEbimB,SAAShH,QAOpB,QAAS1J,qBAAoBH,aACzB,GAAIxW,KAAM,iBAAmBwW,YAAY/M,GAAK,QAC9C,OAAOlD,OACF3F,IAAIZ,KACJoE,KAAK,SAAU+J,QACZ,MAAOA,QAAOrR,OAU1B,QAASoa,MAAKV,YAAa8S,cACvB9S,YAAYoS,QAAUC,KAAKC,KAC3B,IAAItoB,UACAS,OAAQ,OACRjB,IAAK,qBACLU,SACIG,MAASkG,QAAQlG,OAErB/D,MACIysB,eAAgB/S,YAChB8S,aAAcA,aACdE,cAAc,GAItB,OAAOjjB,OAAM/F,SAAS4D,KAAK,SAASkB,UAChC,MAAGA,UAASxI,KACDwI,SAASxI,KAAK2sB,cAajC,QAASpe,OAAM2d,cACX,GAAIhpB,KAAM,qCAAuCgpB,YACjD,OAAOziB,OAAM2C,KAAKlJ,KAStB,QAASoM,MAAKvL,OACV,GAAIb,KAAM,4BAA8Ba,KACxC,OAAO0F,OAAM2C,KAAKlJ,KAWtB,QAAS8X,+BAA8Bb,MAAOO,aAC1C,MAAOP,OAAMyB,UAAU,SAASza,GAC5B,MAAGA,GAAEuP,QACMvP,EAAEuP,UAAYgK,aAAgBvZ,EAAEuP,QAAQvR,MAAQgC,EAAEuP,QAAQvR,OAASub,cAEtEvZ,EAAEuZ,aACCvZ,EAAEuZ,cAAgBA,cArLrC,OACI1O,OAAQA,OACRlI,IAAKA,IACL2N,OAAQA,OACRmb,SAAQR,QACRC,cAAeA,cACfxS,oBAAqBA,oBACrBO,KAAMA,KACN7L,MAAOA,MACPe,KAAMA,KACN0L,8BAA+BA,+BAjBvCxY,QACKC,OAAM,aACNqmB,QAAO,qBAAuBzP,oBAEnCA,mBAAkBjW,SAAW,QAAU,KAAM,cCPjD,WACI,YAQA,SAAS0c,gBAAcrW,OAanB,QAASkG,QAAO4Q,YACZ,GAAIrd,KAAM2pB,QAAU,uBAAyBC,UAAUvM,WAEvD,OAAO9W,OACL3F,IAAIZ,KACJoE,KAAK,SAAU+J,QACZ,MAAOA,QAAOrR,OAIvB,QAAS+sB,gBAAetf,QAASpJ,OAC7B,GAAInB,KAAM2pB,QAAU,eACpBpjB,OAAM3F,IAAIZ,KAAKoE,KAAKmG,QAASpJ,OAGjC,QAAS+M,QAAO3D,QAASpJ,OACrB,GAAInB,KAAM2pB,QAAU,MACpBpjB,OAAM3F,IAAIZ,KAAKoE,KAAKmG,QAASpJ,OAGjC,QAAS7D,SAAQmM,GAAIc,QAASpJ,OAC1B,GAAInB,KAAM2pB,QAAU,IAAMlgB,EAC1BlD,OAAM3F,IAAIZ,KAAKoE,KAAKmG,QAASpJ,OAGjC,QAAS2H,QAAO0E,SACZ,MAAOjH,OAAM2C,KAAKygB,QAASnc,SAG/B,QAASe,QAAOf,SACZ,GAAIxN,KAAM2pB,QAAU,IAAMnc,QAAQvR,IAClC,OAAOsK,OAAMwiB,IAAI/oB,IAAKwN,SAG1B,QAASsc,SAAQtc,QAASjD,QAASpJ,OAC/B,GAAInB,KAAM2pB,QAAU,IAAMnc,QAAQvR,IAClCsK,OAAAA,UAAavG,KAAKoE,KAAKmG,QAASpJ,OAhDpC,GAAIwoB,SAAU,kBAEd,QACIld,OAAQA,OACRod,eAAgBA,eAChB3b,OAAQA,OACR5Q,QAASA,QACTwL,OAAQA,OACRyF,OAAQA,OACRmb,SAAQI,SAhBhBxqB,QACKC,OAAM,aACNqmB,QAAO,iBAAmBhJ,gBAE/BA,eAAc1c,SAAW,YCP7B,WACI,YAQA,SAASggB,6BAA2B3Z,OAQhC,QAAS3F,OACL,GAAIZ,KAAM,iCAAmC+pB,WAC7C,OAAOxjB,OAAM3F,IAAIZ,KAGrB,QAAS8pB,SAAQ1kB,SAAUmF,QAASpJ,OAChC,GAAInB,KAAM,qBAAuBoF,SAASoI,QAAQvR,IAClDsK,OAAAA,UAAavG,IAAKoF,UAAUhB,KAAKmG,QAASpJ,OAd9C,GAAI4oB,aAAc,IAElB,QACInpB,IAAKA,IACLuE,aAAc2kB,SAXtBxqB,QACKC,OAAM,aACNqmB,QAAO,8BAAgC1F,6BAE5CA,4BAA2BhgB,SAAW,YCP1C,WACC,YAQG,SAASS,SAAOsG,WAAa8G,qBACzBrR,KAAKmE,MAAQyd,KAAK0L,SAAS1W,SAAS,IAAI2W,OAAO,GAE/CvtB,KAAKoM,OAAS,SAAUtB,OAAS9K,KAAK8K,MAAQA,OAC9C9K,KAAKuU,QAAU,WAAcvU,KAAK8K,MAAQ,MAE1C9K,KAAK6R,OAAS,SAAUwB,UACpBrT,KAAKqT,SAAWA,SAChB9I,WAAW4C,IAAIkG,SAASjG,UACxBiE,oBAAoBS,qBAAqBT,oBAAoBU,kBAAkB+W,gBAf1FlmB,QACEC,OAAM,aACNqmB,QAAO,UAAYjlB,SAElBA,QAAOT,SAAW,aAAe,0BCPrC,WACI,YAQA,SAASgqB,aAAW3jB,MAAQU,YAcxB,QAAS6B,QAAOtB,MAAO+C,QAASpJ,OAC5B,GAAIyP,OACApJ,MAAOA,MACPsC,SAAUsG,cACV+Z,gBAAgB,EAGpB5jB,OAAM2C,KAAKlJ,IAAM,UAAW4Q,MAAMxM,KAAKmG,QAASpJ,OAGpD,QAASoN,QAAOqC,MACZ,MAAOrK,OAAMwiB,IAAI/oB,IAAK4Q,MAG1B,QAAShQ,OACL,MAAO2F,OAAM3F,IAAIZ,KAGrB,QAASknB,gBAAe3c,QAASpJ,OAC7BoF,MAAM3F,IAAIZ,IAAM,gBAAgBoE,KAAKmG,QAASpJ,OAGlD,QAASiP,eACL,MAAOnJ,YAAW4C,MAAQ5C,WAAW4C,MAAQ5C,WAAWmjB,mBAG5D,QAASrZ,gBAAesZ,YAAahb,YAAa9E,QAASpJ,OACvDoF,MAAMwiB,IAAI/oB,IAAM,+BAAiCsqB,mBAAmBD,aAAe,gBAAkBC,mBAAmBjb,cAAcjL,KAAKmG,QAASpJ,OAGxJ,QAASwJ,eAAcnD,MAAO+C,QAASpJ,OACnCoF,MAAM2C,KAAKlJ,IAAM,wBAA0BwH,OAAOpD,KAAKmG,QAASpJ,OAEpE,QAAS6P,YAAWvJ,SAAU8C,QAASpJ,OACnCoF,MAAAA,UAAavG,IAAM,wBAAyBsqB,mBAAmB7iB,WAAWrD,KAAKmG,QAAQpJ,OA/C3F,GAAInB,KAAM,eAEV,QACI8I,OAAQA,OACRyF,OAAQA,OACR3N,IAAKA,IACLsmB,eAAgBA,eAChB9S,gBAAiBhE,YACjBW,eAAgBA,eAChBpG,cAAeA,cACfqG,WAAYA,YAjBpB1R,QACKC,OAAM,aACNqmB,QAAO,cAAgBsE,aAE5BA,YAAWhqB,SAAW,QAAU,iBCPpC,WACI,YAQA,SAASmW,qBAAmB9P,MAAQjG,GAAIb,YAYpC,QAASmB,OAEL,MADAymB,UAAW/mB,GAAGiiB,QACPhc,MACF3F,IAAIZ,KACJoE,KAAK,SAASkB,UAIX,MAHAyK,UAAWzK,SAASxI,KACpBuqB,SAAS3jB,UACTjE,WAAUiN,MAAM,sBAAwBqD,UACjCzK,WAKnB,QAASgH,eAEL,MADI+a,WAAYzmB,MACTymB,SAAShH,QAAQjc,KAAK,WAAW,MAAO2L,YAGnD,QAASxB,QAAOyB,cACZ,MAAOzJ,OACFwiB,IAAI/oB,IAAKgQ,cACT5L,KAAK,SAASkB,UAGX,MAFAyK,UAAWC,aACXvQ,WAAUiN,MAAM,sBAAwBqD,UACjCzK,WAUnB,QAASgV,eAAc9D,aACnB,MAAOjQ,OACFwiB,IAAI/oB,IAAM,iBAAkBwW,aAC5BpS,KAAK,SAASkB,UAGX,MAFAyK,UAASwa,oBAAsB/T,YAAY/M,GAC3ChK,WAAUiN,MAAM,sBAAwBqD,UACjCzK,WAnDnB,GAAItF,KAAM,uBACN+P,YACAsX,SAAW,IAEf,QACIzmB,IAAKA,IACL0L,YAAaA,YACbiC,OAAQA,OACR+L,cAAeA,eAfvBhb,QACKC,OAAM,aACNqmB,QAAO,sBAAwBvP,qBAEpCA,oBAAmBnW,SAAW,QAAU,KAAM,iBCPlD,WACI,YAQA,SAAS0L,kBAAgB5G,KAAOvF,WAAY+qB,WAAY7pB,QAASqG,UAoE7D,QAAShH,KAAIyqB,GACT,GAAIC,GAAI5D,OAAO6D,QACf,QAAwB,WAAfD,EAAEE,SAAyB,SAAW,SAAWF,EAAEG,KAAOJ,EAGvE,QAASK,UAASC,SACd,OAAQA,SACJ,IAAK,UACDtrB,WAAUiN,MAAM,oBAChB,MACJ,KAAK,eACDjN,WAAUiN,MAAM,wBAChB,MACJ,KAAK,oBACDjN,WAAUiN,MAAM,8BAK5B,QAASse,UAAS3C,KACd,OAAQA,IAAI0C,SACR,IAAK,UACDtrB,WAAUiN,MAAM,oBAChB,MACJ,KAAK,eACDjN,WAAUiN,MAAM,wBAA0B2b,IAAIvrB,KAC9C,MACJ,KAAK,oBACD2C,WAAUiN,MAAM,4BAA8B2b,IAAIvrB,OAK9D,QAASyiB,UAAS8I,KACd,OAAQA,IAAI0C,SACR,IAAK,UACDtrB,WAAUiN,MAAM,oBAAsB2b,IAAIvrB,KAAKb,KAC/C,MACJ,KAAK,eACDwD,WAAUiN,MAAM,wBAA0B2b,IAAIvrB,KAAK2M,GACnD,MACJ,KAAK,yBACDhK,WAAUiN,MAAM,yBAA2B2b,IAAIvrB,KAC/C,MACJ,SAEI2C,WAAUiN,MAAM,0BAjH5B,GAAIue,YAAa,IAEjBvuB,MAAKuQ,eAAiB,WACfge,aACCjmB,KAAKojB,KAAI,gCACT6C,WAAWC,OAAM,KAIzBxuB,KAAK6P,iBAAmB,WACpB,GAAI4e,MAAOzuB,IACRuuB,cACCjmB,KAAKojB,KAAI,iCACT6C,WAAWC,OAAM,IAGrBlmB,KAAKojB,KAAI,+BACT6C,WAAaT,WACTxqB,IAAG,eAEPirB,WAAWG,KAAK9rB,QAAQ+rB,QACpBxqB,MAAOF,QAAQE,MACfyqB,GAAI,MACJ1a,KAAMjQ,QAAQ6G,SAGlByjB,WAAWM,UAAU,SAAUzU,SAC3B,GAAIA,QAAQha,KAAM,CACd,GAAIurB,KAAM/oB,QAAQksB,SAAS1U,QAAQha,KAInC,QAFAkI,KAAKqJ,IAAG,wBAA0Bga,KAE1BA,IAAIvV,MACR,IAAK,SACDgY,SAASzC,IAAI0C,QACb,MACJ,KAAK,SACDC,SAAS3C,IACT,MACJ,KAAK,SACD9I,SAAS8I,IACT,MACJ,SACIrjB,KAAK7D,MAAK,0BAA4BknB,IAAIvV,UAM1DmY,WAAWQ,OAAO,WAAczmB,KAAKojB,KAAI,6BAEzC6C,WAAWS,QAAQ,WACfjsB,WAAUiN,MAAM,cAChB1H,KAAKojB,KAAI,sBACoB,IAA1B6C,WAAWU,YACV3kB,SAAS,WACLmkB,KAAK5e,oBACP,OAIV0e,WAAWW,QAAQ,WACf5mB,KAAK7D,MAAK,+BACV1B,WAAUiN,MAAM,iBAtE5BpN,QACKC,OAAM,aACNqmB,QAAO,mBAAqBha,kBAEjCA,iBAAgB1L,SAAW,OAAS,aAAc,aAAc,UAAW,eCP/E,WACI,YAQA,SAASoW,UAASH,oBACd,GAAI0V,UAAWnvB,IAEfmvB,UAAS3U,KAAO,SAAS4U,QAASC,QAAS5U,SAAUC,WAAYC,OAAQC,UAErE,IADA,GAAIhb,GAAIwvB,QAAQvvB,OACVD,KAAK,CACP,GAAI0vB,SAAUF,QAAQxvB,GAClBuS,IAAMgd,SAAS/T,8BAA8BiU,QAAS5U,SAAS6U,SAEnE,IAAGnd,IAAM,EACLid,QAAQhd,OAAOxS,EAAG,OACf,CACH,GAAI2b,SAAU8T,QAAQld,IACtBuI,YAAW4U,QAAS/T,UAI5BZ,OAAOyU,QAASC,SAChBA,QAAQ9uB,QAAQ,SAASgb,QAASC,cAC9BZ,SAASwU,QAAS7T,QAASC,iBAKnC2T,SAAS/T,8BAAgC3B,mBAAmB2B,8BA9BhExY,QACKC,OAAM,aACNqmB,QAAO,WAAatP,UAEzBA,SAAQpW,SAAW","file":"ueberliste.js","sourcesContent":["/* exported CategoriesCatalog */\r\nfunction CategoriesCatalog(categoriesList, measurementsCatalog) {\r\n\t'use strict';\r\n\r\n var upperCategoryIds = [100000, 200000, 300000, 400000, 500000, 600000, 700000];\r\n\r\n this.categories = [];\r\n this.defaultCategory = {};\r\n this.upperCategories = [];\r\n this.measurementsCatalog = measurementsCatalog;\r\n\r\n function getImgId (pmId) {\r\n return pmId / 100000;\r\n }\r\n\r\n function getIconById (pmId) {\r\n return 'category_' + getImgId(pmId) + '_icon_medium.png';\r\n }\r\n\r\n this.processData = function (data) {\r\n var categories = [];\r\n var upperCategories = [];\r\n if (!data || data.constructor !== Array) {\r\n return;\r\n }\r\n data.forEach(function (category) {\r\n category.icon = getIconById(category.pmId);\r\n\r\n categories.push(category);\r\n if (upperCategoryIds.indexOf(category.pmId) > -1) {\r\n upperCategories.push(category);\r\n }\r\n });\r\n this.categories = categories;\r\n this.upperCategories = upperCategories;\r\n this.defaultCategory = this.upperCategories[0];\r\n };\r\n\r\n this.processData(categoriesList);\r\n\r\n this.getIconById = getIconById;\r\n\r\n this.getColorById = function (pmId) {\r\n var category = this.getById(pmId);\r\n return category ? category.defaultColor : 'transparent';\r\n };\r\n\r\n this.getById = function(pmId) {\r\n if (!this.categories || this.categories === []) {\r\n return null;\r\n }\r\n\r\n return findMatchingCategoryById(this.categories, pmId);\r\n\r\n /*\r\n find is EcmaScript 6 and not available in Internet Explorer!\r\n https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find\r\n\r\n return this.categories.find(function (category) {\r\n return category.pmId === pmId;\r\n });*/\r\n\r\n };\r\n\r\n function findMatchingCategoryById(categories, pmId) {\r\n var category = null;\r\n\r\n for (var i = 0; i < categories.length; i++) {\r\n var c = categories[i];\r\n if(c.pmId === pmId) {\r\n category = c;\r\n break;\r\n }\r\n }\r\n\r\n return category;\r\n }\r\n\r\n this.getUpperCategoryById = function (pmId) {\r\n var category = this.getById(pmId);\r\n return this.getUpperCategory(category);\r\n };\r\n\r\n this.getUpperCategory = function (category) {\r\n var upperCategory = category;\r\n if (!upperCategory) {\r\n return null;\r\n }\r\n while (upperCategory.parentCategory) {\r\n upperCategory = this.getById(upperCategory.parentCategory);\r\n if (!upperCategory) {\r\n return null;\r\n }\r\n }\r\n return upperCategory;\r\n };\r\n\r\n this.getMeasurements = function (category) {\r\n function containsMeasurement(a, obj) {\r\n return a.some(function(e) { return e.shortcut === obj.shortcut; });\r\n }\r\n\r\n // get category from catalog to ensure the correct translation\r\n //category = this.getById(category.pmId);\r\n var measurements = !category || category.measurements.length === 0 ? measurementsCatalog.measurements : category.measurements;\r\n if (!containsMeasurement(measurements, measurementsCatalog.emptyMeasurement)) {\r\n measurements.unshift(measurementsCatalog.emptyMeasurement);\r\n }\r\n\r\n // name field is necessary for the dropdown component\r\n measurements.forEach(function(measurement) {\r\n measurement.name = measurement.shortcut;\r\n });\r\n\r\n return measurements;\r\n };\r\n\r\n}\r\n\r\n","/* exported MeasurementsCatalog */\r\nfunction MeasurementsCatalog(measurementsList) {\r\n\t'use strict';\r\n\r\n this.measurements = [];\r\n this.emptyMeasurement = {};\r\n\r\n this.processData = function (data) {\r\n var measurements = [];\r\n if (!data || data.constructor !== Array) {\r\n return;\r\n }\r\n\r\n this.emptyMeasurement = {\r\n comment: '',\r\n name: '–',\r\n plural: '–',\r\n shortcut: '–'\r\n };\r\n measurements.push(this.emptyMeasurement);\r\n\r\n data.forEach(function (measurement) {\r\n measurement.name = measurement.shortcut;\r\n measurements.push(measurement);\r\n });\r\n this.measurements = measurements;\r\n };\r\n\r\n this.processData(measurementsList);\r\n\r\n this.isEmptyMeasurement = function (measurement) {\r\n if (!measurement) {\r\n return true;\r\n }\r\n return measurement === this.emptyMeasurement;\r\n };\r\n\r\n this.getById = function (pmId) {\r\n var measurement = this.measurements.find(function (measurement) {\r\n return measurement.pmId === pmId;\r\n });\r\n return measurement ? measurement : this.emptyMeasurement;\r\n };\r\n}\r\n","(function () {\r\n 'use strict';\r\n\r\n\tvar dependencies = [\r\n 'überliste',\r\n 'ezfb'\r\n ];\r\n\r\n angular\r\n \t.module('wrapper', dependencies)\r\n\t\t.run(function ($rootScope, $location, $window) {\r\n\t\t\t// Push a tracking event to Google Analytics\r\n\t\t\tvar unregisterViewContentLoaded = $rootScope.$on('$viewContentLoaded', function () {\r\n\t\t\t\t$window.ga('send', 'pageview', {page: $location.url()});\r\n\t\t\t});\r\n\r\n\t\t\t$rootScope.$on('$destroy', function(){\r\n\t\t\t\tunregisterViewContentLoaded();\r\n\t\t\t});\r\n\t\t})\r\n .controller('WrapperController', WrapperController);\r\n\r\n WrapperController.$inject = ['$scope'];\r\n\r\n function WrapperController($scope) {\r\n $scope.isNotIE = !/msie|trident|edge/g.test(navigator.userAgent.toLowerCase());\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n\tvar dependencies = [\r\n 'ngCookies',\r\n 'pascalprecht.translate',\r\n 'ngRoute',\r\n 'ngWebSocket',\r\n 'ngDialog',\r\n 'ngAnimate',\r\n 'ngTouch',\r\n 'ui.bootstrap',\r\n 'duScroll'\r\n ];\r\n\r\n angular\r\n \t.module('überliste', dependencies)\r\n\t\t.run(function ($rootScope, $location, $window, $anchorScroll) {\r\n\t\t\t// Scroll to top in the new page\r\n\t\t\tvar unregisterLocationChangeSuccess = $rootScope.$on('$locationChangeSuccess', function () {\r\n\t\t\t\t$anchorScroll();\r\n\t\t\t});\r\n\r\n\t\t\t$rootScope.$on('$destroy', function(){\r\n\t\t\t\tunregisterLocationChangeSuccess();\r\n\t\t\t});\r\n\t\t});\r\n})();\r\n","(function() {\r\n\t'use strict';\r\n\r\n\tangular\r\n\t\t.module('überliste')\r\n .factory('httpInterceptor', HttpInterceptor)\r\n .config(['$httpProvider', function ($httpProvider) {\r\n $httpProvider.interceptors.push('httpInterceptor');\r\n }]);\r\n\r\n HttpInterceptor.$inject = ['$q', '$rootScope', '$location', '$injector'];\r\n\r\n function HttpInterceptor($q, $rootScope, $location, $injector) {\r\n return {\r\n 'request': function(config) {\r\n if (config.url.indexOf('api/v1') > -1) {\r\n if (!config.headers) {\r\n config.headers = {};\r\n }\r\n\r\n var Session = $injector.get('Session'); // Inject at runtime or else a circular dependency is created\r\n\r\n config.headers.token =\r\n config.headers.token ?\r\n config.headers.token :\r\n Session.token;\r\n }\r\n\r\n return config;\r\n },\r\n // Error provider that redirects to login page on unauthenticated requests\r\n 'responseError': function (rejection) {\r\n var status = rejection.status;\r\n var config = rejection.config;\r\n var method = config.method;\r\n var url = config.url;\r\n\r\n if ($location.path() !== '/' && status === 401) {\r\n $location.path('/loginexpired');\r\n } else {\r\n $rootScope.error = method + ' on ' + url + ' failed with status ' + status;\r\n }\r\n\r\n return $q.reject(rejection);\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .config(securityConfig);\r\n\r\n securityConfig.$inject = ['$httpProvider'];\r\n\r\n function securityConfig($httpProvider) {\r\n $httpProvider.defaults.withCredentials = true;\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .config(translateConfig);\r\n\r\n function translateConfig($translateProvider) {\r\n $translateProvider\r\n .useStaticFilesLoader({\r\n prefix: 'i18n/i18n-',\r\n suffix: '.json'\r\n })\r\n .uniformLanguageTag('bcp47')\r\n .registerAvailableLanguageKeys(['en', 'de', 'ru'], {\r\n 'en-US': 'en',\r\n 'en-DE': 'en',\r\n 'en-UK': 'en',\r\n 'en-GB': 'en',\r\n 'en-au': 'en',\r\n 'en-ca': 'en',\r\n\r\n 'de-DE': 'de',\r\n 'de-CH': 'de',\r\n 'de-at': 'de',\r\n 'de-lu': 'de',\r\n 'de-li': 'de',\r\n \r\n 'ru_RU': 'ru'\r\n })\r\n .determinePreferredLanguage()\r\n .fallbackLanguage('en')\r\n .useSanitizeValueStrategy('escapeParameters')\r\n .useCookieStorage();\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .config(routeConfig);\r\n\r\n function routeConfig($locationProvider, $routeProvider) {\r\n $locationProvider.html5Mode(true);\r\n $routeProvider\r\n .when('/', {\r\n templateUrl: 'template/partial/homepage.html',\r\n controller: 'HomepageController',\r\n resolveRedirectTo: init\r\n })\r\n .when('/shoppinglist', {\r\n templateUrl: 'template/partial/shoppingList.html',\r\n controller: 'ShoppingListController',\r\n resolve: {\r\n Measurements: ['MeasurementService', function(MeasurementService) {\r\n return MeasurementService.get();\r\n }],\r\n Categories: ['ProductCategoryService', function(ProductCategoryService) {\r\n return ProductCategoryService.get();\r\n }],\r\n Auth: ['LoginService', function(LoginService) {\r\n return LoginService.isAuthenticated();\r\n }]\r\n }\r\n })\r\n .when('/loginexpired', {\r\n templateUrl: 'template/partial/homepage.html',\r\n controller: 'HomepageController'\r\n })\r\n .when('/imprint', {\r\n templateUrl: 'template/partial/imprint.html',\r\n controller: 'HomepageController'\r\n })\r\n .when('/terms', {\r\n templateUrl: 'template/partial/terms.html',\r\n controller: 'HomepageController'\r\n })\r\n .when('/contact', {\r\n templateUrl: 'template/partial/contact.html',\r\n controller: 'HomepageController'\r\n })\r\n .when('/help', {\r\n templateUrl: 'template/partial/userManual.html',\r\n controller: 'HomepageController'\r\n })\r\n .when('/accountDeleted', {\r\n templateUrl: 'template/partial/homepage.html',\r\n controller: 'HomepageController'\r\n })\r\n .otherwise({\r\n redirectTo: '/'\r\n });\r\n }\r\n\r\n init.$inject = ['LoginService'];\r\n \r\n function init(LoginService) {\r\n return LoginService\r\n .isAuthenticated()\r\n .then(function () { return '/shoppinglist'; })\r\n .catch(function() { return undefined; });\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('wrapper')\r\n .config(facebookConfig);\r\n\r\n facebookConfig.$inject = ['ezfbProvider'];\r\n\r\n function facebookConfig(ezfbProvider) {\r\n ezfbProvider.setInitParams({\r\n appId: '285790838706044',\r\n xfbml: true,\r\n version: 'v2.7'\r\n });\r\n }\r\n})();\r\n\r\n","(function() {\r\n 'use strict';\r\n angular\r\n .module('wrapper')\r\n .config(['$compileProvider', function ($compileProvider) {\r\n $compileProvider.debugInfoEnabled(false);\r\n $compileProvider.commentDirectivesEnabled(false);\r\n $compileProvider.cssClassDirectivesEnabled(false);\r\n }]);\r\n})();","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('DeleteHistoryItemController', DeleteHistoryItemController);\r\n\r\n DeleteHistoryItemController.$inject = ['$scope', '$log', 'PurchaseHistoryEntryService'];\r\n\r\n function DeleteHistoryItemController($scope, $log, purchaseHistoryEntryService) {\r\n\r\n $scope.confirmDelete = confirmDelete;\r\n $scope.cancel = cancel;\r\n\r\n function confirmDelete() {\r\n\r\n purchaseHistoryEntryService.deleteByPmId($scope.purchase, function () {\r\n // broadcastingService.sendBroadcastMessage(broadcastingService.broadcastMessages.purchaseItemChanged);\r\n $scope.closeThisDialog();\r\n },\r\n function (response) {\r\n $log.error('Error: history item ' + $scope.purchase + ' couldn\\'t be deleted', response);\r\n });\r\n }\r\n\r\n function cancel() {\r\n $scope.closeThisDialog();\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('DeleteProductListController', DeleteProductListController);\r\n\r\n DeleteProductListController.$inject = ['$scope', '$log', 'ProductListService'];\r\n\r\n function DeleteProductListController($scope, $log, productListService) {\r\n $scope.confirmDelete = confirmDelete;\r\n $scope.cancel = cancel;\r\n\r\n function confirmDelete() {\r\n productListService.delete($scope.listToDelete, $scope.closeThisDialog, function (response) {\r\n $log.error('Error: productlist ' + $scope.listToDelete + ' couldn\\'t be deleted.', response);\r\n });\r\n }\r\n\r\n function cancel() {\r\n $scope.closeThisDialog();\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('EditProductListItemController', EditProductListItemController);\r\n\r\n function EditProductListItemController($scope, categoriesCatalog, measurement, dialogTitle, draftListItem) {\r\n var ctrl = this;\r\n\r\n ctrl.dialogTitle = dialogTitle;\r\n ctrl.categoriesCatalog = categoriesCatalog;\r\n ctrl.measurement = measurement;\r\n ctrl.draftListItem = draftListItem;\r\n ctrl.apply = function apply() {\r\n $scope.closeThisDialog(draftListItem);\r\n };\r\n ctrl.cancel = $scope.closeThisDialog;\r\n\r\n ctrl.onMeasurementSelect = function (measurement) {\r\n ctrl.measurement = measurement;\r\n draftListItem.measurement = measurement.pmId; // REST parameter\r\n draftListItem.measurementPmId = measurement.pmId; // UI parameter\r\n };\r\n\r\n ctrl.select = function (category) {\r\n draftListItem.category = category; // REST parameter\r\n draftListItem.categoryPmId = category.pmId; // UI parameter\r\n draftListItem.categoryName = category.name; // UI parameter\r\n draftListItem.upperCategory = category; // UI parameter\r\n draftListItem.defaultColor = ctrl.categoriesCatalog.getColorById(category.pmId); // UI parameter\r\n };\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('HomepageController', HomepageController);\r\n\r\n HomepageController.$inject = ['$scope', '$http', '$httpParamSerializerJQLike', '$location', '$routeParams', 'LoginService', 'UserService', 'NavigationService',\r\n 'NotificationService', 'DialogService','Session','$timeout', '$anchorScroll', '$translate'];\r\n\r\n function HomepageController($scope, $http, $httpParamSerializerJQLike, $location, $routeParams, loginService, userService, navigationService,\r\n notificationService, dialogService, session, $timeout, $anchorScroll, $translate) {\r\n notificationService.setControllerScope($scope);\r\n\r\n if ($location.path() === '/loginexpired') {\r\n notificationService.showWarn('session.expired');\r\n } else if ($routeParams.passwordchanged === 'true') {\r\n notificationService.showSuccess('forgot_password.password_changed');\r\n } else if ($routeParams.passwordchanged === 'false') {\r\n notificationService.showError('forgot_password.password_not_changed');\r\n } else if ($location.path() === '/accountDeleted') {\r\n notificationService.showSuccess('create_free_account_screen.delete_account_success');\r\n }\r\n\r\n $scope.credentials = {\r\n email: '',\r\n password: ''\r\n };\r\n\t var config = {\r\n\t\t headers : {\r\n\t\t\t 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'\r\n\t\t }\r\n\t };\r\n $scope.scrollToPosition = function(hash){\r\n $anchorScroll(hash);\r\n };\r\n $scope.openForgotPasswordDialog = function () {\r\n $scope.mode = 'FORGOT_PASSWORD';\r\n var dialog = dialogService.openLoginDialog($scope);\r\n dialog.closePromise.then(function () {\r\n $scope.dialogOpened = false;\r\n $scope.credentials.email = session.email;\r\n if($scope.$root.onPasswordReseted){\r\n notificationService.setControllerScope($scope);\r\n notificationService.showSuccess('forgot_password.forgot_password_success');\r\n }\r\n });\r\n };\r\n\r\n $scope.openRegistrationDialog = function () {\r\n $scope.mode = 'REGISTRATION';\r\n var dialog = dialogService.openLoginDialog($scope);\r\n dialog.closePromise.then(function () {\r\n $scope.dialogOpened = false;\r\n $scope.credentials.email = session.email;\r\n if($scope.$root.onRegistrationCompleted){\r\n notificationService.setControllerScope($scope);\r\n notificationService.showSuccess('create_free_account_screen.create_account_success');\r\n }\r\n });\r\n };\r\n $scope.onLoggedIn = function () {\r\n $scope.loginFailed = false;\r\n $scope.loginInProgress = false;\r\n navigationService.navigateToShoppingList();\r\n };\r\n\t\r\n\t $scope.onLoginFailed = function () {\r\n $scope.loginFailed = true;\r\n $scope.loginInProgress = false;\r\n \r\n notificationService.showError('login_panel.login_failed');\r\n };\r\n \r\n $scope.submit = function (credentials) {\r\n $scope.loginInProgress = true;\r\n loginService.login(credentials)\r\n .then(function (email) {\r\n session.create(email);\r\n\t $scope.onLoggedIn();\r\n }, $scope.onLoginFailed);\r\n };\r\n\r\n $scope.fbLogin = function () {\r\n $scope.loginInProgress = true;\r\n loginService\r\n .socialLogin('facebook')\r\n .then(loginService.isAuthenticated)\r\n .then($scope.onLoggedIn)\r\n .catch($scope.onLoginFailed);\r\n };\r\n $scope.googleSignIn = function(data){\r\n\t $http.post('/signin/google', $httpParamSerializerJQLike(data), config)\r\n\t \t.then(loginService.isAuthenticated)\r\n\t \t.then($scope.onLoggedIn)\r\n\t \t.catch($scope.onLoginFailed);\r\n };\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = false;\r\n $scope.selectedLang = {name:'', img:''};\r\n $scope.languageOptions = [\r\n {id:'de', name: 'uss.language_de', img: 'img/de.png'},\r\n {id:'en',name: 'uss.language_en', img: 'img/gb.png'},\r\n {id:'ru',name: 'uss.language_ru', img: 'img/ru.png'}\r\n ];\r\n \r\n $scope.selectedLanguage = function(){\r\n if(!localStorage.getItem('lang')){\r\n if(navigator.language.includes('de')){\r\n localStorage.setItem('lang','de');\r\n $scope.selectedLang = $scope.languageOptions[0];\r\n $scope.germanFlag = true;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = false;\r\n $translate.use('de');\r\n }\r\n else if(navigator.language.includes('ru')){\r\n localStorage.setItem('lang','ru');\r\n $scope.selectedLang = $scope.languageOptions[2];\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = true;\r\n $translate.use('ru');\r\n }\r\n else {\r\n localStorage.setItem('lang','en');\r\n $scope.selectedLang = $scope.languageOptions[1];\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = true;\r\n $scope.russianFlag = false;\r\n $translate.use('en');\r\n }\r\n }else {\r\n if(localStorage.getItem('lang') === 'de') {\r\n $scope.selectedLang = $scope.languageOptions[0];\r\n $scope.germanFlag = true;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = false;\r\n $translate.use('de');\r\n }\r\n if(localStorage.getItem('lang') === 'en'){\r\n $scope.selectedLang = $scope.languageOptions[1];\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = true;\r\n $scope.russianFlag = false;\r\n $translate.use('en');\r\n }\r\n if(localStorage.getItem('lang') === 'ru') {\r\n $scope.selectedLang = $scope.languageOptions[2];\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = true;\r\n $translate.use('ru');\r\n }\r\n }\r\n };\r\n $scope.selectedLanguage();\r\n $scope.enableListItems = false;\r\n $scope.enableList = function(){\r\n $scope.enableListItems = true;\r\n };\r\n $scope.languageSelection = function(language){\r\n $scope.enableListItems = false;\r\n localStorage.setItem('lang', language.id);\r\n $scope.selectedLang = language;\r\n switch (language.id) {\r\n case 'en':\r\n localStorage.setItem('lang', 'en');\r\n $scope.germanFlag = true;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = false;\r\n break;\r\n case 'de':\r\n localStorage.setItem('lang','de');\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = true;\r\n $scope.russianFlag = false;\r\n break;\r\n case 'ru':\r\n localStorage.setItem('lang','ru');\r\n $scope.germanFlag = false;\r\n $scope.englishFlag = false;\r\n $scope.russianFlag = true;\r\n break;\r\n \r\n }\r\n $translate.use(language.id);\r\n };\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('LoginController', LoginController);\r\n\r\n LoginController.$inject = [\r\n \t'$rootScope',\r\n \t'$scope',\r\n \t'$translate',\r\n \t'$log',\r\n \t'LoginService',\r\n \t'UserService',\r\n 'NavigationService',\r\n 'NotificationService',\r\n 'Session'];\r\n\r\n function LoginController(\r\n \t$rootScope,\r\n \t$scope,\r\n \t$translate,\r\n \t$log,\r\n \tloginService,\r\n \tuserService,\r\n navigationService,\r\n notificationService) {\r\n notificationService.setControllerScope($scope);\r\n\r\n\r\n if ($scope.expired) {\r\n notificationService.showError('login_panel.expired');\r\n }\r\n\r\n notificationService.addWatch('credentials.email');\r\n notificationService.addWatch('credentials.password');\r\n\r\n var success = function () {\r\n userService.get().then(function (res) {\r\n $translate.use(res.data.language);\r\n });\r\n\r\n $scope.closeThisDialog();\r\n navigationService.navigateToShoppingList();\r\n };\r\n\r\n // Scope variables\r\n $scope.mode = $scope.mode || 'LOGIN';\r\n $scope.credentials = {\r\n email: '',\r\n password: ''\r\n };\r\n\r\n $scope.changeMode = function () {\r\n if ($scope.mode === 'LOGIN') {\r\n $scope.mode = 'FORGOT_PASSWORD';\r\n notificationService.resetNotification();\r\n } else {\r\n $scope.mode = 'LOGIN';\r\n }\r\n };\r\n\r\n /*\r\n * Submit login dialog implements two actions:\r\n *\r\n * 1. Username-password login\r\n * 2. Reset password\r\n */\r\n $scope.submit = function (credentials) {\r\n if ($scope.mode === 'LOGIN') {\r\n loginService.login(credentials)\r\n .then(function () {\r\n success();\r\n }, function () {\r\n notificationService.showError('login_panel.login_failed');\r\n });\r\n } else if ($scope.mode === 'REGISTRATION') {\r\n userService.create($scope.credentials.email, function(){\r\n $scope.$root.onRegistrationCompleted = true;\r\n $scope.closeThisDialog();\r\n }, function(response){\r\n $scope.$root.onRegistrationCompleted = false;\r\n if (response.status === 409) {\r\n notificationService.showError('create_free_account_screen.create_account_already_registered_error');\r\n } else {\r\n notificationService.showError('create_free_account_screen.create_account_error');\r\n }\r\n });\r\n } else if($scope.mode === 'FORGOT_PASSWORD') {\r\n userService.resetPassword($scope.credentials.email, function () {\r\n $scope.$root.onPasswordReseted = true;\r\n $scope.closeThisDialog();\r\n }, function () {\r\n notificationService.showError('forgot_password.forgot_password_error');\r\n });\r\n } else {\r\n $log.warn('Unknown mode ' + $scope.mode);\r\n }\r\n };\r\n\r\n /*\r\n * Facebook login\r\n */\r\n $scope.fbLogin = function () {\r\n loginService\r\n .socialLogin('facebook')\r\n .then(loginService.isAuthenticated)\r\n .then(success)\r\n .catch(function () {\r\n notificationService.showError('login_panel.login_failed');\r\n });\r\n };\r\n\r\n $scope.cancel = $scope.closeThisDialog;\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('NewProductListController', NewProductListController);\r\n\r\n NewProductListController.$inject = ['$log', '$scope', 'ProductListService'];\r\n\r\n function NewProductListController($log, $scope, productListService) {\r\n $scope.cancel = $scope.closeThisDialog;\r\n $scope.showNotification = false;\r\n $scope.notificationClass = 'alert-danger';\r\n $scope.notificationMsg = 'add_list_panel.create_list_error';\r\n\r\n $scope.apply = function(listName) {\r\n productListService\r\n .create(listName)\r\n .then($scope.cancel)\r\n .catch(function (response) {\r\n $scope.showNotification = true;\r\n $log.error(response);\r\n });\r\n };\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('ShareListController', ShareListController);\r\n\r\n ShareListController.$inject = ['$scope', '$location', 'NotificationService', 'ProductListService'];\r\n\r\n function ShareListController($scope, $location, notificationService, productListService) {\r\n init();\r\n \r\n $scope.cancel = cancel;\r\n \r\n notificationService.setControllerScope($scope);\r\n notificationService.resetNotification();\r\n \r\n\t\t$scope.$on('ngDialog.opened', function () {\r\n productListService\r\n .share($scope.activeList.id)\r\n .then(successCallback)\r\n .catch(errorCallback);\r\n\t\t});\r\n\r\n function init() {\r\n\t\t\t$scope.joinListUrl = '';\r\n\t\t\t$scope.listName = $scope.activeList.name;\r\n }\r\n\r\n function cancel() {\r\n $scope.closeThisDialog();\r\n }\r\n\r\n\t\tvar successCallback = function (response) {\r\n\t\t\t$scope.joinListUrl = $location.absUrl().replace($location.url(), '') +\r\n '/shoppinglist?join=' + response.data.token;\r\n\t\t};\r\n\t\t\r\n\t\tvar errorCallback = function (response) {\r\n\t\t\tnotificationService.showError('alert.error_share_product_list', response);\r\n\t\t};\r\n }\r\n})();\r\n","/* global MeasurementsCatalog, CategoriesCatalog */\r\n(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('ShoppingListController', ShoppingListController);\r\n\r\n ShoppingListController.$inject = [\r\n '$location',\r\n '$log',\r\n '$q',\r\n '$scope',\r\n '$timeout',\r\n '$rootScope',\r\n '$routeParams',\r\n 'UserSettingsService',\r\n 'ProductListService',\r\n 'DialogService',\r\n 'Session',\r\n 'MeasurementService',\r\n 'ProductCategoryService',\r\n 'Measurements',\r\n 'Categories',\r\n 'WebSocketService'];\r\n\r\n function ShoppingListController(\r\n $location,\r\n $log,\r\n $q,\r\n $scope,\r\n $timeout,\r\n $rootScope,\r\n \t$routeParams,\r\n \tuserSettingsService,\r\n productListService,\r\n dialogService,\r\n session,\r\n MeasurementService,\r\n ProductCategoryService,\r\n Measurements,\r\n Categories,\r\n WebSocketService) {\r\n\r\n var unbindTranslate = $rootScope.$on('$translateChangeSuccess', reloadMeasurementsAndCategories);\r\n var unbindOpen = $rootScope.$on('ngDialog.opened', dialogOpened);\r\n var unbindClose = $rootScope.$on('ngDialog.closing', dialogClosing);\r\n\r\n $scope.$on('$destroy', function(){\r\n unbindTranslate();\r\n unbindClose();\r\n unbindOpen();\r\n WebSocketService.closeWebSocket();\r\n });\r\n\r\n /*\r\n * Listen to events fired by ngDialog to toggle the blurry state\r\n * of the page.\r\n */\r\n $scope.dialogState = { opened: false };\r\n\r\n function dialogOpened() {\r\n $scope.dialogState = { opened: true };\r\n }\r\n\r\n function dialogClosing() {\r\n $timeout(function(){\r\n $scope.dialogState = { opened: false };\r\n }, 0); // We need this here or else the watcher of ng-class does not fire\r\n }\r\n\r\n $scope.getDialogState = function() { return $scope.dialogState.opened; };\r\n\r\n /*\r\n * insert history list item into active list.\r\n */\r\n $scope.itemToInsert = {};\r\n $scope.insertListItem = function(item) {\r\n $scope.itemToInsert = item;\r\n };\r\n\r\n $scope.removedProduct = {};\r\n $scope.removeProduct = function(product) {\r\n $scope.removedProduct = product;\r\n };\r\n\r\n /*\r\n * remove history item from history list\r\n */\r\n $scope.historyItemToRemove = {};\r\n $scope.removeHistoryItem = function(item) {\r\n $scope.historyItemToRemove = item;\r\n };\r\n\r\n /*\r\n * Initialization\r\n */\r\n function $onInit() {\r\n if (! session.email) {\r\n loginExpired();\r\n return;\r\n } else {\r\n $scope.$watch(\r\n function() { return session.email; },\r\n function(newVal) { $scope.currentUserEmail = newVal; },\r\n true);\r\n }\r\n\r\n if ($routeParams.join) {\r\n // Join a shared product list\r\n joinProductList($routeParams.join);\r\n }\r\n\r\n userSettingsService.getSettings();\r\n WebSocketService.connectWebSocket();\r\n\r\n $scope.measurementsCatalog = new MeasurementsCatalog(Measurements);\r\n $scope.categoriesCatalog = new CategoriesCatalog(Categories, $scope.measurementsCatalog);\r\n }\r\n\r\n $onInit();\r\n\r\n /*\r\n * Redirect to the homepage and show a notification\r\n */\r\n function loginExpired() {\r\n $location.path('/loginexpired');\r\n }\r\n\r\n /*\r\n * Join a shared product list\r\n */\r\n function joinProductList(token) {\r\n productListService.join(token).then(function () {\r\n $location.path('/shoppinglist').search(''); // search removes token from the URL\r\n $rootScope.$emit('joinList');\r\n }).catch(function (response) {\r\n $scope.error(response, 'alert.error_join_product_list');\r\n });\r\n }\r\n\r\n function reloadMeasurementsAndCategories() {\r\n $q.all([\r\n MeasurementService.get(),\r\n ProductCategoryService.get()\r\n ]).then(function(responses) {\r\n $scope.measurementsCatalog = new MeasurementsCatalog(responses[0]);\r\n $scope.categoriesCatalog = new CategoriesCatalog(responses[1], $scope.measurementsCatalog);\r\n });\r\n }\r\n\r\n $scope.error = function(response, errorMessage) {\r\n if(response.status !== 401) { // interceptor already handles this\r\n var dialog = dialogService.openAlertDialog(errorMessage);\r\n dialog.closePromise.then(function () {\r\n $location.search('');\r\n });\r\n }\r\n\r\n $log.error('Error: ', response);\r\n };\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('UserProductsController', UserProductsController);\r\n\r\n UserProductsController.$inject = ['$scope', '$log', 'ProductService', 'BroadcastingService'];\r\n\r\n function UserProductsController($scope, $log, productService, broadcastingService) {\r\n // List of user-defined products\r\n $scope.products = [];\r\n\r\n $scope.hoverIn = function (product) {\r\n product.hoverEdit = true;\r\n };\r\n\r\n $scope.hoverOut = function (product) {\r\n product.hoverEdit = false;\r\n };\r\n\r\n $scope.setName = setName;\r\n $scope.setCategory = setCategory;\r\n $scope.deleteProduct = deleteProduct;\r\n\r\n // Loading data\r\n function loadProducts() {\r\n $scope.products = [];\r\n productService.getOwn(function(result) {\r\n $scope.products = result.data;\r\n for (var i in $scope.products) {\r\n var product = $scope.products[i];\r\n var category = $scope.categoriesCatalog.getById(product.category);\r\n if (category !== null) {\r\n product.color = category.defaultColor;\r\n }\r\n }\r\n }, function () {\r\n $log.log('Error loading user-defined products.');\r\n });\r\n }\r\n loadProducts();\r\n\r\n // Actions\r\n function setName(product, name) {\r\n product.name = name;\r\n productService.update(product, function() {\r\n // success\r\n broadcastingService.sendBroadcastMessage(broadcastingService.broadcastMessages.listItemChanged);\r\n }, function() {\r\n $log.log('Error updating product name.');\r\n });\r\n }\r\n\r\n function setCategory(product, category) {\r\n product.category = category.pmId;\r\n productService.update(product, function() {\r\n // success\r\n product.color = category.defaultColor;\r\n broadcastingService.sendBroadcastMessage(broadcastingService.broadcastMessages.listItemChanged);\r\n }, function() {\r\n $log.log('Error updating product category.');\r\n });\r\n }\r\n\r\n function deleteProduct(product) {\r\n productService.delete(product, function() {\r\n // success\r\n var idx = $scope.products.indexOf(product);\r\n $scope.products.splice(idx, 1);\r\n broadcastingService.sendBroadcastMessage(broadcastingService.broadcastMessages.listItemChanged);\r\n }, function() {\r\n $log.log('Error deleting product.');\r\n });\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .controller('UserSettingsController', UserSettingsController);\r\n\r\n UserSettingsController.$inject = ['$scope',\r\n '$translate',\r\n '$timeout',\r\n '$log',\r\n 'Session',\r\n 'UserService',\r\n 'UserSettingsService',\r\n 'NotificationService',\r\n 'Session',\r\n 'LoginService',\r\n 'NavigationService'];\r\n\r\n var TRANSLATION_KEY_PREFIX = 'uss.language_';\r\n var SHOW_BOUGHT_PREFIX = 'uss.showBought_';\r\n\r\n var LANGUAGE_DE = 'de';\r\n var LANGUAGE_EN = 'en';\r\n var LANGUAGE_RU = 'ru';\r\n\r\n function UserSettingsController($scope,\r\n $translate,\r\n $timeout,\r\n $log,\r\n Session,\r\n userService,\r\n userSettingsService,\r\n notificationService,\r\n session,\r\n loginService,\r\n navigationService) {\r\n var userSettings = {};\r\n init();\r\n\r\n $scope.showPasswordFields = showPasswordFields;\r\n $scope.closePasswordFields = closePasswordFields;\r\n $scope.showPassword = false;\r\n $scope.showAccountDeleteFields = showAccountDeleteFields;\r\n $scope.closeAccountDeleteFields = closeAccountDeleteFields;\r\n $scope.showAccountDelete = false;\r\n $scope.showBoughtSettings = false;\r\n $scope.apply = apply;\r\n $scope.cancel = cancel;\r\n\r\n notificationService.setControllerScope($scope);\r\n notificationService.addWatch('currentPassword');\r\n notificationService.addWatch('newPassword');\r\n notificationService.addWatch('repeatPassword');\r\n notificationService.addWatch('currentLanguageText');\r\n\r\n function init() {\r\n $scope.userNewInfo = null;\r\n $scope.currentPassword = null;\r\n $scope.newPassword = null;\r\n $scope.repeatPassword = null;\r\n $scope.currentUserEmail = Session.email;\r\n\r\n userService.get().then(function (res) {\r\n $scope.currentLanguageText = getLanguageKey(res.data.language);\r\n });\r\n\r\n $scope.languages = [\r\n {'name': getLanguageKey(LANGUAGE_EN)},\r\n {'name': getLanguageKey(LANGUAGE_DE)},\r\n {'name': getLanguageKey(LANGUAGE_RU)}\r\n ];\r\n\r\n $scope.showBought = [\r\n {'name' : SHOW_BOUGHT_PREFIX + 'yes'},\r\n {'name' : SHOW_BOUGHT_PREFIX + 'no'}\r\n ];\r\n\r\n userSettingsService.getSettings().then(function(settings) {\r\n userSettings = settings;\r\n $scope.showBoughtValue =\r\n settings.showBoughtItemsInTheList ?\r\n $scope.showBought[0].name :\r\n $scope.showBought[1].name;\r\n });\r\n }\r\n\r\n $scope.onLanguageChanged = function (language) {\r\n $scope.currentLanguageText = language.name;\r\n };\r\n\r\n $scope.onShowBoughtValueChanged = function(value){\r\n $scope.showBoughtValue = value.name;\r\n userSettings.showBoughtItemsInTheList = value.name === $scope.showBought[0].name;\r\n };\r\n\r\n var error = function (response) {\r\n notificationService.showError('uss.settings_changed_error', response);\r\n };\r\n\r\n var success = function () {\r\n $scope.closeThisDialog();\r\n };\r\n\r\n function getLanguageKey(language) {\r\n return TRANSLATION_KEY_PREFIX + language;\r\n }\r\n\r\n function getLanguage(key) {\r\n return key.replace(TRANSLATION_KEY_PREFIX, '');\r\n }\r\n\r\n function showPasswordFields() {\r\n $scope.showPassword = true;\r\n }\r\n\r\n function closePasswordFields() {\r\n $scope.showPassword = false;\r\n }\r\n\r\n function showAccountDeleteFields(){\r\n $scope.showAccountDelete = true;\r\n }\r\n\r\n function closeAccountDeleteFields(){\r\n $scope.showAccountDelete = false;\r\n }\r\n\r\n function apply() {\r\n // language\r\n var language = getLanguage($scope.currentLanguageText);\r\n var user = {\r\n email: $scope.currentUserEmail,\r\n firstName: '',\r\n lastName: '',\r\n language: language\r\n };\r\n\r\n userSettings.language = language;\r\n\r\n userService.update(user).then(function () {\r\n $translate.use(language);\r\n // password\r\n if ($scope.showPassword && ($scope.currentPassword || $scope.newPassword)) {\r\n changePassword();\r\n userSettingsService.update(userSettings).then(success).catch(error);\r\n } else if ($scope.showAccountDelete && $scope.currentPassword) {\r\n userService.deleteUser($scope.currentPassword, function () {\r\n success();\r\n session.destroy();\r\n loginService.logout(navigationService.navigateToAccountDeleted(), function () {\r\n $log.log('Logout failed.');\r\n });\r\n }, function () {\r\n notificationService.showError('uss.incorrect_password_msg');\r\n $scope.passwordValidationError = true;\r\n });\r\n } else {\r\n success();\r\n userSettingsService.update(userSettings).then(success).catch(error);\r\n }\r\n }, error);\r\n }\r\n\r\n function changePassword() {\r\n if ($scope.newPassword === $scope.repeatPassword) {\r\n if (angular.isUndefined($scope.newPassword) || $scope.newPassword === '') {\r\n notificationService.showError('uss.password_is_empty');\r\n $scope.passwordValidationError = false;\r\n $scope.newPasswordValidationError = true;\r\n } else {\r\n userService.changePassword($scope.currentPassword, $scope.newPassword, success, function() {\r\n notificationService.showError('uss.incorrect_password_msg');\r\n $scope.passwordValidationError = true;\r\n $scope.newPasswordValidationError = false;\r\n });\r\n }\r\n } else {\r\n notificationService.showError('uss.password_doesnt_match_msg');\r\n }\r\n }\r\n\r\n $scope.$watch('currentPassword', function () {\r\n $scope.passwordValidationError = false;\r\n });\r\n\r\n $scope.$watch('newPassword', function (newValue) {\r\n $scope.newPasswordValidationError = false;\r\n $scope.repeatPasswordValidationError = $scope.repeatPassword ? newValue !== $scope.repeatPassword : false;\r\n });\r\n\r\n $scope.$watch('repeatPassword', function (newValue) {\r\n $scope.repeatPasswordValidationError = $scope.newPassword !== newValue;\r\n });\r\n\r\n function cancel() {\r\n $scope.closeThisDialog();\r\n }\r\n\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('cancelBtn', cancelBtn);\r\n\r\n function cancelBtn() {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/cancelBtn.html',\r\n scope: {\r\n cancel: '&' // FIXME: Not uses in directive!\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('focusOn', focusOn);\r\n\r\n focusOn.$inject = ['$parse', '$timeout'];\r\n\r\n function focusOn($parse, $timeout) {\r\n return function(scope, element, attrs) {\r\n var model = $parse(attrs.focusOn);\r\n scope.$watch(model, function(value) {\r\n if(value === true) {\r\n $timeout(function() {\r\n element[0].focus();\r\n }, 100);\r\n }\r\n });\r\n };\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('mainFooter', footer);\r\n\r\n function footer() {\r\n return {\r\n templateUrl: 'template/directive/footer.html'\r\n };\r\n }\r\n})();\r\n","(function() {\r\n\t'use strict';\r\n\r\n\tangular\r\n\t\t.module('überliste')\r\n\t\t.directive('notification', NotificationFn);\r\n\r\n\t\tfunction NotificationFn() {\r\n\t\t\treturn {\r\n\t\t\t\trestrict: 'EA',\r\n\t\t\t\ttemplateUrl: 'template/directive/notification.html',\r\n\t\t\t\tscope: {\r\n\t\t\t\t\tnotifclass: '=',\r\n\t\t\t\t\tnotifmsg: '=',\r\n\t\t\t\t\tnotifshow: '='\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n})();\r\n","(function(){\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('okBtn', okBtn);\r\n\r\n function okBtn() {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/okBtn.html',\r\n scope: {\r\n apply: '&'\r\n }\r\n };\r\n }\r\n})();\r\n","(function(){\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('pmAlert', pmAlert);\r\n\r\n function pmAlert() {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/pmAlert.html',\r\n scope: {\r\n type: '@'\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('scroll', scrollFn);\r\n\r\n function scrollFn() {\r\n return {\r\n restrict: 'A',\r\n scope: {\r\n scroll: '&'\r\n },\r\n link: function(scope, element) {\r\n element.bind('scroll', function () {\r\n scope.scroll();\r\n });\r\n }\r\n };\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .directive('selectOnClick', selectOnClick);\r\n\r\n selectOnClick.$inject = ['$window'];\r\n\r\n function selectOnClick($window) {\r\n return {\r\n restrict: 'A',\r\n link: function (scope, element) {\r\n element.on('click', function () {\r\n if (!$window.getSelection().toString()) {\r\n // Required for mobile Safari\r\n this.setSelectionRange(0, this.value.length);\r\n }\r\n });\r\n }\r\n };\r\n }\r\n})();\r\n","(function () {\r\n\t'use strict';\r\n\tangular\r\n\t\t.module('überliste')\r\n\t\t.directive('googleSignIn',['UserService', 'LoginService',\r\n\t\t\tfunction ( userService, loginService) {\r\n\t\t\t\treturn {\r\n\t\t\t\t\trestrict: 'E',\r\n\t\t\t\t\tlink: postLink\r\n\t\t\t\t};\r\n\t\t\t\tfunction postLink(scope,elem) {\r\n\t\t\t\t\tvar auth2;\r\n\t\t\t\t\tloginService.gapiPromise().then( function (gapi){\r\n\t\t\t\t\t\tgapi.load('auth2', function() {\r\n\t\t\t\t\t\t\tauth2 = gapi.auth2.init({\r\n\t\t\t\t\t\t\t\tCLIENT_ID: '517104027080-49t2g3v5jkhd48gih6gsfj6veebr867m.apps.googleusercontent.com',\r\n\t\t\t\t\t\t\t\tcookiepolicy: 'single_host_origin',\r\n\t\t\t\t\t\t\t\tscope: 'profile email'\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\tvar element = elem[0];\r\n\t\t\t\t\t\t\tvar ID_TOKEN_PARAM = 'id_token';\r\n\t\t\t\t\t\t\tauth2.attachClickHandler(element, {}, function(googleUser) {\r\n\t\t\t\t\t\t\t\tvar data = {\r\n\t\t\t\t\t\t\t\t\ttoken: googleUser.getAuthResponse()[ID_TOKEN_PARAM],\r\n\t\t\t\t\t\t\t\t\tlanguage: userService.getUserLanguage()\r\n\t\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t\t\tscope.googleSignIn(data);\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}]);\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageAdvantages', function () {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageAdvantages.html'\r\n };\r\n });\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageDescription', function () {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageDescription.html'\r\n };\r\n });\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageDownload', ['$document', function ($document) {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageDownload.html',\r\n link: function(scope, element) {\r\n var $el = element[0];\r\n $document.on('scroll', function() {\r\n // Use jQuery for performance optimization\r\n var rect = $el.getBoundingClientRect();\r\n var div = document.querySelector('.homepage-download-block');\r\n if (div) {\r\n if (rect.top <= 0 && rect.bottom > 0) {\r\n div.style.position = 'fixed';\r\n div.style.top = 0;\r\n div.style.right = '15px';\r\n } else {\r\n div.style.position = 'relative';\r\n div.style.right = 0;\r\n }\r\n }\r\n });\r\n }\r\n };\r\n }]);\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageFooter', function () {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageFooter.html'\r\n };\r\n });\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageHeader', ['$document', function ($document) {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageHeader.html',\r\n link: function (scope, element, attrs) {\r\n if (attrs.hideOnTop) {\r\n var description = document.querySelectorAll('#description');\r\n $document.on('scroll', function () {\r\n // Selector should be inside event handler, because the app re-creates header for the each page\r\n var header = document.querySelector('.homepage-header');\r\n if (header) {\r\n // Show header after the first section\r\n var descriptionTop = description && description.length > 0 ? description[0].getBoundingClientRect().top : 1;\r\n header.style.visibility = descriptionTop <= 0 ? 'visible' : 'hidden';\r\n }\r\n });\r\n } else {\r\n document.querySelector('.homepage-header').style.visibility = 'visible';\r\n }\r\n }\r\n };\r\n\r\n // FIXME: uses parent component scope!\r\n }]);\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageIdea', function () {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageIdea.html'\r\n };\r\n });\r\n})();\r\n","(function () {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .directive('homepageMain', function () {\r\n return {\r\n restrict: 'E',\r\n templateUrl: 'template/directive/homepageMain.html'\r\n };\r\n\r\n // FIXME: Uses parent component scope!\r\n });\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('mainHeader', {\r\n templateUrl: 'template/component/header.html',\r\n controller: HeaderController,\r\n bindings: {\r\n categoriesCatalog: '<',\r\n currentUserEmail: '<'\r\n }\r\n });\r\n\r\n HeaderController.$inject = [\r\n '$log',\r\n 'NavigationService',\r\n 'DialogService',\r\n 'LoginService',\r\n 'Session'];\r\n\r\n function HeaderController($log, navigationService, dialogService, loginService, session) {\r\n var ctrl = this;\r\n\r\n ctrl.openLoginDialog = dialogService.openLoginDialog;\r\n ctrl.onSettingSelect = function(setting){ setting.click(); };\r\n\r\n ctrl.settings = [\r\n {\r\n 'name': 'user_settings_menu.user_products_title',\r\n 'click': function () { dialogService.openProductsDialog(ctrl.categoriesCatalog); }\r\n },\r\n {\r\n 'name': 'user_settings_menu.account_settings_title',\r\n 'click': function () { dialogService.openSettingsDialog(); }\r\n },\r\n {\r\n 'name': 'user_settings_menu.logout_title',\r\n 'separator': true,\r\n 'click': function () {\r\n session.destroy();\r\n loginService.logout(navigationService.navigateToHome, function () {\r\n $log.log('Logout failed.');\r\n });\r\n }\r\n }\r\n ];\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('productList', {\r\n templateUrl: 'template/component/productList.html',\r\n controller: ProductListController,\r\n bindings: {\r\n onDeleteProduct: '&',\r\n onAddProduct: '&',\r\n errorHandler: '&',\r\n measurementsCatalog: '<',\r\n categoriesCatalog: '<',\r\n itemToInsert: '<' // push trigger for when the history list wants to insert a new item\r\n }\r\n });\r\n\r\n ProductListController.$inject = [\r\n '$scope',\r\n '$rootScope',\r\n 'MotivationPhraseService',\r\n 'ProductListService',\r\n 'ProductListItemService',\r\n 'UserSettingsService',\r\n 'ListUtil',\r\n 'Session'];\r\n\r\n function ProductListController(\r\n $scope,\r\n $rootScope,\r\n MotivationPhraseService,\r\n ProductListService,\r\n ProductListItemService,\r\n UserSettingsService,\r\n ListUtil,\r\n Session) {\r\n\r\n var ctrl = this;\r\n ctrl.activeList = {};\r\n ctrl.motivationPhrase = '';\r\n\r\n ctrl.errorHandlerForChildren = function(response, message) {\r\n // FIMXE find out how to pass a function binding through component tree\r\n ctrl.errorHandler({ response: response, message: message });\r\n };\r\n\r\n var unbindProductCreate = $rootScope.$on('ws:product:create', function() {\r\n loadProductListItemsFromServer(ctrl.activeList);\r\n });\r\n\r\n var unbindProductListUpdate = $rootScope.$on('ws:productlist:update',\r\n function(event, data) {\r\n if (data.id === ctrl.activeList.id) {\r\n // active list was updated, reload\r\n loadProductListItemsFromServer(ctrl.activeList);\r\n }\r\n });\r\n\r\n var unbindProductListItemUpdate = $rootScope.$on('ws:productlistitem:update',\r\n function(event, data) {\r\n var found = false;\r\n for (var i = 0; ctrl.activeList.items.length; i++) {\r\n var item = ctrl.activeList.items[i];\r\n if(item && item.id && data && data.id){\r\n if (item.id === data.id && item.state.toUpperCase() === 'NEW') {\r\n item.state = data.state;\r\n item.amount = data.amount;\r\n item.measurementPmId = data.measurement;\r\n item.description = data.description;\r\n \r\n found = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!found) {\r\n loadProductListItemsFromServer($scope.activeList);\r\n }\r\n });\r\n\r\n var unbindDeleteProduct = $rootScope.$on('ws:product:delete',\r\n function(event, pmId) { deleteProduct(pmId); });\r\n\r\n ctrl.$onDestroy = function() {\r\n unbindProductCreate();\r\n unbindProductListUpdate();\r\n unbindProductListItemUpdate();\r\n unbindDeleteProduct();\r\n };\r\n\r\n $scope.$watchCollection('$ctrl.activeList.items', function (items) {\r\n updateItemsCount(items);\r\n });\r\n\r\n ctrl.$onChanges = function(changes) {\r\n if(changes.itemToInsert && Session.mail !== null) {\r\n var newItem = changes.itemToInsert.currentValue;\r\n if(! (!newItem || angular.equals(newItem, {}))) {\r\n ctrl.insertListItem(newItem);\r\n }\r\n }\r\n\r\n // only watch measurements changes because they are displayed\r\n // on the active list items\r\n if(changes.measurementsCatalog && Session.mail !== null) {\r\n loadProductListItemsFromServer(ctrl.activeList);\r\n }\r\n };\r\n\r\n ctrl.setActiveList = function(list) {\r\n UserSettingsService\r\n .setActiveList(list)\r\n .then(function() {\r\n ctrl.activeList = list;\r\n $rootScope.$emit('change:activelist');\r\n loadProductListItemsFromServer(list);\r\n });\r\n };\r\n\r\n function loadProductListItemsFromServer(productList) {\r\n if (Object.keys(productList).length > 0 && productList.constructor === Object) {\r\n ProductListService\r\n .getProductListItems(productList)\r\n .then(syncProductItems)\r\n .catch(function (response) {\r\n ctrl.errorHandler({\r\n response: response,\r\n message: 'alert.error_load_product_list'\r\n });\r\n });\r\n }\r\n }\r\n\r\n ctrl.updateActiveListName = function(newName) {\r\n ctrl.activeList.name = newName;\r\n\r\n ProductListService\r\n .update(ctrl.activeList)\r\n .catch(function (response) {\r\n ctrl.errorHandler({\r\n response: response,\r\n message: 'alert.error_update_active_list'\r\n });\r\n });\r\n };\r\n\r\n ctrl.insertListItem = function (newItem) {\r\n var tmpList = {};\r\n angular.copy(ctrl.activeList, tmpList);\r\n\r\n var itemObj = ProductListItemService.createProductListItem(newItem)(ctrl.activeList.id);\r\n tmpList.items = [itemObj];\r\n ProductListService\r\n .sync(tmpList, true)\r\n .then(function(response){\r\n ctrl.onAddProduct({product: itemObj});\r\n return response;\r\n })\r\n .then(syncProductItems)\r\n .catch(function (response) {\r\n ctrl.errorHandler({\r\n response: response,\r\n message: 'alert.error_insert_item'\r\n });\r\n });\r\n };\r\n\r\n function syncProductItems(serverItems) {\r\n var localItems = ctrl.activeList.items;\r\n\r\n ListUtil.sync(\r\n localItems,\r\n serverItems,\r\n itemToId,\r\n updateItem,\r\n sortFn,\r\n insertFn);\r\n }\r\n\r\n function itemToId(localItem) {\r\n return localItem.productPmId;\r\n }\r\n\r\n function updateItem(localItem, serverItem) {\r\n angular.copy(serverItem, localItem);\r\n }\r\n\r\n function sortFn(localList, serverList) {\r\n localList.forEach(function (localItem, index) {\r\n var idx = ListUtil.getIndexOfItemWithProductPmId(serverList, localItem.productPmId);\r\n // state BOUGHT -> NEW\r\n if (index > idx) {\r\n swap(localList, index, idx);\r\n }\r\n serverList[idx].processed = true;\r\n });\r\n }\r\n\r\n function insertFn(localList, newItem, newItemIndex) {\r\n if (!newItem.processed) {\r\n localList.splice(newItemIndex, 0, newItem);\r\n }\r\n }\r\n\r\n function swap(array, oldIndex, newIndex) {\r\n // FIXME: this can never happen\r\n if (newIndex >= array.length) {\r\n var k = newIndex - array.length;\r\n while ((k--) + 1) {\r\n array.push(undefined);\r\n }\r\n }\r\n\r\n var tmp = array[newIndex];\r\n array[newIndex] = array[oldIndex];\r\n array[oldIndex] = tmp;\r\n }\r\n\r\n ctrl.removeListItem = function(item) {\r\n if(item.state === 'BOUGHT') {\r\n ctrl.onDeleteProduct({product: item});\r\n } else if(item.state === 'DELETED') {\r\n deleteProduct(item.productPmId);\r\n }\r\n };\r\n\r\n function deleteProduct(pmId) {\r\n var itemIndex = ctrl.activeList.items.findIndex(function (item) {\r\n return item.productPmId === pmId;\r\n });\r\n var removedItem = ctrl.activeList.items.splice(itemIndex, 1);\r\n updateItemsCount(ctrl.activeList.items);\r\n ctrl.onDeleteProduct({product: removedItem[0]});\r\n }\r\n\r\n // Updating number of items in list selection. Items count is another variable than items because changing of items causes UI animation\r\n function updateItemsCount(items) {\r\n if (Object.keys(ctrl.activeList).length > 0 && ctrl.activeList.constructor === Object) {\r\n ctrl.activeList.itemsCount =\r\n angular.isUndefined(items) ?\r\n 0 :\r\n items.filter(function (el) {\r\n return el.state.toUpperCase() === 'NEW';\r\n }).length;\r\n }\r\n\r\n showMotivationPhrase();\r\n }\r\n\r\n function showMotivationPhrase() {\r\n ctrl.motivationPhrase = '';\r\n if (ctrl.activeList.itemsCount <= 1) {\r\n return MotivationPhraseService\r\n .getRandom()\r\n .then(function (data) {\r\n if (data) {\r\n ctrl.motivationPhrase = data.phrase;\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('productListSelect', {\r\n templateUrl: 'template/component/productListSelect.html',\r\n controller: ProductListSelectController,\r\n bindings: {\r\n activeList: '<',\r\n setActiveList: '&',\r\n updateActiveListName: '&',\r\n errorHandler: '&'\r\n }\r\n });\r\n\r\n ProductListSelectController.$inject = ['$rootScope', 'ProductListService', 'DialogService'];\r\n\r\n function ProductListSelectController($rootScope, ProductListService, DialogService) {\r\n var ctrl = this;\r\n ctrl.productLists = [];\r\n ctrl.activeList = { name: '' }; // model value for the product list name\r\n\r\n var events = [\r\n { name: 'joinList', unbind: angular.noop },\r\n { name: 'ws:product:update', unbind: angular.noop },\r\n { name: 'ws:productlist:create', unbind: angular.noop },\r\n { name: 'ws:productlist:update', unbind: angular.noop },\r\n { name: 'ws:productlist:delete', unbind: angular.noop },\r\n { name: 'ws:productlistitem:create', unbind: angular.noop }\r\n ];\r\n\r\n ctrl.$onDestroy = function() {\r\n angular.forEach(events, function(event) {\r\n event.unbind();\r\n });\r\n };\r\n\r\n ctrl.$onInit = function() {\r\n loadProductLists();\r\n\r\n angular.forEach(events, function(event) {\r\n var fn = angular.noop;\r\n\r\n if(event.name === 'ws:productlist:update') {\r\n fn = function(ev, data) {\r\n for (var i in ctrl.productLists) {\r\n var list = ctrl.productLists[i];\r\n if (list.id === data.id) {\r\n list.name = data.name;\r\n list.users = data.users;\r\n return;\r\n }\r\n }\r\n };\r\n } else if(event.name === 'ws:productlist:delete') {\r\n fn = function(event, id) {\r\n var listIndex = ctrl.productLists.findIndex(function (list) {\r\n return list.id === id;\r\n });\r\n\r\n if(listIndex) {\r\n ctrl.productLists.splice(listIndex, 1);\r\n }\r\n\r\n if (ctrl.activeList.id === id) {\r\n ctrl.setActiveList({list: ctrl.productLists[0]});\r\n ctrl.activeList = { name: ctrl.productLists[0].name };\r\n }\r\n };\r\n } else {\r\n fn = loadProductLists;\r\n }\r\n\r\n event.unbind = $rootScope.$on(event.name, fn);\r\n });\r\n };\r\n\r\n function loadProductLists() {\r\n ProductListService\r\n .get()\r\n .then(function(productLists) {\r\n ctrl.productLists = [];\r\n productLists.forEach(function (list) {\r\n enrichList(list);\r\n ctrl.productLists.push(list);\r\n\r\n if(list.active === true) {\r\n ctrl.setActiveList({list: list});\r\n ctrl.activeList = { name: list.name };\r\n }\r\n });\r\n })\r\n .catch(function(response) {\r\n ctrl.errorHander({\r\n response: response,\r\n message: 'alert.error_load_product_lists'\r\n });\r\n });\r\n }\r\n\r\n function enrichList(list) {\r\n list.itemsCount = list.items.length;\r\n list.items = [];\r\n }\r\n\r\n ctrl.shareProductList = function(list) {\r\n DialogService.openShareListDialog(list);\r\n };\r\n\r\n ctrl.deleteProductList = function(list) {\r\n if(ctrl.productLists.length > 1) {\r\n DialogService\r\n .openDeleteListDialog(list)\r\n .closePromise\r\n .then(loadProductLists);\r\n }\r\n };\r\n\r\n ctrl.addNewProductList = function() {\r\n DialogService\r\n .addProductList()\r\n .closePromise\r\n .then(loadProductLists);\r\n };\r\n\r\n ctrl.updateListName = function() {\r\n ctrl.updateActiveListName({newName: ctrl.activeList.name});\r\n };\r\n\r\n ctrl.activateList = function(list) {\r\n ctrl.setActiveList({list: list});\r\n };\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('productListSelectItem', {\r\n templateUrl: 'template/component/productListSelectItem.html',\r\n controller: ProductListSelectItemController,\r\n bindings: {\r\n list: '<',\r\n listsSize: '<',\r\n shareList: '&',\r\n deleteList: '&',\r\n selectActiveList: '&'\r\n }\r\n });\r\n \r\n function ProductListSelectItemController() {\r\n var ctrl = this;\r\n\r\n ctrl.shareProductList = function() {\r\n ctrl.shareList({list: ctrl.list});\r\n };\r\n\r\n ctrl.deleteProductList = function() {\r\n ctrl.deleteList({list: ctrl.list});\r\n };\r\n\r\n ctrl.activateProductList = function() {\r\n ctrl.selectActiveList({list: ctrl.list});\r\n };\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('productSearch', {\r\n templateUrl: 'template/component/productSearch.html',\r\n controller: ProductSearchController,\r\n bindings: {\r\n activeList: '<',\r\n categoriesCatalog: '<',\r\n measurementsCatalog: '<',\r\n insertSelectedItem: '&',\r\n errorHandler: '&'\r\n }\r\n });\r\n\r\n ProductSearchController.$inject = [\r\n '$scope',\r\n '$q',\r\n '$timeout',\r\n 'DialogService',\r\n 'ProductService',\r\n 'ProductListService'];\r\n\r\n function ProductSearchController(\r\n $scope,\r\n $q,\r\n $timeout,\r\n DialogService,\r\n ProductService,\r\n ProductListService) {\r\n var ctrl = this;\r\n var searchResults = []; // last returned search results\r\n\r\n ctrl.searchWord = '';\r\n\r\n ctrl.addNewProductListItem = function() {\r\n var dialog = DialogService.newProductListItem(\r\n ctrl.searchWord,\r\n true,\r\n ctrl.categoriesCatalog,\r\n ctrl.measurementsCatalog);\r\n\r\n dialog\r\n .closePromise\r\n .then(createProduct)\r\n .then(selectProduct)\r\n .catch(function(response) {\r\n ctrl.errorHander({\r\n response: response,\r\n message: 'new_list_item_panel.error'\r\n });\r\n });\r\n };\r\n\r\n ctrl.getProductById = function(id) {\r\n return $q(function(resolve, reject) {\r\n ProductService.getById(id, resolve, reject);\r\n }).then(function(response) {\r\n return response.data;\r\n }).catch(function(error) {\r\n throw error;\r\n });\r\n };\r\n\r\n function createProduct(dialogValue) {\r\n if(dialogValue.value === '$closeButton'){ return $q.when(); }\r\n\r\n var draftListItem = dialogValue.value;\r\n\r\n var product = {\r\n 'name': draftListItem.productName,\r\n 'category': draftListItem.category.pmId\r\n };\r\n\r\n return $q.all([ProductService.create(product), $q.when(draftListItem)]);\r\n }\r\n\r\n function selectProduct(resolves) {\r\n if(resolves) {\r\n var result = resolves[0].data;\r\n var draftListItem = resolves[1];\r\n draftListItem.pmId = result.pmId;\r\n draftListItem.category = result.category;\r\n ctrl.selectSearchResult(draftListItem);\r\n }\r\n\r\n return $q.when();\r\n }\r\n\r\n // use scope here for the typeahead expression\r\n $scope.searchProducts = function() {\r\n if(ctrl.searchWord.charAt(0) === '#') {\r\n return localSearch(ctrl.searchWord);\r\n } else {\r\n return remoteSearch(ctrl.searchWord);\r\n }\r\n };\r\n\r\n function localSearch(searchWord) {\r\n var searchTerm = searchWord.split(': ')[1];\r\n if (searchTerm && angular.isArray(searchResults)) {\r\n searchResults = searchResults.filter(function (item) {\r\n return item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0;\r\n });\r\n }\r\n\r\n return $q.resolve(searchResults);\r\n }\r\n\r\n function remoteSearch(searchWord) {\r\n return ProductService\r\n .search(searchWord)\r\n .then(function (data) {\r\n searchResults = processData(data.hashtags, data.products);\r\n return searchResults;\r\n });\r\n }\r\n\r\n\r\n\r\n function processData(hashTags, products) {\r\n var hashTagArray = hashTags !== null ? hashTags : [];\r\n var productArray = products !== null ? products : [];\r\n\r\n hashTagArray.forEach(function (ht) { ht.isHashtag = true; });\r\n\r\n var productPromises = productArray.map(function (product) {\r\n var productCategoryPromise;\r\n\r\n if (product.userDefined) {\r\n productCategoryPromise = ctrl.getProductById(product.pmId)\r\n .then(function(productWithCategory) {\r\n return productWithCategory.category;\r\n });\r\n } else {\r\n productCategoryPromise = $q.resolve(Math.floor(product.pmId / 1000000) * 100000);\r\n }\r\n\r\n return productCategoryPromise.then(function (productCategory) {\r\n var idx = ProductListService.getIndexOfItemWithProductPmId(ctrl.activeList.items, product.pmId);\r\n if(idx > -1) {\r\n var item = ctrl.activeList.items[idx];\r\n if (item.product === product.pmId) {\r\n product.isDisabled = true;\r\n }\r\n }\r\n\r\n product.isProduct = true;\r\n product.defaultColor = ctrl.categoriesCatalog.getColorById(productCategory);\r\n });\r\n });\r\n\r\n return $q.all(productPromises).then(function() {\r\n return hashTagArray.concat(productArray);\r\n });\r\n }\r\n\r\n ctrl.selectSearchResult = function (item) {\r\n if (!item.isDisabled) {\r\n if (item.isHashtag) {\r\n searchResults = processData(item.childHashtags, item.products);\r\n ctrl.searchWord = '#' + item.name + ': ';\r\n $timeout(function () {\r\n angular.element(document.querySelector('#searchBar')).triggerHandler('input');\r\n });\r\n } else {\r\n ctrl.searchWord = '';\r\n ctrl.insertSelectedItem({item: item});\r\n }\r\n } else {\r\n ctrl.searchWord = '';\r\n }\r\n };\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('productListItem', {\r\n templateUrl: 'template/component/productListItem.html',\r\n controller: ProductListItemController,\r\n bindings: {\r\n item: '<',\r\n onEdit: '&',\r\n onDelete: '&',\r\n measurementsCatalog: '<'\r\n }\r\n });\r\n\r\n function ProductListItemController() {\r\n var ctrl = this;\r\n\r\n ctrl.editItem = function() {\r\n if(ctrl.item.state.toUpperCase() === 'NEW') {\r\n ctrl.onEdit({item: ctrl.item});\r\n }\r\n };\r\n\r\n ctrl.deleteItem = function () {\r\n ctrl.onDelete({item: ctrl.item});\r\n };\r\n \r\n ctrl.showItemAmount = function() {\r\n var amount = ctrl.measurementsCatalog.getById(ctrl.item.measurementPmId);\r\n if(! amount || amount.plural === '-' || amount.shortcut === '–') { return ''; }\r\n if(ctrl.item.amount === 1) {\r\n return amount.shortcut;\r\n } else {\r\n return amount.plural;\r\n }\r\n };\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('productListItems', {\r\n templateUrl: 'template/component/productListItems.html',\r\n controller: ProductListItemsController,\r\n bindings: {\r\n activeList: '<',\r\n categoriesCatalog: '<',\r\n measurementsCatalog: '<',\r\n removeItem: '&',\r\n errorHandler: '&'\r\n }\r\n });\r\n\r\n ProductListItemsController.$inject = [\r\n '$q',\r\n '$rootScope',\r\n '$timeout',\r\n 'DialogService',\r\n 'ProductService',\r\n 'ProductListItemService',\r\n 'UserSettingsService'\r\n ];\r\n\r\n function ProductListItemsController($q,\r\n $rootScope,\r\n $timeout,\r\n DialogService,\r\n ProductService,\r\n ProductListItemService,\r\n UserSettingsService) {\r\n var ctrl = this;\r\n ctrl.showBought = false;\r\n\r\n var unbind = $rootScope.$on('userSettingsChanged', function (ev, settings) {\r\n ctrl.showBought = settings.showBoughtItemsInTheList;\r\n });\r\n\r\n ctrl.$onDestroy = function () {\r\n unbind();\r\n };\r\n\r\n ctrl.$onInit = function () {\r\n UserSettingsService.getSettings().then(function (settings) {\r\n ctrl.showBought = settings.showBoughtItemsInTheList;\r\n });\r\n };\r\n\r\n ctrl.editItem = function (item) {\r\n var dialog = DialogService.editProductListItem(item,\r\n ctrl.categoriesCatalog, ctrl.measurementsCatalog);\r\n\r\n dialog\r\n .closePromise\r\n .then(updateProduct)\r\n .then(updateProductListItem)\r\n .then(function (draftListItem) {\r\n if (angular.isDefined(draftListItem)) {\r\n angular.copy(draftListItem, item);\r\n }\r\n })\r\n .catch(function (response) {\r\n ctrl.errorHandler({\r\n response: response,\r\n message: 'edit_list_item_panel.error'\r\n });\r\n });\r\n };\r\n\r\n function updateProduct(dialogValue) {\r\n if (angular.isUndefined(dialogValue.value) || dialogValue.value === '$closeButton') {\r\n return $q.when();\r\n }\r\n\r\n var draftListItem = dialogValue.value;\r\n if (draftListItem.userDefined) {\r\n\r\n var product = {\r\n pmId: draftListItem.productPmId,\r\n name: draftListItem.productName,\r\n category: draftListItem.category.pmId,\r\n userDefined: true\r\n };\r\n\r\n return ProductService\r\n .update(product)\r\n .then(function () {\r\n // TODO: if the category was changed, the position of the item should be updated too\r\n return draftListItem;\r\n });\r\n } else {\r\n return $q.when(draftListItem);\r\n }\r\n }\r\n\r\n function updateProductListItem(draftListItem) {\r\n if (angular.isUndefined(draftListItem)) {\r\n return $q.when();\r\n }\r\n return ProductListItemService\r\n .update(draftListItem)\r\n .then(function () {\r\n return draftListItem;\r\n });\r\n }\r\n\r\n ctrl.deleteItem = function (item) {\r\n item.internalState = 'WILL_BE_DELETED';\r\n $timeout(function () {\r\n item.state = 'DELETED';\r\n ProductListItemService\r\n .update(item)\r\n .then(function () {\r\n ctrl.removeItem({item: item});\r\n });\r\n }, 200);\r\n };\r\n\r\n ctrl.buyItem = function (item) {\r\n item.internalState = 'WILL_BE_BOUGHT';\r\n $timeout(function () {\r\n if (item.state.toUpperCase() === 'NEW') {\r\n item.state = 'BOUGHT';\r\n } else if (item.state.toUpperCase() === 'BOUGHT') {\r\n item.state = 'DELETED';\r\n }\r\n\r\n ProductListItemService\r\n .update(item)\r\n .then(function () {\r\n if (item.state === 'DELETED' || item.state === 'BOUGHT') {\r\n ctrl.removeItem({item: item});\r\n }\r\n });\r\n }, 200);\r\n };\r\n\r\n }\r\n})();\r\n\r\n","(function(){\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('historyList', {\r\n templateUrl: 'template/component/historyList.html',\r\n controller: HistoryListController,\r\n bindings: {\r\n categoriesCatalog: '<',\r\n removedProduct: '<',\r\n itemToRemove: '<',\r\n insertListItem: '&',\r\n errorHandler: '&'\r\n }\r\n });\r\n\r\n HistoryListController.$inject = [\r\n '$q',\r\n '$scope',\r\n '$rootScope',\r\n 'Session',\r\n 'UserSettingsService',\r\n 'ProductListService',\r\n 'PurchaseHistoryEntryService'];\r\n\r\n function HistoryListController(\r\n $q,\r\n $scope,\r\n $rootScope,\r\n Session,\r\n UserSettingsService,\r\n ProductListService,\r\n PurchaseHistoryEntryService) {\r\n var ctrl = this;\r\n\r\n ctrl.historyList = [];\r\n ctrl.showHistory = false;\r\n ctrl.activeSorter = function() { return 0; };\r\n\r\n var waitForSorter = $q.defer();\r\n $scope.$on('activeSorter', function(event, arg) {\r\n event.stopPropagation();\r\n ctrl.activeSorter = arg.sort;\r\n waitForSorter.resolve();\r\n });\r\n\r\n var events = [\r\n { name: 'ws:productlist:create', unbind: angular.noop },\r\n { name: 'ws:productlistitem:create', unbind: angular.noop },\r\n { name: 'ws:product:update', unbind: angular.noop },\r\n { name: 'ws:productlist:update', unbind: angular.noop },\r\n { name: 'ws:productlistitem:update', unbind: angular.noop },\r\n { name: 'ws:historyentry:delete', unbind: angular.noop },\r\n { name: 'change:activelist', unbind: angular.noop }\r\n ];\r\n\r\n ctrl.$onDestroy = function() {\r\n angular.forEach(events, function(event) {\r\n event.unbind();\r\n });\r\n };\r\n\r\n ctrl.$onInit = function() {\r\n // FIXME: Make sure, that session settings are there! (Should be after login...)\r\n ctrl.showHistory = Session.settings ? Session.settings.showHistory : false;\r\n loadPurchaseHistory();\r\n\r\n angular.forEach(events, function(event) {\r\n if(event.name === 'ws:historyentry:delete') {\r\n event.unbind = $rootScope.$on(event.name, function(event, data) {\r\n removeHistoryItem(data);\r\n });\r\n } else {\r\n event.unbind = $rootScope.$on(event.name, loadPurchaseHistory);\r\n }\r\n });\r\n };\r\n\r\n ctrl.$onChanges = function(changes) {\r\n if(changes.categoriesCatalog &&\r\n changes.categoriesCatalog.isFirstChange() &&\r\n changes.removedProduct &&\r\n changes.removedProduct.isFirstChange() &&\r\n changes.itemToRemove &&\r\n changes.itemToRemove.isFirstChange()) {\r\n return; // $onChanges is called before $onInit so ignore the first change\r\n // else loadPurchaseHistory is called twice\r\n }\r\n\r\n if((changes.categoriesCatalog || changes.removedProduct) && Session.mail !== null) {\r\n loadPurchaseHistory();\r\n }\r\n\r\n if(changes.itemToRemove) {\r\n removeHistoryItem({product: {pmId: changes.itemToRemove.currentValue.product} });\r\n }\r\n };\r\n\r\n function loadPurchaseHistory() {\r\n waitForSorter\r\n .promise\r\n .then(PurchaseHistoryEntryService.get)\r\n .then(function (result) {\r\n if (result.data && result.data.constructor === Array) {\r\n syncPurchases(ctrl.historyList, result.data);\r\n }\r\n })\r\n .catch(function (response) {\r\n ctrl.errorHandler({\r\n response: response,\r\n message: 'alert.error_load_purchases'\r\n });\r\n });\r\n }\r\n\r\n function syncPurchases(purchaseHistory, purchaseHistoryFromServer) {\r\n for (var i = 0; i < purchaseHistory.length; i++) {\r\n var idx = ProductListService.getIndexOfItemWithProductPmId(\r\n purchaseHistoryFromServer,\r\n purchaseHistory[i].product.pmId);\r\n\r\n if (idx < 0) {\r\n // 1. Remove\r\n purchaseHistory.splice(i--, 1);\r\n } else {\r\n // 2. Update\r\n purchaseHistory[i].product = purchaseHistoryFromServer[idx].product;\r\n purchaseHistory[i].count = purchaseHistoryFromServer[idx].count;\r\n purchaseHistoryFromServer.splice(idx, 1);\r\n }\r\n }\r\n\r\n // 3. Create\r\n var sortedList = ctrl.activeSorter(purchaseHistory.concat(purchaseHistoryFromServer));\r\n\r\n purchaseHistoryFromServer.forEach(function (purchaseFromServer) {\r\n var i = sortedList.indexOf(purchaseFromServer);\r\n purchaseHistory.splice(i, 0, purchaseFromServer);\r\n\r\n });\r\n\r\n // 4. Update categories (colors)\r\n purchaseHistory.forEach(function (purchase) {\r\n purchase.categoryColor = ctrl.categoriesCatalog.getColorById(purchase.product.category);\r\n });\r\n\r\n updateHistoryListItemOrders(sortedList);\r\n }\r\n\r\n ctrl.showHidePurchases = function() {\r\n ctrl.showHistory = !ctrl.showHistory;\r\n\r\n UserSettingsService\r\n .update({showHistory: ctrl.showHistory})\r\n .catch(function(response) {\r\n ctrl.errorHandler({\r\n response: response,\r\n message: '' // FIXME\r\n });\r\n });\r\n };\r\n\r\n ctrl.addItemToProductList = function(historyItem) {\r\n historyItem.hidden = true;\r\n historyItem.amount = 1.0;\r\n\r\n ctrl.insertListItem({item: historyItem});\r\n removeHistoryItem(historyItem);\r\n\r\n };\r\n\r\n function removeHistoryItem(historyItem) {\r\n var idx = ProductListService.getIndexOfItemWithProductPmId(ctrl.historyList, historyItem.product.pmId);\r\n if (idx > -1) {\r\n ctrl.historyList.splice(idx, 1);\r\n\r\n var historyListCopy = ctrl.historyList.slice();\r\n historyListCopy.sort(function (a, b) {\r\n return a.order - b.order;\r\n });\r\n updateHistoryListItemOrders(historyListCopy);\r\n }\r\n }\r\n\r\n function updateHistoryListItemOrders(sortedHistoryList) {\r\n for (var i = 0; i < sortedHistoryList.length; i++) {\r\n var j = ctrl.historyList.indexOf(sortedHistoryList[i]);\r\n ctrl.historyList[j].order = i;\r\n ctrl.historyList[j].opacity = getOpacity(i);\r\n ctrl.historyList[j].hidden = false;\r\n }\r\n }\r\n\r\n /*\r\n * Calculation of history item opacity.\r\n */\r\n function getOpacity(order) {\r\n var minOpacity = 0.4;\r\n\r\n var historyListItemsSelector = angular.element(document.querySelector('.history-list-items'));\r\n var historyListItemSelector = angular.element(document.querySelector('.history-list-item'));\r\n\r\n var fullHeight = historyListItemsSelector.prop('offsetHeight');\r\n var itemHeight = historyListItemSelector.prop('offsetHeight') ?\r\n historyListItemSelector.prop('offsetHeight') : 35;\r\n\r\n var totalPossibleElements = Math.abs(fullHeight / itemHeight);\r\n var totalVisibleElements =\r\n totalPossibleElements > ctrl.historyList.length ?\r\n ctrl.historyList :\r\n totalPossibleElements;\r\n\r\n var opacityStep = (1.0 - minOpacity) / (totalVisibleElements / 2.0);\r\n\r\n var scrollPos = historyListItemsSelector.prop('scrollTop');\r\n\r\n // Order correction for scroll\r\n order -= Math.abs(scrollPos / itemHeight);\r\n\r\n // Opacity for the top and the bottom of the list\r\n // return order <= totalVisibleElements / 2 ? minOpacity + opacityStep * order : 2 - opacityStep * order;\r\n\r\n // Opacity for the bottom of the list\r\n return order < totalVisibleElements / 3 ? 1 : 1.5 - opacityStep * order;\r\n }\r\n\r\n ctrl.executeSort = function(sortFn) {\r\n ctrl.activeSorter = sortFn;\r\n var historyListCopy = ctrl.historyList.slice();\r\n var sortedHistoryList = sortFn(historyListCopy);\r\n updateHistoryListItemOrders(sortedHistoryList);\r\n };\r\n\r\n ctrl.setOpacity = function() {\r\n for (var i in ctrl.historyList) {\r\n var purchase = ctrl.historyList[i];\r\n purchase.opacity = getOpacity(purchase.order);\r\n }\r\n\r\n // force UI update\r\n $scope.$digest();\r\n };\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n angular\r\n .module('überliste')\r\n .component('historyListItem', {\r\n templateUrl: 'template/component/historyListItem.html',\r\n controller: HistoryListItemController,\r\n bindings: {\r\n historyListItem: '<',\r\n addItemToProductList: '&'\r\n }\r\n });\r\n\r\n HistoryListItemController.$inject = ['DialogService'];\r\n\r\n function HistoryListItemController(DialogService) {\r\n var ctrl = this;\r\n\r\n ctrl.addProductListItem = function() {\r\n ctrl.addItemToProductList({historyItem: ctrl.historyListItem});\r\n };\r\n\r\n ctrl.deleteHistoryListItem = function() {\r\n DialogService.openDeleteHistoryItemDialog(ctrl.historyListItem);\r\n };\r\n }\r\n\r\n})();","(function(){\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('historySortPanel', {\r\n templateUrl: 'template/component/historySortPanel.html',\r\n controller: SortPanelController,\r\n bindings: {\r\n categoriesCatalog: '<',\r\n sort: '&'\r\n }\r\n });\r\n\r\n SortPanelController.$inject = ['$scope'];\r\n\r\n function SortPanelController($scope) {\r\n var ctrl = this;\r\n ctrl.sortOptions = [];\r\n\r\n ctrl.$onInit = function() {\r\n initSortOptions();\r\n };\r\n\r\n ctrl.sortList = function(sortOption) {\r\n ctrl.sort({sortFn: sortOption.sort});\r\n };\r\n\r\n function initSortOptions() {\r\n var catalog = ctrl.categoriesCatalog;\r\n var idx = 0;\r\n\r\n catalog.upperCategories.forEach(function (category) {\r\n var pmId = category.pmId;\r\n\r\n ctrl.sortOptions.push({\r\n sort: function(purchasesToSort) {\r\n return sortByCategory(purchasesToSort, catalog, pmId);\r\n },\r\n imageName: catalog.getIconById(pmId),\r\n color: catalog.getColorById(pmId),\r\n order: idx++\r\n });\r\n });\r\n\r\n ctrl.sortOptions.push({\r\n sort: sortByCount,\r\n imageName: 'sortfreq_56m56.png',\r\n order: idx++\r\n });\r\n ctrl.sortOptions.push({\r\n sort: sortByName,\r\n imageName: 'sortalpha_56m56.png',\r\n order: idx++\r\n });\r\n\r\n $scope.$emit('activeSorter', {sort: sortByCount});\r\n }\r\n }\r\n\r\n function sortByName(arrayToSort) {\r\n arrayToSort.sort(function (a, b) {\r\n return a.product.name.localeCompare(b.product.name);\r\n });\r\n return arrayToSort;\r\n }\r\n\r\n function sortByOrder(arrayToSort){\r\n arrayToSort.sort(function (a, b) {\r\n if (parseInt(a.order) < parseInt(b.order)) { return -1; }\r\n if (parseInt(a.order) > parseInt(b.order)) { return 1; }\r\n return 0;\r\n });\r\n return arrayToSort;\r\n }\r\n\r\n function sortByCount(arrayToSort) {\r\n arrayToSort.sort(function (a, b) {\r\n // compare by purchase count\r\n var countDiff = b.count - a.count;\r\n if (countDiff !== 0) {\r\n return countDiff;\r\n }\r\n // if count equal compare by category\r\n else {\r\n if (a.categoryColor > b.categoryColor) {\r\n return 1;\r\n }\r\n else if (a.categoryColor < b.categoryColor) {\r\n return -1;\r\n }\r\n // if category equal compare by name\r\n else {\r\n if (a.product.name > b.product.name) {\r\n return 1;\r\n }\r\n else if (a.product.name < b.product.name) {\r\n return -1;\r\n }\r\n else {\r\n return 0;\r\n }\r\n }\r\n }\r\n });\r\n return arrayToSort;\r\n }\r\n\r\n function sortByCategory(purchasesToSort, categoriesCatalog, sortCategoryPmId) {\r\n var restPurchases = [];\r\n var categoryPurchases = [];\r\n\r\n purchasesToSort.forEach(function (purchase) {\r\n var category = categoriesCatalog.getById(purchase.product.category);\r\n\r\n var upperCategory = categoriesCatalog.getUpperCategory(category);\r\n if (upperCategory && upperCategory.pmId === sortCategoryPmId) {\r\n categoryPurchases.push(purchase);\r\n }\r\n else {\r\n restPurchases.push(purchase);\r\n }\r\n });\r\n\r\n sortByName(categoryPurchases);\r\n sortByOrder(restPurchases);\r\n purchasesToSort = categoryPurchases.concat(restPurchases);\r\n return purchasesToSort;\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .component('userProductEditRow', {\r\n templateUrl: 'template/component/userProductEditRow.html',\r\n controller: UserProductEditRowController,\r\n bindings: {\r\n product: '<',\r\n categoriesCatalog: '<',\r\n setProductCategory: '&',\r\n setProductName: '&',\r\n deleteProduct: '&'\r\n }\r\n });\r\n\r\n function UserProductEditRowController() {\r\n var ctrl = this;\r\n\r\n ctrl.setName = function(name) {\r\n ctrl.setProductName({\r\n product: ctrl.product,\r\n name: name\r\n });\r\n };\r\n\r\n ctrl.removeProduct = function() {\r\n ctrl.deleteProduct({product: ctrl.product});\r\n };\r\n\r\n ctrl.setCategoryOfProduct = function(category) {\r\n ctrl.setProductCategory({\r\n product: ctrl.product,\r\n category: category\r\n });\r\n };\r\n }\r\n})();","(function() {\r\n\t'use strict';\r\n\r\n\tangular\r\n\t\t.module('überliste')\r\n\t\t.component('categoryDropdown', {\r\n templateUrl: 'template/component/categoryDropdown.html',\r\n\t\t\tcontroller: CategoryDropDownController,\r\n\t\t\tbindings: {\r\n \tcategories: '<',\r\n selectedCategory: '<',\r\n\t\t\t\tdisabled: '<',\r\n\t\t\t\tonSelect: '&'\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tfunction CategoryDropDownController() {\r\n\t\t\tvar ctrl = this;\r\n\r\n\t\t\tctrl.select = function (item) {\r\n\t\t\t\tctrl.onSelect({category: item});\r\n\t\t\t};\r\n\t\t}\r\n})();\r\n","(function(){\r\n\t'use strict';\r\n\t\r\n\tangular\r\n\t\t.module('überliste')\r\n\t\t.component('dropdown', {\r\n\t\t\ttemplateUrl: 'template/component/dropdown.html',\r\n\t\t\tbindings: {\r\n\t\t\t\tvalue: '@',\r\n\t\t\t\tlist: '<',\r\n\t\t\t\tdisabled: '<',\r\n\t\t\t\tonItemSelect: '&'\r\n\t\t\t}\r\n\t\t});\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('BroadcastingService', BroadcastingService);\r\n\r\n BroadcastingService.$inject = ['$rootScope'];\r\n\r\n // watch rescans the whole scope in order to find changes\r\n // broadcast just sends notifications to its subscribed listeners\r\n function BroadcastingService($rootScope) {\r\n var BroadcastMessages = {\r\n updateSession: 'update session',\r\n categoriesArrived: 'categories arrived',\r\n listsChanged: 'lists changed',\r\n listItemChanged: 'list item changed',\r\n connectionLost: 'lost connection',\r\n logout: 'logout'\r\n };\r\n\r\n return {\r\n broadcastMessages : BroadcastMessages,\r\n sendBroadcastMessage: sendBroadcastMessage,\r\n addBroadcastListener: addBroadcastListener\r\n };\r\n\r\n function sendBroadcastMessage(message, args) {\r\n $rootScope.$broadcast(message, args);\r\n }\r\n\r\n function addBroadcastListener(scope, message, callback) {\r\n scope.$on(message, callback);\r\n }\r\n }\r\n})();","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('DialogService', DialogService);\r\n\r\n DialogService.$inject = ['$rootScope', 'ngDialog'];\r\n\r\n function DialogService($rootScope, ngDialog) {\r\n return {\r\n addProductList: addProductList,\r\n newProductListItem: newProductListItem,\r\n editProductListItem: editProductListItem,\r\n openDeleteListDialog: openDeleteListDialog,\r\n openShareListDialog: openShareListDialog,\r\n openLoginDialog: openLoginDialog,\r\n openProductsDialog: openProductsDialog,\r\n openSettingsDialog: openSettingsDialog,\r\n openDeleteHistoryItemDialog: openDeleteHistoryItemDialog,\r\n openAlertDialog: openAlertDialog,\r\n // openNewProductDialog: openNewProductDialog,\r\n getOpenDialogs: getOpenDialogs\r\n };\r\n\r\n function addProductList() {\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/productList.html',\r\n controller: 'NewProductListController',\r\n scope: $rootScope.$new()\r\n });\r\n return dialog;\r\n }\r\n\r\n function newProductListItem(productName, userDefined, categoriesCatalog, measurementsCatalog) {\r\n var resolves = {\r\n categoriesCatalog: function () { return categoriesCatalog; },\r\n measurement: function(){ return measurementsCatalog.getById(); },\r\n dialogTitle: function(){ return 'new_list_item_panel.title'; },\r\n draftListItem: function () {\r\n return {\r\n productName: productName,\r\n userDefined: userDefined,\r\n category: categoriesCatalog.defaultCategory,\r\n upperCategory: categoriesCatalog.defaultCategory\r\n };\r\n }\r\n };\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/productListItem.html',\r\n controller: 'EditProductListItemController',\r\n controllerAs: '$ctrl',\r\n resolve: resolves,\r\n $scope: $rootScope.$new()\r\n });\r\n return dialog;\r\n }\r\n\r\n function editProductListItem(item, categoriesCatalog, measurementsCatalog) {\r\n var resolves = {\r\n categoriesCatalog: function () { return categoriesCatalog; },\r\n dialogTitle: function(){ return 'edit_list_item_panel.title'; },\r\n measurement: function(){ return measurementsCatalog.getById(item.measurementPmId); },\r\n draftListItem: function () {\r\n var copyItem = angular.copy(item);\r\n copyItem.category = categoriesCatalog.getById(item.categoryPmId);\r\n copyItem.upperCategory = categoriesCatalog.getUpperCategoryById(item.categoryPmId);\r\n return copyItem;\r\n }\r\n };\r\n\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/productListItem.html',\r\n controller: 'EditProductListItemController',\r\n controllerAs: '$ctrl',\r\n resolve: resolves,\r\n scope: $rootScope.$new()\r\n });\r\n return dialog;\r\n }\r\n\r\n function openDeleteListDialog(list) {\r\n var scope = $rootScope.$new();\r\n scope.listToDelete = list;\r\n\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/deleteProductList.html',\r\n controller: 'DeleteProductListController',\r\n scope: scope\r\n });\r\n return dialog;\r\n }\r\n\r\n function openShareListDialog(list) {\r\n var scope = $rootScope.$new();\r\n scope.activeList = list;\r\n\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/shareList.html',\r\n controller: 'ShareListController',\r\n scope: scope\r\n });\r\n return dialog;\r\n }\r\n\r\n function openLoginDialog(scope) {\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/login.html',\r\n controller: 'LoginController',\r\n scope: scope\r\n });\r\n return dialog;\r\n }\r\n\r\n function openProductsDialog(categoriesCatalog) {\r\n var scope = $rootScope.$new();\r\n scope.categoriesCatalog = categoriesCatalog;\r\n\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/userProducts.html',\r\n className: 'ngdialog-theme-default user-products-dialog',\r\n controller: 'UserProductsController',\r\n scope: scope\r\n });\r\n return dialog;\r\n }\r\n\r\n function openSettingsDialog() {\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/userSettings.html',\r\n controller: 'UserSettingsController',\r\n scope: $rootScope.$new()\r\n });\r\n return dialog;\r\n }\r\n\r\n function openDeleteHistoryItemDialog(itemToDelete) {\r\n var scope = $rootScope.$new();\r\n scope.purchase = itemToDelete;\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/deleteHistoryItem.html',\r\n controller: 'DeleteHistoryItemController',\r\n scope: scope\r\n });\r\n return dialog;\r\n }\r\n\r\n function openAlertDialog(message, type){\r\n var scope = $rootScope.$new();\r\n scope.alertType = type ? type : 'alert-warning';\r\n scope.alertMessage = message;\r\n\r\n var dialog = ngDialog.open({\r\n template: 'template/dialog/alert.html',\r\n scope: scope\r\n });\r\n\r\n return dialog;\r\n }\r\n\r\n function getOpenDialogs(){\r\n return ngDialog.getOpenDialogs();\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular.module('überliste').service('LoginService', LoginService);\r\n\r\n LoginService.$inject = [\r\n '$http',\r\n '$httpParamSerializerJQLike',\r\n '$q',\r\n '$log',\r\n 'Session',\r\n 'ezfb',\r\n 'UserService',\r\n 'UserSettingsService',\r\n ];\r\n\r\n function LoginService(\r\n $http,\r\n $httpParamSerializerJQLike,\r\n $q,\r\n $log,\r\n session,\r\n ezfb,\r\n userService,\r\n userSettingsService\r\n ) {\r\n var config = {\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;',\r\n },\r\n };\r\n\r\n return {\r\n isAuthenticated: isAuthenticated,\r\n login: login,\r\n socialLogin: socialLogin,\r\n logout: logout,\r\n gapiPromise: gapiPromise,\r\n };\r\n\r\n function isAuthenticated() {\r\n var userResult = $q.defer();\r\n var userSettingsResult = $q.defer();\r\n\r\n if (!session.email) {\r\n userService\r\n .get()\r\n .then(function (res) {\r\n if (res.data && res.data.email) {\r\n session.create(res.data.email);\r\n return userSettingsService.get();\r\n } else {\r\n return $q.reject();\r\n }\r\n })\r\n .then(function (res) {\r\n session.update(res.data);\r\n userResult.resolve();\r\n userSettingsResult.resolve();\r\n })\r\n .catch(function () {\r\n userResult.reject();\r\n userSettingsResult.reject();\r\n });\r\n } else {\r\n userResult.resolve();\r\n userSettingsResult.resolve();\r\n }\r\n return $q.all([userResult.promise, userSettingsResult.promise]).catch(function () {\r\n $log.log('Unable to get logged in status.');\r\n return $q.reject();\r\n });\r\n }\r\n\r\n function login(credentials) {\r\n return $http.post('/signin', $httpParamSerializerJQLike(credentials), config).then(function () {\r\n session.create(credentials.email);\r\n userSettingsService.get().then(function (res) {\r\n session.update(res.data);\r\n });\r\n return credentials.email;\r\n });\r\n }\r\n\r\n function socialLogin(providerId) {\r\n if (providerId === 'facebook') {\r\n return fbLogin().then(function (token) {\r\n var data = {\r\n token: token,\r\n language: userService.getUserLanguage(),\r\n };\r\n return $http.post('/signin/facebook', $httpParamSerializerJQLike(data), config);\r\n });\r\n } else {\r\n return $q.reject();\r\n }\r\n }\r\n\r\n function logout(success, error) {\r\n if (ezfb.$ready === true) {\r\n socialLogout();\r\n }\r\n if (window.gapi) {\r\n googleLogout(success, error);\r\n }\r\n $http.post('/signout').then(success, error);\r\n }\r\n function googleLogout(success, error) {\r\n var auth2;\r\n window.gapi.load('auth2', function () {\r\n auth2 = gapi.auth2.getAuthInstance();\r\n auth2.signOut().then(success, error);\r\n });\r\n }\r\n function socialLogout() {\r\n if (ezfb.getAuthResponse()) {\r\n ezfb.logout();\r\n }\r\n }\r\n\r\n /*\r\n * Facebook login\r\n */\r\n function fbLogin() {\r\n return ezfb\r\n .getLoginStatus()\r\n .then(function (response) {\r\n if (response.status === 'connected') {\r\n return $q.when(response);\r\n } else {\r\n return ezfb.login(angular.noop, { scope: 'email' });\r\n }\r\n })\r\n .then(function (response) {\r\n if (response.status === 'connected') {\r\n return $q.when(response.authResponse.accessToken);\r\n } else {\r\n return $q.reject();\r\n }\r\n })\r\n .catch(function (error) {\r\n $log.error('ERROR', error);\r\n });\r\n }\r\n\r\n function gapiPromise() {\r\n var deferred = $.Deferred();\r\n if (gapi) {\r\n deferred.resolve(gapi);\r\n }\r\n return deferred.promise();\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('MeasurementService', MeasurementService);\r\n\r\n MeasurementService.$inject = ['$http', 'UserService'];\r\n\r\n function MeasurementService($http, userService) {\r\n return {\r\n get: get\r\n };\r\n\r\n function get() {\r\n var url = '/api/v1/measurements?language=' + userService.getUserLanguage();\r\n return $http\r\n .get(url)\r\n .then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('MotivationPhraseService', MotivationPhraseService);\r\n\r\n MotivationPhraseService.$inject = ['$http'];\r\n\r\n function MotivationPhraseService($http) {\r\n return {\r\n getRandom: getRandom\r\n };\r\n\r\n function getRandom() {\r\n var url = '/api/v1/motivationphrases/random';\r\n\r\n return $http\r\n \t.get(url)\r\n \t.then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('NavigationService', NavigationService);\r\n\r\n NavigationService.$inject = ['$location', '$window'];\r\n\r\n function NavigationService($location, $window) {\r\n var LOCATION_ALREADY_THERE = 0,\r\n LOCATION_SET = 1;\r\n\r\n return {\r\n navigateToShoppingList: navigateToShoppingList,\r\n navigateToPasswordForget: navigateToPasswordForget,\r\n navigateToHome: navigateToHome,\r\n navigateBack: navigateBack,\r\n navigateToAccountDeleted: navigateToAccountDeleted,\r\n // for testing purposes only\r\n _navigateTo: navigateTo\r\n };\r\n\r\n /**\r\n * Navigates to a new page through location path.\r\n *\r\n * @param path Path to navigate to.\r\n */\r\n function navigateTo(path) {\r\n if ($location.path() === path) {\r\n return LOCATION_ALREADY_THERE;\r\n } else {\r\n var sharingListToken = $location.search().join;\r\n if (sharingListToken) {\r\n $location.path(path).search({ join: sharingListToken });\r\n } else {\r\n $location.path(path).search({});\r\n }\r\n return LOCATION_SET;\r\n }\r\n }\r\n\r\n function navigateToShoppingList() {\r\n navigateTo('/shoppinglist');\r\n }\r\n\r\n function navigateToPasswordForget() {\r\n navigateTo('/account/forgotpassword');\r\n }\r\n\r\n function navigateToHome() {\r\n navigateTo('/');\r\n }\r\n\r\n function navigateBack(){\r\n $window.history.back();\r\n }\r\n\r\n function navigateToAccountDeleted() {\r\n navigateTo('/accountDeleted');\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('NotificationService', NotificationService);\r\n\r\n\tNotificationService.$inject = ['$log'];\r\n\r\n function NotificationService($log) {\r\n var scope;\r\n\r\n return {\r\n resetNotification: resetNotification,\r\n setControllerScope: setControllerScope,\r\n showInfo: info,\r\n showSuccess: success,\r\n showError: error,\r\n showWarn: warn,\r\n addWatch: addWatch\r\n };\r\n\r\n function setControllerScope(controllerScope) {\r\n scope = controllerScope;\r\n }\r\n\r\n function info(msg) {\r\n show('alert-info', msg);\r\n }\r\n\r\n function success(msg) {\r\n show('alert-success', msg);\r\n }\r\n\r\n function error(msg, response) {\r\n show('alert-danger', msg, response);\r\n }\r\n\r\n function warn(msg, response) {\r\n show('alert-warning', msg, response);\r\n }\r\n\r\n function resetNotification() {\r\n scope.showNotification = false;\r\n scope.notificationMsg = '';\r\n scope.notificationClass = null;\r\n }\r\n\r\n function show(notifClass, notifMsg, response) {\r\n if (checkScope()) {\r\n resetNotification();\r\n scope.notificationClass = notifClass;\r\n scope.notificationMsg = notifMsg;\r\n if (response) {\r\n $log.log(response);\r\n }\r\n scope.showNotification = true;\r\n }\r\n\r\n }\r\n\r\n function addWatch(parameter) {\r\n if (checkScope()) {\r\n scope.$watch(parameter, resetNotification);\r\n }\r\n }\r\n\r\n function checkScope() {\r\n if (!scope) {\r\n $log.error('Controller\\'s scope is not defined. Please call function setControllerScope before.');\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n }\r\n\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('ProductCategoryService', ProductCategoryService);\r\n\r\n ProductCategoryService.$inject = ['$http', 'UserService'];\r\n\r\n function ProductCategoryService($http, userService) {\r\n return {\r\n get: get\r\n };\r\n\r\n function get() {\r\n var url = '/api/v1/categories?language=' + userService.getUserLanguage();\r\n return $http\r\n .get(url)\r\n .then(function (result) { return result.data; });\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('ProductListItemService', ProductListItemService);\r\n\r\n ProductListItemService.$inject = ['$http', '$q'];\r\n\r\n function ProductListItemService($http, $q) {\r\n return {\r\n update: update,\r\n createProductListItem: createProductListItem\r\n };\r\n\r\n function update(item) {\r\n var url = '/api/v1/items/' + item.id;\r\n item.updated = Date.now();\r\n\r\n var deferred = $q.defer();\r\n $http.put(url, item).then(function (result) {\r\n deferred.resolve(result.data);\r\n }, function () {\r\n deferred.reject();\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n function createProductListItem(item) {\r\n return function(activeListId) {\r\n return {\r\n productList: activeListId,\r\n product: item.pmId || item.product.pmId,\r\n state: 'NEW',\r\n amount: item.amount ? item.amount : 1.0,\r\n measurement: item.measurement ? item.measurement : null,\r\n description: item.description ? item.description : '',\r\n created: Date.now(),\r\n updated: Date.now()\r\n };\r\n };\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('ProductListService', ProductListService);\r\n\r\n ProductListService.$inject = ['$http', '$q', 'Session'];\r\n\r\n function ProductListService($http, $q, session) {\r\n return {\r\n create: create,\r\n get: get,\r\n update: update,\r\n delete: _delete,\r\n getActiveList: getActiveList,\r\n getProductListItems: getProductListItems,\r\n sync: sync,\r\n share: share,\r\n join: join,\r\n getIndexOfItemWithProductPmId: getIndexOfItemWithProductPmId\r\n };\r\n\r\n /**\r\n * Add a new [empty] product list with given name\r\n *\r\n * @param name\r\n */\r\n function create(name) {\r\n var url = '/api/v1/lists';\r\n\r\n var productList = {\r\n id: null,\r\n name: name,\r\n items: null,\r\n active: true,\r\n users: '',\r\n updated: Date.now()\r\n };\r\n\r\n return $http.post(url, productList);\r\n }\r\n\r\n /**\r\n * Get all user's product lists\r\n *\r\n * @param success\r\n * @param error\r\n */\r\n function get() {\r\n var url = '/api/v1/lists';\r\n\r\n return $http\r\n .get(url)\r\n .then(function (result) {\r\n return result.data;\r\n });\r\n\r\n }\r\n\r\n /**\r\n * Update product list\r\n *\r\n * @param productList\r\n */\r\n function update(productList) {\r\n var url = '/api/v1/lists/' + productList.id;\r\n\r\n productList.updated = Date.now();\r\n return $http.put(url, productList);\r\n }\r\n\r\n /**\r\n * Delete product list\r\n *\r\n * @param productList\r\n * @param success\r\n * @param error\r\n */\r\n function _delete(productList, success, error) {\r\n var url = '/api/v1/lists/' + productList.id;\r\n\r\n productList.updated = Date.now();\r\n $http.delete(url).then(success, error);\r\n }\r\n\r\n /**\r\n * Return the active product list\r\n */\r\n function getActiveList() {\r\n var deferred = $q.defer();\r\n get()\r\n .then(function (lists) {\r\n if (!lists || lists.length === 0) {\r\n deferred.reject();\r\n }\r\n\r\n var activeList = lists.filter(function (list) {\r\n return list.active;\r\n }).pop();\r\n\r\n if(activeList) {\r\n deferred.resolve(activeList);\r\n } else {\r\n deferred.reject();\r\n }\r\n })\r\n .catch(deferred.reject);\r\n\r\n return deferred.promise;\r\n }\r\n\r\n /**\r\n * Load product list items\r\n *\r\n */\r\n function getProductListItems(productList) {\r\n var url = '/api/v1/lists/' + productList.id + '/items';\r\n return $http\r\n .get(url)\r\n .then(function (result) {\r\n return result.data;\r\n });\r\n }\r\n\r\n /**\r\n * Product list synchronization\r\n *\r\n * @param productList List to sync\r\n * @param shouldNotify Server should notify all bound mobile devices about changes.\r\n */\r\n function sync(productList, shouldNotify) {\r\n productList.updated = Date.now();\r\n var request = {\r\n method: 'POST',\r\n url: '/api/v1/lists/sync',\r\n headers: {\r\n 'token': session.token\r\n },\r\n data: {\r\n productListDto: productList,\r\n shouldNotify: shouldNotify,\r\n returnWebDto: true\r\n }\r\n };\r\n\r\n return $http(request).then(function(response) {\r\n if(response.data) {\r\n return response.data.webItems;\r\n } else {\r\n return [];\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Load active product list items\r\n *\r\n * @param success\r\n * @param error\r\n */\r\n function share(activeListId) {\r\n var url = '/api/v1/lists/share?productListId=' + activeListId;\r\n return $http.post(url);\r\n }\r\n\r\n /**\r\n * Load active product list items\r\n *\r\n * @param success\r\n * @param error\r\n */\r\n function join(token) {\r\n var url = '/api/v1/lists/join?token=' + token;\r\n return $http.post(url);\r\n }\r\n\r\n /**\r\n * Finds the index of the item in the items list that has a pmId equal\r\n * to productPmId.\r\n *\r\n * @param items\r\n * @param productPmId\r\n * @returns {*}\r\n */\r\n function getIndexOfItemWithProductPmId(items, productPmId){\r\n return items.findIndex(function(e) {\r\n if(e.product){\r\n return e.product === productPmId || (e.product.pmId && e.product.pmId === productPmId);\r\n }\r\n else if(e.productPmId){\r\n return e.productPmId === productPmId;\r\n }\r\n return false;\r\n });\r\n }\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('ProductService', ProductService);\r\n\r\n ProductService.$inject = ['$http'];\r\n\r\n function ProductService($http) {\r\n var baseUri = '/api/v1/products';\r\n\r\n return {\r\n search: search,\r\n getUserDefined: getUserDefined,\r\n getOwn: getOwn,\r\n getById: getById,\r\n create: create,\r\n update: update,\r\n delete: delete_\r\n };\r\n\r\n function search(searchTerm) {\r\n var url = baseUri + '/search/?searchTerm=' + encodeURI(searchTerm);\r\n\r\n return $http\r\n \t.get(url)\r\n \t.then(function (result) {\r\n \t return result.data;\r\n \t});\r\n }\r\n\r\n function getUserDefined(success, error) {\r\n var url = baseUri + '/user-defined';\r\n $http.get(url).then(success, error);\r\n }\r\n\r\n function getOwn(success, error) {\r\n var url = baseUri + '/own';\r\n $http.get(url).then(success, error);\r\n }\r\n\r\n function getById(id, success, error) {\r\n var url = baseUri + '/' + id;\r\n $http.get(url).then(success, error);\r\n }\r\n\r\n function create(product) {\r\n return $http.post(baseUri, product);\r\n }\r\n\r\n function update(product) {\r\n var url = baseUri + '/' + product.pmId;\r\n return $http.put(url, product);\r\n }\r\n\r\n function delete_(product, success, error) {\r\n var url = baseUri + '/' + product.pmId;\r\n $http.delete(url).then(success, error);\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('PurchaseHistoryEntryService', PurchaseHistoryEntryService);\r\n\r\n PurchaseHistoryEntryService.$inject = ['$http'];\r\n\r\n function PurchaseHistoryEntryService($http) {\r\n var historySize = '30';\r\n\r\n return {\r\n get: get,\r\n deleteByPmId: delete_\r\n };\r\n\r\n function get() {\r\n var url = '/api/v1/purchases?historySize=' + historySize;\r\n return $http.get(url);\r\n }\r\n\r\n function delete_(purchase, success, error) {\r\n var url = '/api/v1/purchases/' + purchase.product.pmId;\r\n $http.delete(url, purchase).then(success, error);\r\n }\r\n\r\n }\r\n})();\r\n","(function() {\r\n\t'use strict';\r\n\r\n\tangular\r\n\t\t.module('überliste')\r\n\t\t.service('Session', Session);\r\n\r\n Session.$inject = ['$translate', 'BroadcastingService'];\r\n\r\n function Session($translate, broadcastingService) {\r\n this.token = Math.random().toString(36).substr(2);\r\n\r\n this.create = function (email) { this.email = email; };\r\n this.destroy = function () { this.email = null; };\r\n\r\n this.update = function (settings) {\r\n this.settings = settings;\r\n $translate.use(settings.language);\r\n broadcastingService.sendBroadcastMessage(broadcastingService.broadcastMessages.updateSession);\r\n };\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('UserService', UserService);\r\n\r\n UserService.$inject = ['$http', '$translate'];\r\n\r\n function UserService($http, $translate) {\r\n var url = '/api/v1/users';\r\n\r\n return {\r\n create: create,\r\n update: update,\r\n get: get,\r\n getLoginStatus: getLoginStatus,\r\n getUserLanguage: getLanguage,\r\n changePassword: changePassword,\r\n resetPassword: resetPassword,\r\n deleteUser: deleteUser,\r\n };\r\n\r\n function create(email, success, error) {\r\n var user = {\r\n email: email,\r\n language: getLanguage(),\r\n createDefaults: true\r\n };\r\n\r\n $http.post(url + '/signup', user).then(success, error);\r\n }\r\n\r\n function update(user) {\r\n return $http.put(url, user);\r\n }\r\n\r\n function get() {\r\n return $http.get(url);\r\n }\r\n\r\n function getLoginStatus(success, error) {\r\n $http.get(url + '/loginstatus').then(success, error);\r\n }\r\n\r\n function getLanguage() {\r\n return $translate.use() ? $translate.use() : $translate.proposedLanguage();\r\n }\r\n\r\n function changePassword(oldPassword, newPassword, success, error) {\r\n $http.put(url + '/changepassword?oldPassword=' + encodeURIComponent(oldPassword) + '&newPassword=' + encodeURIComponent(newPassword)).then(success, error);\r\n }\r\n\r\n function resetPassword(email, success, error) {\r\n $http.post(url + '/resetpassword?email=' + email).then(success, error);\r\n }\r\n function deleteUser(password, success, error){\r\n $http.delete(url + '/deleteuser?password=' +encodeURIComponent(password)).then(success,error);\r\n }\r\n\r\n }\r\n})();\r\n","(function () {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('UserSettingsService', UserSettingsService);\r\n\r\n UserSettingsService.$inject = ['$http', '$q', '$rootScope'];\r\n\r\n function UserSettingsService($http, $q, $rootScope) {\r\n var url = '/api/v1/usersettings';\r\n var settings = {};\r\n var deferred = null;\r\n\r\n return {\r\n get: get,\r\n getSettings: getSettings,\r\n update: update,\r\n setActiveList: setActiveList\r\n };\r\n\r\n function get() {\r\n deferred = $q.defer();\r\n return $http\r\n .get(url)\r\n .then(function(response) {\r\n settings = response.data;\r\n deferred.resolve();\r\n $rootScope.$emit('userSettingsChanged', settings);\r\n return response;\r\n });\r\n }\r\n\r\n // FIXME: TEST!!!!!\r\n function getSettings() {\r\n if(!deferred) { get(); }\r\n return deferred.promise.then(function(){return settings;});\r\n }\r\n\r\n function update(userSettings) {\r\n return $http\r\n .put(url, userSettings)\r\n .then(function(response) {\r\n settings = userSettings;\r\n $rootScope.$emit('userSettingsChanged', settings);\r\n return response;\r\n });\r\n\r\n }\r\n\r\n /**\r\n * Set active product list\r\n *\r\n * @param productList\r\n */\r\n function setActiveList(productList) {\r\n return $http\r\n .put(url + '/setactivelist', productList)\r\n .then(function(response) {\r\n settings.activeProductListId = productList.id;\r\n $rootScope.$emit('userSettingsChanged', settings);\r\n return response;\r\n });\r\n }\r\n }\r\n})();\r\n","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('WebSocketService', WebSocketService);\r\n\r\n WebSocketService.$inject = ['$log', '$rootScope', '$websocket', 'Session', '$timeout'];\r\n\r\n function WebSocketService($log, $rootScope, $websocket, Session, $timeout) {\r\n var dataStream = null;\r\n\r\n this.closeWebSocket = function() {\r\n if(dataStream) {\r\n $log.info('Closing socket connection...');\r\n dataStream.close(true);\r\n }\r\n };\r\n\r\n this.connectWebSocket = function() {\r\n var self = this;\r\n if(dataStream) {\r\n $log.info('Closing old socket connection');\r\n dataStream.close(true);\r\n }\r\n\r\n $log.info('Connecting to web-socket...');\r\n dataStream = $websocket(\r\n url('/websocket'));\r\n \r\n dataStream.send(angular.toJson({\r\n token: Session.token,\r\n os: 'web',\r\n user: Session.email\r\n }));\r\n\r\n dataStream.onMessage(function (message) {\r\n if (message.data) {\r\n var msg = angular.fromJson(message.data);\r\n\r\n $log.log('Got WS notification: ', msg);\r\n\r\n switch (msg.type) {\r\n case 'CREATE':\r\n onCreate(msg.subject);\r\n break;\r\n case 'UPDATE':\r\n onUpdate(msg);\r\n break;\r\n case 'DELETE':\r\n onDelete(msg);\r\n break;\r\n default:\r\n $log.error('Unknown ws message type', msg.type);\r\n break;\r\n }\r\n }\r\n });\r\n\r\n dataStream.onOpen(function () { $log.info('Connected to web-socket'); });\r\n\r\n dataStream.onClose(function () {\r\n $rootScope.$emit('ws:onClose');\r\n $log.info('Closing web-socket');\r\n if(dataStream.readyState === 3){\r\n $timeout(function(){\r\n self.connectWebSocket();\r\n },20000);\r\n }\r\n });\r\n\r\n dataStream.onError(function () {\r\n $log.error('Web-socket connection error');\r\n $rootScope.$emit('ws:onClose');\r\n });\r\n };\r\n\r\n function url(s) {\r\n var l = window.location;\r\n return ((l.protocol === 'https:') ? 'wss://' : 'ws://') + l.host + s;\r\n }\r\n\r\n function onCreate(subject) {\r\n switch (subject) {\r\n case 'PRODUCT':\r\n $rootScope.$emit('ws:product:create');\r\n break;\r\n case 'PRODUCT_LIST':\r\n $rootScope.$emit('ws:productlist:create');\r\n break;\r\n case 'PRODUCT_LIST_ITEM':\r\n $rootScope.$emit('ws:productlistitem:create');\r\n break;\r\n }\r\n }\r\n\r\n function onUpdate(msg) {\r\n switch (msg.subject) {\r\n case 'PRODUCT':\r\n $rootScope.$emit('ws:product:update');\r\n break;\r\n case 'PRODUCT_LIST':\r\n $rootScope.$emit('ws:productlist:update', msg.data);\r\n break;\r\n case 'PRODUCT_LIST_ITEM':\r\n $rootScope.$emit('ws:productlistitem:update', msg.data);\r\n break;\r\n }\r\n }\r\n\r\n function onDelete(msg) {\r\n switch (msg.subject) {\r\n case 'PRODUCT':\r\n $rootScope.$emit('ws:product:delete', msg.data.pmId);\r\n break;\r\n case 'PRODUCT_LIST':\r\n $rootScope.$emit('ws:productlist:delete', msg.data.id);\r\n break;\r\n case 'PURCHASE_HISTORY_ENTRY':\r\n $rootScope.$emit('ws:historyentry:delete', msg.data);\r\n break;\r\n default:\r\n // triggers lists and history reload\r\n $rootScope.$emit('ws:productlist:create');\r\n }\r\n }\r\n }\r\n})();","(function() {\r\n 'use strict';\r\n\r\n angular\r\n .module('überliste')\r\n .service('ListUtil', ListUtil);\r\n\r\n ListUtil.$inject = ['ProductListService'];\r\n\r\n function ListUtil(ProductListService) {\r\n var listUtil = this;\r\n\r\n listUtil.sync = function(oldList, newList, itemToId, updateItem, sortFn, insertFn) {\r\n var i = oldList.length;\r\n while(i--) {\r\n var oldItem = oldList[i];\r\n var idx = listUtil.getIndexOfItemWithProductPmId(newList, itemToId(oldItem));\r\n\r\n if(idx < 0) {\r\n oldList.splice(i, 1);\r\n } else {\r\n var newItem = newList[idx];\r\n updateItem(oldItem, newItem);\r\n }\r\n }\r\n\r\n sortFn(oldList, newList);\r\n newList.forEach(function(newItem, newItemIndex) {\r\n insertFn(oldList, newItem, newItemIndex);\r\n });\r\n };\r\n\r\n // FIXME\r\n listUtil.getIndexOfItemWithProductPmId = ProductListService.getIndexOfItemWithProductPmId;\r\n }\r\n})();"]}